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

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

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

     1、看电路图生气

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

基于ARM-contexA9蜂鸣器驱动开发_第1张图片

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


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

  2、查数据手册,找到相关的寄存器,并配置生气

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

 基于ARM-contexA9蜂鸣器驱动开发_第2张图片

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

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

基于ARM-contexA9蜂鸣器驱动开发_第3张图片

3、开始写驱动程序。

<span style="font-size:18px;">#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、写测试程序
<span style="font-size:18px;">#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
<span style="font-size:18px;">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、编译

  基于ARM-contexA9蜂鸣器驱动开发_第4张图片

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

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

9、开始执行

基于ARM-contexA9蜂鸣器驱动开发_第5张图片

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

你可能感兴趣的:(tiny4412,contex-A9)