linux驱动:(8)实战:用杂项设备完成蜂鸣器驱动

最终效果是使用杂项设备完成一个蜂鸣器驱动,然后在应用程序中传入参数1为打开蜂鸣器,0为关闭蜂鸣器

步骤

  1. 新建一个beep.c和Makefile和app.c,放在一个文件夹中
  2. 查找蜂鸣器原理图对应的管脚名称,然后在参考手册中找到对应的引脚为gpio几,然后再找gpio几的数据寄存器的地址
  3. 编写beep.c蜂鸣器驱动代码,我这里拿第六章中的misc代码来修改,只需要加一个io.h库,然后定义对应GPIO几的地址,并定义一个虚拟地址全局变量,在init函数添加申请虚拟地址,exit函数释放虚拟地址,write函数读取应用传进来的数据并作出判断来修改虚拟地址
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/miscdevice.h>
    #include <linux/fs.h>
    #include <linux/uaccess.h>
    #include <linux/io.h>
    
    #define GPIO5_DR 0x020AC00
    unsigned int *vir_gpio5_dr;
    
    int misc_open(struct inode * inode,struct file * file)
    {
        printk("hello misc_open\n");
        return 0;
    }
    int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
    {
        char kbuf[64] = "heheh";
        if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
        {
            printk("copy_to_user error\n");
            return -1;
        }
        return 0;
    }
    int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
    {
        char kbuf[64] = {0};
        if( copy_from_user(kbuf,ubuf,size)!=0)
        {
            printk("copy_from_user error\n");
            return -1;
        }
        printk("kbuf is %s\n",kbuf);
        if(kbuf[0]==1)
        {
            *vir_gpio5_dr |= (1<<1);
        }
        else if
        {
            *vir_gpio5_dr &= ~(1<<1);
        }
        return 0;
    }
    struct const file_operation misc_fops = {
        .owner = THIS_MODULE,
        .open = misc_open,
        .write= misc_write,
        .read = misc_read
    };
    struct miscdevice misc_dev = {
        .minor = MISC_DYNAMIC_MINOR,//动态分配
        .name ="hellomisc",//设备节点名字
        .fops =&misc_fops 
    };
     
    static int misc_init(void)
    {
        int ret;
        ret = misc_register(&misc_dev);
        if(ret<0)
        {
            printk("misc registe is error\n");
            return -1;
        }
        vir_gpio5_dr = ioremap(GPIO5_DR,4);
        if(vir_gpio5_dr ==NULL)
        {
            printk("GPIO5_DR ioremap error\n");
            return -EBUSY;
        }
        printk("GPIO5_DR ioremap ok\n");
        return 0;
    }
     
    static void misc_exit(void)
    {
        misc_deregister(&misc_dev);
        iounmap(vir_gpio5_dr );
        printk("misc goodbye");
    }
     
    module_init(misc_init);
    module_exit(misc_exit);
     
    MODULE_LICENSE("GPL");
  4. 编写Makefile编译蜂鸣器驱动模块代码,也是第六章的代码,只是将参数写入buf然后写入驱动
    obj-m +=beep.o
    KDIR:=自己的linux内核源码根目录路径
    PWD?=$(shell pwd)
    all:
        make -C $(KDIR) M=$(PWD) modules
  5. 编写app.c应用程序代码
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
     
    int main(int argc, char * argv)
    {
        int fd;
        char buf[64] = {0};
        fd = open("/dev/hellomisc",O_RDWR);
        if (fd<0)
        {
            perror("open error\n");
            return fd;
        }
        buf[0] = atoi(argv[1]);
        write(fd,buf,sizeof(buf));
        printf("buf is %s\n",buf);
        close(fd);
        return 0;
    }
  6. 配置arm环境和交叉编译环境
  7. 将驱动编译成模块,和将应用程序编译成可执行文件,两者放入开发板中
  8. 加载驱动,查看是否加载成功,insmod beep.ko
  9. 运行可执行文件测试驱动,打开蜂鸣器为./app 1,关闭蜂鸣器为./app 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值