日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

驱动程序实例(三):蜂鸣器驱动程序(misc类设备驱动框架)

發(fā)布時間:2023/12/19 综合教程 28 生活家
生活随笔 收集整理的這篇文章主要介紹了 驱动程序实例(三):蜂鸣器驱动程序(misc类设备驱动框架) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

結(jié)合之前對Linux內(nèi)核的misc類設(shè)備驅(qū)動框架的分析 ,本文將編寫基于misc類設(shè)備驅(qū)動框架的Buzzer設(shè)備的實例代碼并對其進行分析。

misc類設(shè)備驅(qū)動框架的分析,詳見Linux字符設(shè)備驅(qū)動框架(三):Linux內(nèi)核的misc類設(shè)備驅(qū)動框架。

硬件接口:

  CPU:s5pv210;

  Buzzer的GPIO:GPIO_D0_2 ;

  LED的工作方式:低電平停,高電平響。

P.S.:無源蜂鳴器聲音頻率可控,一般采用PWM控制;有源蜂鳴器用普通IO控制方式即可。

1. 驅(qū)動程序分析

本代碼取自,九鼎科技x210開發(fā)板的BSP。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h>

#define DEVICE_NAME     "buzzer"

#define PWM_IOCTL_SET_FREQ        1
#define PWM_IOCTL_STOP            0

static struct semaphore lock;

// TCFG0在Uboot中設(shè)置,這里不再重復(fù)設(shè)置
// Timer0輸入頻率Finput=pclk/(prescaler1+1)/MUX1
//                     =66M/16/16
// TCFG0 = tcnt = (pclk/16/16)/freq;
// PWM0輸出頻率Foutput =Finput/TCFG0= freq
static void PWM_Set_Freq( unsigned long freq )
{
    unsigned long tcon;
    unsigned long tcnt;
    unsigned long tcfg1;

    struct clk *clk_p;
    unsigned long pclk;
    
    //設(shè)置GPD0_2為PWM輸出
    s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(2));

    tcon = __raw_readl(S3C2410_TCON);
    tcfg1 = __raw_readl(S3C2410_TCFG1);

    //mux = 1/16
    tcfg1 &= ~(0xf<<8);
    tcfg1 |= (0x4<<8);
    __raw_writel(tcfg1, S3C2410_TCFG1);
    
    clk_p = clk_get(NULL, "pclk");
    pclk  = clk_get_rate(clk_p);

    tcnt  = (pclk/16/16)/freq;
    
    __raw_writel(tcnt, S3C2410_TCNTB(2));
    __raw_writel(tcnt/2, S3C2410_TCMPB(2));//占空比為50%

    tcon &= ~(0xf<<12);
    tcon |= (0xb<<12);        //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
    __raw_writel(tcon, S3C2410_TCON);
    
    tcon &= ~(2<<12);         //clear manual update bit
    __raw_writel(tcon, S3C2410_TCON);
}

void PWM_Stop( void )
{
    //將GPD0_2設(shè)置為input
    s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(0));    
}

static int x210_pwm_open(struct inode *inode, struct file *file)
{
    if (!down_trylock(&lock))//上鎖
        return 0;
    else
        return -EBUSY;
    
}

static int x210_pwm_close(struct inode *inode, struct file *file)
{
    up(&lock);//解鎖
    return 0;
}

// PWM:GPF14->PWM0
static int x210_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd) 
    {
        case PWM_IOCTL_SET_FREQ:
            printk("PWM_IOCTL_SET_FREQ:
");
            if (arg == 0)
                return -EINVAL;
            PWM_Set_Freq(arg);
            break;

        case PWM_IOCTL_STOP:
        default:
            printk("PWM_IOCTL_STOP:
");
            PWM_Stop();
            break;
    }
    return 0;
}

//buzzer設(shè)備操作集
static struct file_operations dev_fops = {
    .owner   =   THIS_MODULE,
    .open    =   x210_pwm_open,
    .release =   x210_pwm_close, 
    .ioctl   =   x210_pwm_ioctl,
};

//misc類設(shè)備信息初始化
static struct miscdevice misc = 
{
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

//buzzer設(shè)備注冊
static int __init dev_init(void)
{
    int ret;

    init_MUTEX(&lock);           //上鎖
    ret = misc_register(&misc);  //將buzzer注冊到misc類下
    
    /* GPD0_2 (PWMTOUT2) */
    ret =
gpio_request(S5PV210_GPD0(2), "GPD0"); //申請GPIO if(ret) printk("buzzer-x210: request gpio GPD0(2) fail"); s3c_gpio_setpull(S5PV210_GPD0(2), S3C_GPIO_PULL_UP);//將GPIO_D0_2設(shè)置為上拉 s3c_gpio_cfgpin(S5PV210_GPD0(2), S3C_GPIO_SFN(1)); //將GPIO_D0_2設(shè)置為輸出模式 gpio_set_value(S5PV210_GPD0(2), 0); //將GPIO_D0_2設(shè)置為低電平 printk ("x210 "DEVICE_NAME" initialized "); return ret; } //buzzer設(shè)備注銷 static void __exit dev_exit(void) { init_MUTEX_LOCKED(&lock); //解鎖 gpio_free(S5PV210_GPD0(2));//釋放GPIO misc_deregister(&misc); //注銷buzzer設(shè)備 } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("www.9tripod.com"); MODULE_DESCRIPTION("x210 PWM Driver");

2. 測試

Buzzer驅(qū)動模塊被裝載進內(nèi)核之后,可運行如下應(yīng)用程序測試該驅(qū)動是否工作正常。若運行應(yīng)用程序之后,蜂鳴器連響3聲,則說明驅(qū)動工作正常。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>

#define FILE_BUZZER "/dev/buzzer"

#define PWM_IOCTL_SET_FREQ        1
#define PWM_IOCTL_STOP            0

int main(void)
{
    int fd = -1;
    int i = 0;
    
    fd = open(FILE_BUZZER, O_RDWR);
    if (fd < 0)
    {
        printf("open buzzer file error.
");
        return -1;
    }
    
    for (i=0; i<3; i++)
    {
        ioctl(fd, PWM_IOCTL_SET_FREQ, 10000);
        sleep(3);
        ioctl(fd, PWM_IOCTL_STOP);
        sleep(3);
    }
    
    return 0;
}

總結(jié)

以上是生活随笔為你收集整理的驱动程序实例(三):蜂鸣器驱动程序(misc类设备驱动框架)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。