《嵌入式软件设计概述 (14).ppt》由会员分享,可在线阅读,更多相关《嵌入式软件设计概述 (14).ppt(55页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、蜂鸣器驱动程序蜂鸣器驱动程序运行于S3C2410/Linux 2.4内核。S3C2410芯片的GPB0端口连接蜂鸣器,当给GPB0口写低电平时,蜂鸣器鸣响,当给GPB0口写高电平时,蜂鸣器静音。蜂鸣器驱动程序蜂鸣器驱动程序硬件电路如图所示#include#include#include#include#include#include#include#include#include#include#include#include#define BUZZER_MAJOR 222#define BUZZER_DEVNAME buzzerbuzzer.c#define GPB_CTL_BASE io_
2、p2v(0 x56000010)#define S3C2410_GPBCON (GPB_CTL_BASE+0 x0)#define S3C2410_GPBDAT (GPB_CTL_BASE+0 x4)struct unit u32*GPB_CON;u32*GPB_DAT;static struct unit buzzer_unit=.GPB_CON=(u32*)S3C2410_GPBCON,.GPB_DAT=(u32*)S3C2410_GPBDAT,;buzzer.cstatic void buzzer_set_value(struct unit*unit,u8 val)if(val=1)*u
3、nit-GPB_DAT=*unit-GPB_DAT&(0 x1);/PB0置低电平,鸣响 else*unit-GPB_DAT=*unit-GPB_DAT|0 x1;/PB0置高电平,静音ssize_t Buzzer_open(struct inode*inode,struct file*file)MOD_INC_USE_COUNT;file-private_data=&buzzer_unit;return 0;buzzer.cssize_t Buzzer_release(struct inode*inode,struct file*file)MOD_DEC_USE_COUNT;return 0
4、;ssize_t Buzzer_write(struct file*file,const char*buf,size_t count,loff_t*offset)char temp;int ret;struct unit*unit=(struct unit*)file-private_data;ret=copy_from_user(&temp,buf,count);if(ret!=0)printk(wrong!n);return-EFAULT;else buzzer_set_value(unit,temp);return ret;buzzer.cstruct file_operations B
5、uzzer_Ctl_ops=open:Buzzer_open,write:Buzzer_write,release:Buzzer_release,;static devfs_handle_t devfs_handle,devfs_buzzer_dir;static void _init init_hardware(struct unit*unit)*unit-GPB_CON&=0 x2;/PBCON1=0 *unit-GPB_CON|=0 x1;/PBCON0=1 PB0为输出*unit-GPB_DAT|=0 x1;/PB0初始值为1,蜂鸣器静音buzzer.cstatic int _init
6、 init_buzzer()int res;printk(This is my Buzzer driver!n);res=devfs_register_chrdev(BUZZER_MAJOR,BUZZER_DEVNAME,&Buzzer_Ctl_ops);devfs_buzzer_dir=devfs_mk_dir(NULL,BUZZER_DEVNAME,NULL);devfs_handle=devfs_register(devfs_buzzer_dir,0,DEVFS_FL_DEFAULT,BUZZER_MAJOR,0,S_IFCHR|S_IRUSR|S_IWUSR,&Buzzer_Ctl_o
7、ps,NULL);init_hardware(&buzzer_unit);return res;static void _exit clean_buzzer()devfs_unregister_chrdev(BUZZER_MAJOR,BUZZER_DEVNAME);devfs_unregister(devfs_handle);devfs_unregister(devfs_buzzer_dir);buzzer.cmodule_init(init_buzzer);module_exit(clean_buzzer);MODULE_DESCRIPTION(EduKit III-2410 buzzer
8、driver);MODULE_AUTHOR(SSDUT);MODULE_LICENSE(GPL);buzzer.c利用下面的Makefile交叉编译驱动程序蜂鸣器驱动的蜂鸣器驱动的makefile#Makefile for the kernel buzzer driver(Module).WKDIR=/usr/local/src/edukit-2410CROSSDIR=/usrINSTALLDIR=/home/app#$(WKDIR)/driversMODDEV=buzzer.oMODFILE=buzzer.cMODFILE_H=CROSS=arm-linux-CC=$(CROSS)gccAS
9、=$(CROSS)asLD=$(CROSS)lddriver_makefileMACRO=-DMODULE-D_KERNEL_-DCONFIG_KERNELDifdef DEBUGCFLAGS=-gendifCFLAGS=-O2-fomit-frame-pointerCFLAGS+=$(MACRO)-mapcs-32-march=armv4-mtune=arm9tdmi-fno-builtinINCLUDES=-I$(WKDIR)/kernel/include-I$(CROSSDIR)/arm-linux/include-I$(CROSSDIR)/lib/gcc-lib/arm-linux/2
10、.95.3/include$(MODDEV):$(MODFILE)$(MODFILE_H)Makefile$(CC)$(CFLAGS)$(INCLUDES)-o$-c$install:$(MODDEV)mkdir-p$(INSTALLDIR)cp-target-dir=$(INSTALLDIR)$(MODDEV)clean:-rm-f$(MODDEV)driver_makefile下面的程序用来测试蜂鸣器设备是否正常工作。蜂鸣器测试程序蜂鸣器测试程序#include#include#include#include int main(int argc,char*argv)int fd,on,of
11、f;int i=0;static char*driver=/dev/buzzer/0;on=1;off=0;printf(BUZZER test example base on Linux.n);fd=open(driver,O_RDWR);if(fd 0)printf(Cant not open%sn,driver);return fd;buzzer_test.cfor(;i10;i+)if(i%2=0)write(fd,&on,1);printf(Buzzer ON!n);usleep(1000*1000);elsewrite(fd,&off,1);printf(Buzzer OFF!n)
12、;sleep(1);printf(end.n);close(fd);return 0;buzzer_test.c运行于S3C2410/Linux 2.4内核。每当按下实验设备上的按键,即可触发一个中断,然后在超级终端上显示一条信息。中断按键驱动程序中断按键驱动程序硬件电路如图所示#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include eint0.c#define MY_EINT0_SIG 50
13、/自定义的信号MYSIG#define EINT0_DEVNAME eint0#define EINT0_MAJOR 223#define S3C2410_GPFCON io_p2v(0 x56000050)#define S3C2410_EXTINT0io_p2v(0 x56000088)static int pid;/用于保存应用程序的进程号,当中断发生时/才能将MYSIG信号准确的发给应用程序struct unit u32*GPF_CON;u32*rEXTINT0;static struct unit eint0_unit=.GPF_CON=(u32*)S3C2410_GPFCON,.r
14、EXTINT0=(u32*)S3C2410_EXTINT0,;static int mysig(void);eint0.cvoid eint0_do_tasklet();DECLARE_TASKLET(my_tasklet,eint0_do_tasklet,NULL);void eint0_do_tasklet()mysig();/中断上半部,直接注册中断并被中断触发,在其中调度下半部static void eint0_handler(int irq,void*dev_id,struct pt_regs*reg)/此函数用来调度一个tasklet运行tasklet_schedule(&my_t
15、asklet);static int mysig(void)siginfo_t info;struct task_struct*p;/task_struct即PCB,用来描述每一个进程eint0.cread_lock(&tasklist_lock);/减1,为负则加锁,等待锁变量变为1,否则 /遍历(环形)进程表中的每一个进程:for_each_task(p)if(p-pid=pid)read_unlock(&tasklist_lock);goto find_ps;read_unlock(&tasklist_lock);printk(can not find processn);return-
16、1;find_ps:send_sig_info(MY_EINT0_SIG,&info,p);return 0;eint0.cssize_t eint0_open(struct inode*inode,struct file*file)MOD_INC_USE_COUNT;return 0;ssize_t eint0_release(struct inode*inode,struct file*file)MOD_DEC_USE_COUNT;return 0;ssize_t eint0_read(struct file*file,char*buf,size_t count,loff_t*offset
17、)return 0;ssize_t eint0_write(struct file*file,const char*buf,size_t count,loff_t*offset)int ret,temp;eint0.cret=copy_from_user(&temp,buf,count);pid=temp;return 0;struct file_operations eint0_Ctl_ops=open:eint0_open,read:eint0_read,write:eint0_write,release:eint0_release,;static void _init init_hard
18、ware(struct unit*unit)*unit-GPF_CON&=(0 x3);*unit-GPF_CON|=(1rEXTINT0&=(3rEXTINT0|=(11);static devfs_handle_t devfs_handle,devfs_eint0_dir;eint0.cstatic int _init init_eint0()int res;printk(This is my Eint0 driver!n);devfs_register_chrdev(EINT0_MAJOR,EINT0_DEVNAME,&eint0_Ctl_ops);devfs_eint0_dir=dev
19、fs_mk_dir(NULL,EINT0_DEVNAME,NULL);devfs_handle=devfs_register(devfs_eint0_dir,0,DEVFS_FL_DEFAULT,EINT0_MAJOR,0,S_IFCHR|S_IRUSR|S_IWUSR,&eint0_Ctl_ops,NULL);init_hardware(&eint0_unit);res=request_irq(IRQ_EINT0,eint0_handler,SA_INTERRUPT,EINT0_DEVNAME,NULL);if(res 0)printk(The IRQ Wrong!n);return res
20、;eint0.cstatic void _exit clean_eint0()devfs_unregister_chrdev(EINT0_MAJOR,EINT0_DEVNAME);devfs_unregister(devfs_handle);devfs_unregister(devfs_eint0_dir);free_irq(IRQ_EINT0,NULL);module_init(init_eint0);module_exit(clean_eint0);MODULE_DESCRIPTION(EduKitIII-2410 eint0 driver);MODULE_AUTHOR(SSDUT);MO
21、DULE_LICENSE(GPL);eint0.c利用下面的Makefile交叉编译驱动程序中断按键驱动的中断按键驱动的makefile#Makefile for the eint0 driver.WKDIR=/usr/local/src/edukit-2410CROSSDIR=/usrINSTALLDIR=/home/app#$(WKDIR)/driversMODDEV=eint0.oMODFILE=eint0.cMODFILE_H=CROSS=arm-linux-CC=$(CROSS)gccAS=$(CROSS)asLD=$(CROSS)ldMACRO=-DMODULE-D_KERNEL_
22、-DCONFIG_KERNELDifdef DEBUGmakefileCFLAGS=-gendifCFLAGS=-O2-fomit-frame-pointerCFLAGS+=$(MACRO)-mapcs-32-march=armv4-mtune=arm9tdmi-fno-builtinINCLUDES=-I$(WKDIR)/kernel/include-I$(CROSSDIR)/arm-linux/include-I$(CROSSDIR)/lib/gcc-lib/arm-linux/2.95.3/include$(MODDEV):$(MODFILE)$(MODFILE_H)Makefile$(
23、CC)$(CFLAGS)$(INCLUDES)-o$-c$install:$(MODDEV)mkdir-p$(INSTALLDIR)cp-target-dir=$(INSTALLDIR)$(MODDEV)clean:-rm-f$(MODDEV)makefile下面的程序用来测试中断按键设备是否正常工作。中断按键测试程序中断按键测试程序#include#include#include#include#include#include#define MYSIG 50void handler()/信号句柄函数,每当收到信号是会被调用printf(int eint0 signal handler,sig
24、nal sending success!n);int main(int argc,char*argv)int fd1,adcData,pid,oflags;static char*driver1=/dev/eint0/0;fd1=open(driver1,O_RDWR);if(fd1 0)printf(device open failn);eint0_test.creturn-1;pid=getpid();printf(the process pid is:%d,pid);write(fd1,&pid,4);/将本测试程序的进程号写入驱动程序signal(MYSIG,handler);/当接收
25、到MYSIG信号时调用handler函数/以下几行设置异步通知机制/设置本进程为设备文件的拥有者,告诉内核将信号发给本进程fcntl(STDIN_FILENO,F_SETOWN,getpid();/读取打开文件描述符的状态oflags=fcntl(STDIN_FILENO,F_GETFL);/设置FASYNC标志,修改打开文件描述符的状态,启动异步通知机制fcntl(STDIN_FILENO,F_SETFL,oflags|FASYNC);while(1)/通过无限循环等待用户按键close(fd1);printf(end.n);return 0;eint0_test.c运行于S3C2440/L
26、inux 2.6内核的键盘驱动程序实例。键盘驱动程序键盘驱动程序硬件电路如图所示键盘的列线为输出线,从左到右依次连接处理器的引脚GPG7、GPF5、GPF4和GPF3;键盘的行线为输入线,左侧通过上拉电阻连接至电源,右侧从上到下依次连接至嵌入式处理器的引脚GPF2、GPF1、GPG5和GPG6,这4个引脚采用中断模式工作,下降沿触发。矩阵键盘的按键识别有多种方法,本例采用逐列扫描法,流程如下。首先,设置连接列线的处理器引脚输出低电平,设置连接行线的处理器引脚工作在中断模式下。当按键不被按下时,中断引脚通过电阻连接至电源,始终保持为高电平,中断不会被触发。一旦有按键按下,该行电平即被列线拉低为低
27、电平,该行对应的中断即被触发,从而完成行识别。然后,程序执行对应行的中断服务程序,在其中逐一将各列线设置为高电平,同时继续检测按键行是否仍为低电平,如为低,说明按下的键不在该列,如为高,说明按下的键从属于该列,从而完成列识别。#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include button.c#define DEVICE_NAME dial_keystruct
28、 button_irq_desc int irq;int pin;int pin_setting;int number;char*name;struct col_descint pin;int pin_setting;static struct col_desc col_table =S3C2410_GPG(7),S3C2410_GPIO_OUTPUT,S3C2410_GPF(5),S3C2410_GPIO_OUTPUT,S3C2410_GPF(4),S3C2410_GPIO_OUTPUT,S3C2410_GPF(3),S3C2410_GPIO_OUTPUT,;button.cstatic s
29、truct button_irq_desc button_irqs =IRQ_EINT2,S3C2410_GPF(2),S3C2410_GPF2_EINT2,0,KEY1,IRQ_EINT1,S3C2410_GPF(1),S3C2410_GPF1_EINT1,1,KEY2,IRQ_EINT13,S3C2410_GPG(5),S3C2410_GPG5_EINT13,2,KEY3,IRQ_EINT14,S3C2410_GPG(6),S3C2410_GPG6_EINT14,3,KEY4,;static volatile char key_values =0,0,0,0;static volatile
30、 char user_values =0,0;static DECLARE_WAIT_QUEUE_HEAD(button_waitq);static volatile int ev_press=0;static volatile int row=-1;static volatile int col=-1;static irqreturn_t buttons_interrupt(int irq,void*dev_id)struct button_irq_desc*button_irqs=(struct button_irq_desc*)dev_id;int down;int i,t=10;dow
31、n=!s3c2410_gpio_getpin(button_irqs-pin);button.c if(down=1)udelay(100);down=!s3c2410_gpio_getpin(button_irqs-pin);if(down=1)&(ev_press=0)key_valuesbutton_irqs-number=0+down;ev_press=1;for(i=0;i pin);switch(t)case 2:case 4:case 32:case 64:button.crow=button_irqs-number;col=i;break;default:row=-1;col=
32、-1;break;s3c2410_gpio_setpin(col_tablei.pin,0);if(row=0)&(col=0)break;wake_up_interruptible(&button_waitq);return IRQ_RETVAL(IRQ_HANDLED);button.cstatic int s3c24xx_buttons_open(struct inode*inode,struct file*file)int i,j;int err=0;for(i=0;i sizeof(button_irqs)/sizeof(button_irqs0);i+)if(button_irqs
33、i.irq 0)continue;err=request_irq(button_irqsi.irq,buttons_interrupt,IRQ_TYPE_LEVEL_LOW,button_irqsi.name,(void*)&button_irqsi);if(err)break;button.c for(j=0;j=0;i-)if(button_irqsi.irq 0)continue;disable_irq(button_irqsi.irq);free_irq(button_irqsi.irq,(void*)&button_irqsi);return-EBUSY;button.c ev_pr
34、ess=1;for(i=0;i 4;i+)s3c2410_gpio_setpin(col_tablei.pin,0);return 0;static int s3c24xx_buttons_close(struct inode*inode,struct file*file)int i;for(i=0;i sizeof(button_irqs)/sizeof(button_irqs0);i+)if(button_irqsi.irq f_flags&O_NONBLOCK)return-EAGAIN;else wait_event_interruptible_timeout(button_waitq
35、,ev_press,500);user_values0=row+48;user_values1=col+48;err=copy_to_user(buff,(const void*)user_values,2);user_values0=0;user_values1=0;button.ccol=-1;row=-1;ev_press=0;return err?-EFAULT:min(sizeof(key_values),count);static unsigned int s3c24xx_buttons_poll(struct file*file,struct poll_table_struct*
36、wait)unsigned int mask=0;poll_wait(file,&button_waitq,wait);if(ev_press)mask|=POLLIN|POLLRDNORM;return mask;button.cstatic struct file_operations dev_fops=.owner =THIS_MODULE,.open =s3c24xx_buttons_open,.release=s3c24xx_buttons_close,.read =s3c24xx_buttons_read,.poll =s3c24xx_buttons_poll,;static st
37、ruct miscdevice misc=.minor=MISC_DYNAMIC_MINOR,.name=DEVICE_NAME,.fops=&dev_fops,;button.cstatic int _init dev_init(void)int ret;ret=misc_register(&misc);printk(DEVICE_NAMEtinitializedn);return ret;static void _exit dev_exit(void)misc_deregister(&misc);printk(DEVICE_NAMEexitn);module_init(dev_init);
38、module_exit(dev_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(FriendlyARM Inc.);button.c利用下面的Makefile交叉编译驱动程序键盘驱动的键盘驱动的makefile#Description:#Makefile for 2.6 device drivers#Comment/uncomment the following line to disable/enable debugging#DEBUG=y#Add your debugging flag(or not)to CFLAGSifeq($(DEBUG),y)DEBF
39、LAGS=-O-g-DCAN_DEBUG#-O is needed to expand inlineselseDEBFLAGS=-O2endifmakefileifneq($(KERNELRELEASE),)#call from kernel build systemobj-m:=dial_keyboard_drv_task.o elseKERNELDIR?=/usr/src/linux-2.6.32.2PWD:=$(shell pwd)CC:=arm-linux-gccHOSTCC:=gccexport CC HOSTCCdefault:$(MAKE)-C$(KERNELDIR)M=$(PW
40、D)modulesendifclean:rm-rf*.o*.komakefile下面的程序用来测试键盘设备是否正常工作。键盘测试程序键盘测试程序#include#include#include#include#include#include#include#include#include#include#include int main(void)int buttons_fd;char current_state;char buttons2=0,0;buttons_fd=open(/dev/dial_key,0);/打开按键设备button_test.cif(buttons_fd 0)perr
41、or(open device buttons failed);/打开按键失败exit(1);while(1)/打开成功,执行循环 char realchar=x;char current_buttons2;if(read(buttons_fd,current_buttons,sizeof current_buttons)!=sizeof current_buttons)perror(read buttons:);/读取按键失败exit(1);buttons0=current_buttons0;buttons1=current_buttons1;button_test.cswitch(butto
42、ns0)case 51:switch(buttons1)case 51:realchar=1;/按键1break;case 50:realchar=2;/按键2break;case 49:realchar=3;/按键3break;case 48:realchar=A;/按键Abreak;break;button_test.ccase 50:switch(buttons1)case 51:realchar=4;/按键4break;case 50:realchar=5;/按键5break;case 49:realchar=6;/按键6break;case 48:realchar=B;/按键Bbre
43、ak;break;button_test.ccase 49:switch(buttons1)case 51:realchar=7;/按键7break;case 50:realchar=8;/按键8break;case 49:realchar=9;/按键9break;case 48:realchar=C;/按键Cbreak;break;button_test.ccase 48:switch(buttons1)case 51:realchar=*;/按键*break;case 50:realchar=0;/按键0break;case 49:realchar=#;/按键#break;case 48:realchar=D;/按键Dbreak;break;button_test.cif(realchar!=x)printf(the put key is%cn,realchar);/输出按下的键值close(buttons_fd);return 0;button_test.c