【OK210试用体验】+第十篇☞PWM(蜂鸣器)驱动 - 在线问答 - 电子技术论坛 - 最好最受欢迎电子论坛!

【OK210试用体验】+第十篇☞PWM(蜂鸣器)驱动

杨永胜 ( 楼主 ) 2015-9-1 16:07:42  只看该作者 倒序浏览
继续,在驱动程序的世界里爬行,上次成功把开发环境转移到Fedora10上之后,接下来就继续在Fedora上编写程序了。这次要介绍的是PWM驱动,和我做的一些测试。首先,看开发版的原理图和S5PV210的pdf文档,养成好的习惯,同时借助思维导图软件,根据文档的介绍罗列下来程序的整个框架。
根据文档我作出来的框架图如下所示:


接下来就是根绝这个大的框架进行编程了,对驱动的变成又一个几乎固定的结构,这就不在这里赘述了,直接上源代码了:

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include "pwm.h"

  8. /*GPD0[0]*/
  9. #define GPD0CON 0Xe02000A0
  10. #define TCFG0 0xe2500000
  11. #define TCFG1 0xe2500004
  12. #define TCNTB0 0xe250000c
  13. #define TCMPB0 0xe2500010
  14. #define TCON 0xe2500008

  15. unsigned int *gpd0_config;
  16. unsigned int *pwm_tcfg0;
  17. unsigned int *pwm_tcfg1;
  18. unsigned int *pwm_tcntb0;
  19. unsigned int *pwm_tcmpb0;
  20. unsigned int *pwm_tcon;

  21. struct cdev pwmdev;//定义结构体
  22. dev_t devnum;//定义设备号

  23. /*定义open函数*/
  24. int pwm_open (struct inode *inode, struct file *filp)
  25. {
  26.         gpd0_config = ioremap(GPD0CON, 4);
  27.         writel(0x0002, gpd0_config);
  28.         pwm_tcfg0 = ioremap(TCFG0, 4);
  29.         writel(255, pwm_tcfg0);
  30.         pwm_tcfg1 = ioremap(TCFG1, 4);
  31.         writel(3, pwm_tcfg1);
  32.         pwm_tcntb0 = ioremap(TCNTB0, 4);
  33.         writel(32200, pwm_tcntb0);
  34.         pwm_tcmpb0 = ioremap(TCMPB0, 4);
  35.         writel(9999, pwm_tcmpb0);
  36.         pwm_tcon = ioremap(TCON, 4);
  37.         writel(0x0e, pwm_tcon);
  38.         writel(0x0d, pwm_tcon);
  39.         printk(KERN_INFO"welcome to yspwmn");
  40.         return 0;
  41. }
  42. long pwm_ioctl (struct file *filp, unsigned int cmd, unsigned long arg){
  43.    
  44.         switch (cmd){
  45.     case PWM_A://占空比1/10
  46.         writel(3219, pwm_tcmpb0);
  47.         printk(KERN_INFO"the duty  is 1/10n");
  48.                 break;
  49.     case PWM_B://占空比2/10
  50.         writel(6439, pwm_tcmpb0);
  51.         printk(KERN_INFO"the duty  is 2/10n");
  52.                 break;
  53.     case PWM_C://占空比3/10
  54.         writel(9659, pwm_tcmpb0);
  55.         printk(KERN_INFO"the duty  is 3/10n");
  56.                 break;
  57.     case PWM_D://占空比4/10
  58.         writel(12879, pwm_tcmpb0);
  59.         printk(KERN_INFO"the duty  is 4/10n");
  60.                 break;
  61.     case PWM_OFF://PWM_OFF
  62.         writel(0, pwm_tcon);
  63.         printk(KERN_INFO"the pwm is off!n");
  64.                 break;
  65.     default://占空比5/10
  66.             writel(16099, pwm_tcmpb0);
  67.         printk(KERN_INFO"the duty  is 5/10n");
  68.         break;                    
  69.     }
  70.     return 0;
  71. }

  72. /*声明函数操作集*/
  73. static struct file_operations pwmfops = {
  74.         .open = pwm_open,
  75.         .owner = THIS_MODULE,
  76.         .unlocked_ioctl = pwm_ioctl,
  77. };

  78. static int pwm_init(void)//定义驱动入口函数
  79. {
  80.         cdev_init(&pwmdev, &pwmfops);//联系起来结构体和文件操作集
  81.         alloc_chrdev_region(&devnum, 0, 1, "yspwm");//分配空间
  82.         cdev_add(&pwmdev, devnum, 1);//注册驱动
  83.         return 0;
  84. }

  85. static void pwm_exit(void)
  86. {
  87.         cdev_del(&pwmdev);//删除空间
  88.         unregister_chrdev_region(devnum, 1);//取消注册
  89. }

  90. MODULE_LICENSE("GPL");//声明LICENSE,防止安装时出现警告
  91. MODULE_AUTHOR("SIMON YANG");//声明驱动作者

  92. module_init(pwm_init);//声明驱动入口
  93. module_exit(pwm_exit);//声明驱动出口
复制代码
上述代码的整个open函数就是按照思维导图的框架进行编写的,并且我稍微增加了一点功能,就是可以接受命令,根据不同的命令,可以更改pwm波的占空比从(1/10----------5/10),除此之外,还避免不了一个关闭pwm的命令,要不然,很吵人的,刚开始我没有定义这个命令,导致实验现象之后就要重启开发板,因为一直吵着影响了周围的人啊。整个驱动代码,主要使用了open和ioctl两个函数,这样框架更加清楚,明了,很适合像我这种初学者
接下来就是编写用户代码,如下所示:
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include "pwm.h"
  7. #include //和ioctl函数相关的头文件声明也可以是/sys/ioctl.h


  8. int main(int argc, char *argv[])
  9. {
  10.         int fd = 0;
  11.         int cmd;
  12.         
  13.         if(argc < 2){
  14.                 printf("please input the second commandn");
  15.                 return 0;
  16.         }
  17.         fd = open("/dev/yspwm", O_RDWR);//以读写方式打开设备
  18.         if (fd == 0xffffffff){
  19.                 printf("open the keydev failed! the errno is %dn",errno);
  20.                 return errno;}
  21.         
  22.         cmd = atoi(argv[1]);
  23.         switch(cmd){
  24.         case 1:
  25.                 ioctl(fd, PWM_A);
  26.                 break;
  27.         case 2:
  28.                 ioctl(fd, PWM_B);
  29.                 break;
  30.         case 3:
  31.                 ioctl(fd, PWM_C);
  32.                 break;
  33.         case 4:
  34.                 ioctl(fd, PWM_D);
  35.                 break;
  36.         default:
  37.                 printf("sorry the command which i couldn't to answern");
  38.                 break;
  39.         }
  40.                
  41.         return 0;
  42. }
复制代码
用户程序的代码也是很简单的,就是接收命令,判断命令的类型,并且执行,但是,中途变异用户代码的时候,我却遇到了问题,如下图所示:


提示我,__IO的问题,我很不理解当时,因为,整个框架我是从按键驱动当时的那个文件夹拷贝过来的,最后,还是请教了高人帮我解决了,就是缺少了ioctl.h的头文件,如上述代码红色部分所示。
最后,添加了头文件之后,很顺利的编译通过了,同时也完成了如下的实验现象:


他们分别对应不同的占空比,声音里面可以稍微听出来一些,以及关闭蜂鸣器的命令,至此pwm驱动也暂时完成了,接下来的时间我还是要继续前行啊,,,

4个回复

chkconfig 发表于 2015-10-14 00:23:25
请问你有遇到不能卸载模块的问题吗
杨永胜 发表于 2015-10-14 20:59:22
chkconfig 发表于 2015-10-14 00:23
请问你有遇到不能卸载模块的问题吗

我记得当时我遇到过,
chkconfig 发表于 2015-10-15 22:13:46
iysheng 发表于 2015-10-14 20:59
我记得当时我遇到过,

记得你是怎么解决的吗
杨永胜 发表于 2015-10-16 10:38:10
chkconfig 发表于 2015-10-15 22:13
记得你是怎么解决的吗

我好想没有解决,我一直是重新启动,然后从NFS挂载根文件系统的,
您需要登录后才可以回帖 登录 | 注册

本版积分规则


关闭

站长推荐上一条 /6 下一条

小黑屋|手机版|Archiver|电子发烧友 ( 湘ICP备2023018690号 )

GMT+8, 2024-12-22 11:22 , Processed in 0.655648 second(s), Total 59, Slave 42 queries .

Powered by 电子发烧友网

© 2015 bbs.elecfans.com

微信扫描
快速回复 返回顶部 返回列表