8.IMX6ULL LINUX驱动之蜂鸣器

326 阅读1分钟

一、蜂鸣器驱动说明

蜂鸣器与GPIO点灯程序相差无几,本节实验重点编写代码,回顾通过修改设备树添加pinctrl与gpio结点信息来快速驱动Buzzer。

由原理图如下,想要驱动buzzer,使用GPIO1_19引脚的输出,使用高电平驱动蜂鸣器,使得三极管导通,2边通到GND。

4_buzzer.png

二、程序

二话不说,有了前面的经验,现在gpio驱动buzzer可以说是小case。

1、添加设备树结点信息

注意,除此之外还要注意,不能有重复的IO配置。

/{
        buzzer{
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "pintitus,buzzer";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_buzzer>;
        buzzer-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
        status = "okay";
        };
};
&iomuxc {
    pinctrl-names = "default";
    imx6ul-evk {
        pinctrl_buzzer:buzzergrp{
            fsl,pins = <
                MX6UL_PAD_UART1_RTS_B__GPIO1_IO19   0x10b0
            >;
        };
    };
};

2.驱动程序

/*设备结构体*/
struct gpio_buzzer{
    dev_t   devid;        /*设备号*/
    int     major;        /*主设备号*/
    int     minor;        /*次设备号*/
    struct  cdev cdev;    /*字符设备*/
    struct class *class;  /*设备的类*/
    struct device *device;/*设备*/
    struct device_node *nd;/*设备结点*/
    
    int    buzzer_gpio;      /*IO的编号*/
    char   name[13];         /*IO申请名称*/ 
};
struct gpio_buzzer buzzer;
/*
    注册与注销设备
*/
static int __init buzzer_init(void){
    int ret = 0;
​
    /*  注册字符设备    */
    if(buzzer.major){
        buzzer.devid = MKDEV(buzzer.major , 0);
        ret = register_chrdev_region(buzzer.devid , BUZZER_CNT , BUZZER_NAME);
    }else{
        ret = alloc_chrdev_region(&buzzer.devid , 0 , BUZZER_CNT , BUZZER_NAME);
        buzzer.major = MAJOR(buzzer.devid);
        buzzer.minor = MINOR(buzzer.devid);
    }
    if(ret < 0){
        goto failed_devid;
    }
    printk("buzzer.major = %d , buzzer.minor = %d \r\n" ,buzzer.major , buzzer.minor );
​
    /*  添加字符设备  */
    buzzer.cdev.owner = THIS_MODULE;
    cdev_init( &buzzer.cdev , &buzzer_fops);
    ret = cdev_add(&buzzer.cdev , buzzer.devid , BUZZER_CNT);
    if(ret < 0){
        goto failed_cdev;
    }
​
    /*  自动创建设备结点    */
    /*  创建设备的类    */
    buzzer.class = class_create(THIS_MODULE , BUZZER_NAME);
    if(IS_ERR(buzzer.class)){
        ret = PTR_ERR(buzzer.class);
        goto failed_class;
    }
    /*    创建设备    */
    buzzer.device = device_create(buzzer.class , NULL , buzzer.devid , NULL ,BUZZER_NAME);
    if(IS_ERR(buzzer.device)){
        ret = PTR_ERR(buzzer.device);
        goto failed_device;
    }
    
​
    /*  1.获取设备结点    */
    buzzer.nd = of_find_node_by_path("/buzzer");
    if(buzzer.nd == NULL){
        ret = -EINVAL;
        goto failed_findnd;
    }
    
    /*  2.获取buzzer对应的GPIO   */
    buzzer.buzzer_gpio= of_get_named_gpio(buzzer.nd , "buzzer-gpios" , 0);
    if(buzzer.buzzer_gpio < 0){
        printk("buzzer.buzzer_gpio < 0\r\n");
        ret = -EINVAL;
        goto failed_findnd;
    }
    printk("buzzer.buzzer_gpio  = %d\r\n" ,buzzer.buzzer_gpio );
​
    /*  3.申请IO    */
    buzzer.name[0]="------------";
    sprintf(buzzer.name, "buzzer-gpios");
    printk("%s\r\n" , buzzer.name);
    ret = gpio_request(buzzer.buzzer_gpio, buzzer.name);
    if (ret) {
        printk("failed to request GPIO for buzzer\n");
        ret = -EINVAL;
        goto failed_findnd;
    }
    
    /*  4.使用IO,设置为输出  */
    ret = gpio_direction_output(buzzer.buzzer_gpio ,0 );
    if(ret < 0){
        goto failed_setio;
    }
    /*  5.输出电平 ,buzzer */
    gpio_set_value(buzzer.buzzer_gpio , 0);
​
    return 0;
​
​
failed_setio:
    gpio_free(buzzer.buzzer_gpio);
    printk("failed_request\r\n");
failed_findnd:
    device_destroy(buzzer.class , buzzer.devid);
    printk("failed_findnd\r\n");
failed_device:
    class_destroy(buzzer.class);
    printk("failed_device\r\n");
failed_class:
    cdev_del(&buzzer.cdev);
    printk("failed_class\r\n");
failed_cdev:
    unregister_chrdev_region(buzzer.devid , BUZZER_CNT);
    printk("failed_cdev\r\n");
failed_devid:
    return ret;
}
static void __exit buzzer_exit(void){
    cdev_del(&buzzer.cdev);
    unregister_chrdev_region(buzzer.devid , BUZZER_CNT);
​
    device_destroy(buzzer.class , buzzer.devid);
    class_destroy(buzzer.class);
​
    /*IO释放*/
    gpio_free(buzzer.buzzer_gpio);
}
module_init(buzzer_init);
module_exit(buzzer_exit);
MODULE_LICENSE("GPL");
​

\