版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
编写PWM驱动以及测试程序开发板的BEEP灯电路在Exynos4412中,一共有5个32位定时器,这些定时器课发送中断信号给ARM处理器,另外,定时器0、1、2、3包含了脉冲宽度调制(PWM),并可驱动其对应的I/O引脚。每个定时器都有一个独立的32位递减计数器,定时器启动后,计数缓冲寄存器(TCNTBn)将初始值加载到递减计数器,定时器时钟驱动递减计数器,当递减计数器达到零,自动产生计时器中断请求,同时相应TCNTBn的值自动重新加载,开始下一个循环。但是,如果定时器停止,如清除TCONn的定时器使能位,TCNTBn的值将不会重新加载到计数器中。每个定时器都有一个独立的32位比较缓冲寄存器(TCMPBn)。当递减计数器与定时器控制逻辑中比较寄存器的值相匹配时,PWM输出会产生由低到高的电平跳变,因此,比较寄存器决定PWM输出的开启时间或关闭时间。1、初始化定时器n对应的计数缓冲寄存器TCNTBn为159,定时器n对应的计数比较缓冲寄存器TCMPBn为109。2、启动定时器n:设置定时器n的启动位为1,并手动更新为为零。此时寄存器TCNTBn的值159自动加载到内部的递减寄存器中,并开始递减计数,同时输出引脚TOUTn输出低电平。3、当递减寄存器的值递减到109(TCMPBn的数值)时,定时器n对应的电平输出引脚TOUTn从低电平翻转到高电平。4、当递减寄存器的值递减到0时,计数缓冲寄存器TCNTBn的值159重新被加载到定时器的递减器,定时器n对应的电平输出引脚TOUTn重新输出低电平,这样流程重复进行,引脚TOUTn就输出占空比可控的PWM波。值得注意的是,修改计数缓冲寄存器TCNTBn或比较缓冲寄存器TCMPBn的值,只能在下一个PWM周期起作用,不影响当前周期PWM的占空比。PWM驱动源程序文件(pwm_dev.c)设计,关键步骤为:pwm_dev_open:主要实现对PWM的寄存器进行初始化工作,pwm_dev_release:主要实现停止PWM波形的输出,pwm_dev_ioctl:分别设置了四个命令实现PWM的启动,停止,设置分频系数以及设置频率。在驱动加载时,即pwm_dev_init函数中,将实例化的文件操作结构体pwm_ops与设备号关联并注册到内核中,同时生成对应的设备文件。#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/platform_device.h>#include<linux/fb.h>#include<linux/err.h>#include<linux/slab.h>#include<linux/delay.h>#include<linux/gpio.h>#include<mach/gpio.h>#include<plat/gpio-cfg.h>
MODULE_LICENSE("GPLv2");
#defineDEVICE_NAME "pwm"//定义设备的名字为
pwm#defineDEVICE_NUM 1staticintmajor=0;//主设备号,次设备号staticintminor=0;
structcdevpwm_dev_cdev;staticstructclass*pwm_class;
pwm_dev.c
#defineNS_IN_1HZ 0x6400//100MHz/256/16
#defineBUZZER_PMW_GPIO EXYNOS4_GPD0(0)//蜂鸣器GPIO配置
#defineTIMER_BASE 0X139D0000void__iomem *timer_base;#defineTCFG0 (void__iomem *)(timer_base+0X00)#defineTCFG1 (void__iomem *)(timer_base+0X04)#defineTCON (void__iomem *)(timer_base+0X08)#defineTCNTB1 (void__iomem *)(timer_base+0X0C)#defineTCMPB1 (void__iomem *)(timer_base+0X10)
#definePWM_ON _IO('K',0)#definePWM_OFF _IO('K',1)#definePWM_SET_PRE _IOW('K',2,int)#definePWM_SET_FREQ _IOW('K',3,int)//open方法函数,主要打开pwm的操作staticintpwm_dev_open(structinode*inode,structfile*file){ printk(KERN_INFO"pwm_openstart"); s3c_gpio_cfgpin(BUZZER_PMW_GPIO,S3C_GPIO_SFN(2));
writel(readl(TCFG0)|0xff,TCFG0); writel((readl(TCFG1)&(~0x0f))|0x04,TCFG1); writel(300,TCNTB1); writel(150,TCMPB1); writel((readl(TCON)&(~0x1f))|0X02,TCON); return0;}//close方法函数,主要是关闭pwm操作staticintpwm_dev_release(structinode*inode,structfile*file){ printk(KERN_INFO"pwm_close"); writel(readl(TCON)&(~0x1f),TCON); s3c_gpio_cfgpin(BUZZER_PMW_GPIO,S3C_GPIO_OUTPUT); return0;}//控制io口方法函数staticlongpwm_dev_ioctl(structfile*filep,unsignedintcmd,unsignedlongarg){ intdata=arg;
if(_IOC_TYPE(cmd)!='K') return-ENOTTY; if(_IOC_NR(cmd)>3) return-ENOTTY;
printk(KERN_INFO"pwm_ioctlstart");
switch(cmd){ casePWM_ON: writel((readl(TCON)&(~0x1f))|0X0D,TCON); break; casePWM_SET_PRE: if(data==0) return-EINVAL; writel(readl(TCON)&(~0x1f),TCON); writel((readl(TCFG0)&(~0xff))|(data&0xff),TCFG0); writel((readl(TCON)&(~0x1f))|0X0D,TCON); break; casePWM_SET_FREQ: if(data==0) return-EINVAL;data=(NS_IN_1HZ)/data; writel(data,TCNTB1); writel(data>>1,TCMPB1); break; casePWM_OFF: writel(readl(TCON)&(~0x1f),TCON); break; } return0;}//operations结构体staticstructfile_operationspwm_ops={ .owner=THIS_MODULE, .unlocked_ioctl=pwm_dev_ioctl, .open=pwm_dev_open, .release=pwm_dev_release};
//pwm设备初始化,设备在被insmod插入模块到内核的过程中会调用这个函数staticint__initpwm_dev_init(void){ intret=0; dev_tdevno; printk(KERN_INFO"pwm_dev_initstart");
gpio_free(BUZZER_PMW_GPIO); ret=gpio_request(BUZZER_PMW_GPIO,DEVICE_NAME);
if(ret){ printk(KERN_INFO"requestGPIO%dforpwmfailed\n",BUZZER_PMW_GPIO); gotoERR1; } s3c_gpio_cfgpin(BUZZER_PMW_GPIO,S3C_GPIO_OUTPUT); gpio_set_value(BUZZER_PMW_GPIO,0);/*动态注册设备号*/ ret=alloc_chrdev_region(&devno,minor,DEVICE_NUM,"pwmdriver"); /*获得主设备号*/ major=MAJOR(devno); printk(KERN_INFO"dynamicadev_regionmajoris%d!\n",major); if(ret<0){ printk(KERN_INFO"register_chrdev_regionreq%disfailed!\n",major); gotoERR2;}else{ cdev_init(&pwm_dev_cdev,&pwm_ops); pwm_dev_cdev.owner=THIS_MODULE; ret=cdev_add(&pwm_dev_cdev,devno,DEVICE_NUM); if(ret<0){ printk(KERN_INFO"cdev_add%disfailed!\n",ret); gotoERR3; } else{ pwm_class=class_create(THIS_MODULE,DEVICE_NAME); device_create(pwm_class,NULL,devno,NULL,DEVICE_NAME); }}//地址映射timer_base=ioremap(TIMER_BASE,0x20);if(timer_base==NULL){ printk(KERN_INFO"ioremapfailed!\n"); ret=-ENOMEM; gotoERR4;} printk(KERN_INFODEVICE_NAME"\tinitialized\n");return0;
ERR4: device_destroy(pwm_class,devno); class_unregister(pwm_class); class_destroy(pwm_class); cdev_del(&pwm_dev_cdev);ERR3: unregister_chrdev_region(devno,DEVICE_NUM);ERR2: gpio_free(BUZZER_PMW_GPIO);ERR1: returnret;}
//设备在被卸载rmmod的过程中会调用这个函数staticvoid__exitpwm_dev_exit(void){ dev_tdevno=MKDEV(major,minor);
printk("pwm_exitstart");
gpio_free(BUZZER_PMW_GPIO); device_destroy(pwm_class,devno); class_unregister(pwm_class); class_destroy(pwm_class); cdev_del(&pwm_dev_cdev); unregister_chrdev_region(devno,DEVICE_NUM); iounmap(timer_base); printk(KERN_INFO"pwm_dev_exit!\n"); return;}
//模块初始化module_init(pwm_dev_init);//销毁模块module_exit(pwm_dev_exit);Makefileobj-m=pwm_dev.oKERNELDIR:=/root/yizhi/boot-kernel-source/iTop4412_Kernel_3.0PWD:=$(shellpwd)modules: $(MAKE)-C$(KERNELDIR)M=$(PWD)modulesclean: rm-rf*.o~core.depend*.ko*.mod.c*.*.cmd rm–rf.tmp_versions要编译的结果,名字和驱动源程序相同在PWM测试应用程序中,根据PWM驱动设计的3个文件操作open、close、ioctl,操作对应的PWM设备驱动文件/dev/pwm,来实现对PWM的控制。本例中,通过PWM驱动设置不同音调的频率,以及设置不同频率的播放时间,实现控制蜂鸣器输出音乐旋律。/*pwm_music.c*/#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<string.h>#include<sys/types.h>#include<sys/stat.h>#include<sys/ioctl.h>#include"pwm_music.h“intmain(){inti=0;intdev_fd;intpre=255;arm-none-linux-gnueabi-gcc–opwm_musicpwm_music.cdev_fd=open("/dev/pwm",O_RDWR|O_NONBLOCK);if(dev_fd<0){printf("error!\n");return-1;}ioctl(dev_fd,PWM_ON);ioctl(dev_fd,PWM_SET_PRE,pre);for(i=0;i<sizeof(Twotigers)/sizeof(Note);i++){ ioctl(dev_fd,PWM_SET_FREQ,Twotigers[i].pitch); usleep(Twotigers[i].dimation*50);}ioctl(dev_fd,PWM_OFF);close(dev_fd);return0;}打开pwm设置基本频率播放音调音调的持续时间停止pwm/*pwm_music.h*/#ifnd
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年上半年贵州黔南州独山县教育系统部分事业单位引进急需紧缺专业人才易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年贵州遵义市务川县事业单位面向三支一扶人员招聘易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年贵州省凤冈县乡镇事业单位招聘194人易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年贵州521事业单位联考笔试(全省)重点基础提升(共500题)附带答案详解-1
- 2025年上半年襄阳鱼梁洲开发区招考易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年蚌埠仲裁委员会秘书处招考易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年聊城市孔繁森同志纪念馆讲解员招考易考易错模拟试题(共500题)试卷后附参考答案
- 2025年消防设施设备拆除与重建服务合同3篇
- 二零二五年房地产投资合作项目税务筹划协议3篇
- 融创集团2025年度供应商反贿赂合规合同2篇
- DB32T-经成人中心静脉通路装置采血技术规范
- 【高空抛物侵权责任规定存在的问题及优化建议7100字(论文)】
- TDALN 033-2024 学生饮用奶安全规范入校管理标准
- 物流无人机垂直起降场选址与建设规范
- 冷库存储合同协议书范本
- AQ/T 4131-2023 烟花爆竹重大危险源辨识(正式版)
- 武术体育运动文案范文
- 设计服务合同范本百度网盘
- 2024年市级专科护士理论考核试题及答案
- 肺炎临床路径
- 供应商供货服务方案(2篇)
评论
0/150
提交评论