(四)控制蜂鸣器

四、控制蜂鸣器

1.1、控制原理

蜂鸣器使用的是有缘蜂鸣器,所以其实也只需要设置引脚的高低电平即可驱动蜂鸣器。
最终原理还是驱动GPIO,参考上一篇的GPIO,修改对应的设备树引脚即可。

1.2、设备树添加GPIO节点

在对应的设备树pinctrl节点上添加驱动的GPIO信息。

pinctrl_beep:beepgrp{
			fsl,pins = <
				MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01    0x10b0
			>;
		};

之后在根/下面添加自己的gpio节点

gpiobeep{
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-gpiobeep";
    	pinctrl-name = "default";
		pinctrl-0=<&pinctrl_beep>;
		beep-gpio = 	< &gpio5 1 GPIO_ACTIVE_LOW >;	//低电平点亮 
		status = "okay";
	};

1.3、驱动代码

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>


#define BEEP_NAME   "beep"
#define BEEP_CT     1   

#define BEEP_ON     1
#define BEEP_OFF    0   


struct beep_struct{
    int major;
    int minor;
    dev_t devid;
    struct cdev cdev;
    struct class *class;
    struct device *device;
    struct device_node *nd;
    int gpio_num;

};

struct beep_struct beep_dev;


static int beep_open(struct inode *inode, struct file *file)
{
    file->private_data = &beep_dev;
    return 0;
}

static int beep_release(struct inode *inode, struct file *file)
{
	return 0;
}

ssize_t beep_write(struct file *file, const char __user *data,size_t len, loff_t *ppos)
{
    struct beep_struct *dev = file->private_data;
    unsigned char data_tmp = 0;
    int ret = 0;

    ret = copy_from_user(&data_tmp,data,1);

    if(ret < 0){
        printk("write data err\r\n");
        return -1;
    }

    if(data_tmp == BEEP_ON){
        gpio_set_value(dev->gpio_num,0);
    }
    else if(data_tmp == BEEP_OFF){
            gpio_set_value(dev->gpio_num,1);
    }

    return 0;
}

ssize_t beep_read(struct file *file, char __user * buf,size_t len, loff_t * ppos)
{
    return 0;
}


static const struct file_operations beep_fileope = {
    .owner      = THIS_MODULE,
    .open       = beep_open,
    .write      = beep_write,
    .read       = beep_read,
    .release    = beep_release,
};


static int beep_gpio_init(void)
{
    int ret = 0;
    beep_dev.nd = of_find_node_by_path("/gpiobeep");

    if(beep_dev.nd == NULL){
        printk("not find node\r\n");
        return -1;
    }

    printk("get node\r\n");

    beep_dev.gpio_num = of_get_named_gpio(beep_dev.nd,"beep-gpio",0);

    if(beep_dev.gpio_num < 0){
        printk("not get gpio\r\n");
        return -2;
    }

    printk("gpio num:%d\r\n",beep_dev.gpio_num);

    ret = gpio_direction_output(beep_dev.gpio_num,1);
    if(ret < 0){
        printk("gpio set err\r\n");
        return -3;
    }

    
    return 0;

}

static int __init beep_init(void)
{
    int ret = 0;

    ret = beep_gpio_init();
    if(ret < 0){
        printk("beep gpio init err\r\n");
        goto CHRDEV_ERR;
    }

    beep_dev.major = 0;
    
    if(beep_dev.major){
        beep_dev.devid = MKDEV(beep_dev.major,0);
        ret = register_chrdev_region(beep_dev.devid,BEEP_CT,BEEP_NAME);
    }
    else{
        ret = alloc_chrdev_region(&beep_dev.devid,0,BEEP_CT, BEEP_NAME);
        beep_dev.major = MAJOR(beep_dev.devid);
    }

    if(ret < 0){
        printk("chrdev err\r\n");
        goto CHRDEV_ERR;
    }
    printk("beep major:%#x\r\n",beep_dev.major);

    beep_dev.cdev.owner = THIS_MODULE;

    cdev_init(&beep_dev.cdev, &beep_fileope);
	ret = cdev_add(&beep_dev.cdev, beep_dev.devid, BEEP_CT);

    if(ret < 0){
        printk("cdev err\r\n");
        goto CDEV_ERR;
    }

    beep_dev.class = class_create(THIS_MODULE, "bsr");
	if (IS_ERR(beep_dev.class)) {
		printk("class create err\r\n");
		ret = PTR_ERR(beep_dev.class);
		goto CLASS_ERR;
	}


    beep_dev.device = device_create(beep_dev.class,NULL,beep_dev.devid,NULL,BEEP_NAME);

    if (IS_ERR(beep_dev.device)) {
		printk("device create err\r\n");
		ret = PTR_ERR(beep_dev.device);
		goto DEVICE_ERR;
	}

    return 0;

DEVICE_ERR:
    class_destroy(beep_dev.class);

CLASS_ERR:
    cdev_del(&beep_dev.cdev);

CDEV_ERR:
    unregister_chrdev_region(beep_dev.devid,BEEP_CT);

CHRDEV_ERR:
    return ret;
}

static void __exit beep_exit(void)
{
    device_destroy(beep_dev.class,beep_dev.devid);
    class_destroy(beep_dev.class);
    cdev_del(&beep_dev.cdev);
    unregister_chrdev_region(beep_dev.devid,BEEP_CT);
}

module_init(beep_init);
module_exit(beep_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("gale");


发布了29 篇原创文章 · 获赞 0 · 访问量 431

猜你喜欢

转载自blog.csdn.net/weixin_42547950/article/details/104201439