基于ARM-contexA9蜂鸣器驱动开发

简介: 基于ARM-contexA9蜂鸣器驱动开发

上次,我们写了一个LED的驱动程序,这一节,我们只需稍微改动一下就可以实现蜂鸣器的驱动,让我们来看看吧。

    还是跟之前一样,先找电路图,找到电路板上对应的引脚和相关联的寄存器。

    1、看电路图0.gif

    (1)蜂鸣器接口位于电路板的底板,看电路图可知道是高电平有效。

0.png

  (2)相对应的找到核心板的接口。由此可知,我们的蜂鸣器是GPD0_0

0.png

 接下来找数据手册,找到对应的寄存器,然后配置它就可以了。

 2、查数据手册,找到相关的寄存器,并配置0.gif

(1)找到GPD0CON,地址是0x114000A0,我们需要配置GPD0CON(0)为输出状态。也就是写0x1这个值到这个寄存器。

640.jpg

(2)找到GPD0DAT这个寄存器,用于配置蜂鸣器的高低电平,物理地址是0x114000A4,刚好与上一个差4个字节的偏移

我们只要对这个寄存器写1和写0,那么蜂鸣器就可以叫起来了,哈哈。是不是很简单?0.gif

640.jpg

3、开始写驱动程序。


[plain] view plain copy print?

#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/fs.h>  
#include <linux/io.h>  
#include <asm/uaccess.h>  
#include <asm/irq.h>  
#include <asm/io.h>  
#define DEV_NAME    "test-dev"  
//定义蜂鸣器配置IO的地址   
#define GPD0CON  0x114000A0  
volatile unsigned long *bell_config = NULL ;   
volatile unsigned long *bell_dat = NULL ;   
int bell_open(struct inode *inode, struct file *filp)  
{  
    printk("bell_open\n");  
    //清寄存器   
    *bell_config &= ~(0xf);  
    //设置io为输出   
    *bell_config |= (0x1);  
    return 0;  
}  
int bell_close(struct inode *inode, struct file *filp)  
{  
    printk("bell_close\n");  
    //关闭蜂鸣器   
    *bell_dat &= ~0x1 ;  
    return 0;  
}  
long bell_ioctl(struct file *filp, unsigned int request, unsigned long arg)  
{  
    //控制蜂鸣器的状态   
    switch(request)  
    {  
        case 0:  
            printk(KERN_EMERG"bell on\n");  
            *bell_dat |= 0x1 ;  
            break;  
        case 1:  
            printk(KERN_EMERG"bell off\n");  
            *bell_dat &=~0x1 ;  
            break;  
    }  
    return 0 ;  
}  
struct file_operations fops = {  
    .owner = THIS_MODULE ,  
    .open = bell_open,  
    .release = bell_close,  
    .unlocked_ioctl = bell_ioctl,  
};  
int major ;  
int test_init(void)  
{  
    printk("bell_init\n");  
    //注册设备   
    major = register_chrdev(major, DEV_NAME, &fops);  
    //映射IO   
    bell_config = (volatile unsigned long *)ioremap(GPD0CON , 16);  
    //加4个字节偏移到GP0DAT顺便映射该物理地址   
    bell_dat = bell_config + 1 ;      
    return 0;  
}  
void test_exit(void)  
{  
    printk("bell_exit\n");  
    //解除注册   
    unregister_chrdev(major, DEV_NAME);  
    //取消映射   
    iounmap(bell_config);  
}  
module_init(test_init);  
module_exit(test_exit);  
MODULE_LICENSE("GPL");  
MODULE_AUTHOR("Y.X.YANG");  
MODULE_VERSION("2016.1.16");</span>  

4、写测试程序


[plain] view plain copy print?

#include <stdio.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
int main(int argc, char **argv)  
{  
    int fd;  
    //打开设备   
    fd = open("/dev/test-dev",O_RDWR) ;  
    if(-1 == fd)  
    {  
        printf("open fair!\n");  
        return -1 ;  
    }  
    while(1){  
        //打开蜂鸣器   
        ioctl(fd,1);  
        sleep(1);  
        //关闭蜂鸣器   
        ioctl(fd,0);  
        sleep(1);  
    }  
    return 0;  
}</span>  

5、编写makefile


[plain] view plain copy print?

obj-m   += bell.o  
ROOTFS = /disk/A9/filesystem  
KERNEL = /disk/A9/linux-3.5/  
all:  
    make -C $(KERNEL) M=`pwd` modules  
clean:  
    make -C $(KERNEL) M=`pwd` clean  
    rm -rf my_bell  
install:  
    make -C $(KERNEL) M=`pwd` modules_install INSTALL_MOD_PATH=$(ROOTFS)  
my_bell:  
    arm-linux-gcc my_bell.c -o my_bell  
</span>  

6、编译

640.jpg

7、查看设备主设备号,这里就省略图了,我们得到主设备号是250  cat /proc/devices  

8、创建设备节点  mknod  /dev/test-dev  c   250  0

9、开始执行

640.jpg

由于蜂鸣器的现象没有实质的效果展示,只能通过终端打印,如有兴趣,自己去尝试,用其它板子也可以,就照着我这个方法写驱动,一定成功的!

目录
相关文章
|
7月前
|
缓存 C++
基于ARM-contexA9-蜂鸣器pwm驱动开发
基于ARM-contexA9-蜂鸣器pwm驱动开发
52 0