基于ARM-contexA9蜂鳴器驅(qū)動開發(fā)
上次,我們寫了一個LED的驅(qū)動程序,這一節(jié),我們只需稍微改動一下就可以實現(xiàn)蜂鳴器的驅(qū)動,讓我們來看看吧。
還是跟之前一樣,先找電路圖,找到電路板上對應(yīng)的引腳和相關(guān)聯(lián)的寄存器。
1、看電路圖
(1)蜂鳴器接口位于電路板的底板,看電路圖可知道是高電平有效。
(2)相對應(yīng)的找到核心板的接口。由此可知,我們的蜂鳴器是GPD0_0
接下來找數(shù)據(jù)手冊,找到對應(yīng)的寄存器,然后配置它就可以了。
2、查數(shù)據(jù)手冊,找到相關(guān)的寄存器,并配置
(1)找到GPD0CON,地址是0x114000A0,我們需要配置GPD0CON(0)為輸出狀態(tài)。也就是寫0x1這個值到這個寄存器。
(2)找到GPD0DAT這個寄存器,用于配置蜂鳴器的高低電平,物理地址是0x114000A4,剛好與上一個差4個字節(jié)的偏移
我們只要對這個寄存器寫1和寫0,那么蜂鳴器就可以叫起來了,哈哈。是不是很簡單?
3、開始寫驅(qū)動程序。
[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);
//設(shè)置io為輸出
*bell_config |= (0x1);
return 0;
}
int bell_close(struct inode *inode, struct file *filp)
{
printk("bell_close\n");
//關(guān)閉蜂鳴器
*bell_dat &= ~0x1 ;
return 0;
}
long bell_ioctl(struct file *filp, unsigned int request, unsigned long arg)
{
//控制蜂鳴器的狀態(tài)
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");
//注冊設(shè)備
major = register_chrdev(major, DEV_NAME, &fops);
//映射IO
bell_config = (volatile unsigned long *)ioremap(GPD0CON , 16);
//加4個字節(jié)偏移到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;
//打開設(shè)備
fd = open("/dev/test-dev",O_RDWR) ;
if(-1 == fd)
{
printf("open fair!\n");
return -1 ;
}
while(1){
//打開蜂鳴器
ioctl(fd,1);
sleep(1);
//關(guān)閉蜂鳴器
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、編譯
7、查看設(shè)備主設(shè)備號,這里就省略圖了,我們得到主設(shè)備號是250 cat /proc/devices
8、創(chuàng)建設(shè)備節(jié)點 mknod /dev/test-dev c 250 0
9、開始執(zhí)行
由于蜂鳴器的現(xiàn)象沒有實質(zhì)的效果展示,只能通過終端打印,如有興趣,自己去嘗試,用其它板子也可以,就照著我這個方法寫驅(qū)動,一定成功的!
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!