新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > Linux 驱动--ADC驱动

Linux 驱动--ADC驱动

作者: 时间:2016-11-20 来源:网络 收藏
主机系统:Ubuntu 11.04

内核版本:Linux Kernel 2.6.39

本文引用地址://m.amcfsurvey.com/article/201611/318848.htm

硬件平台:FL2440

开发板系统:Linux Kernel 2.6.28

下面是用CPU轮寻的方式来判断AD转换完成的

  1. #include
  2. #include
  3. #include
  4. #include/*创建设备节点*/
  5. #include
  6. #include/*延时函数*/
  7. #include
  8. #include
  9. #includeadc.h>
  10. #include
  11. #defineADC_MAJOR102
  12. #defineADC_NAME"my_adc"
  13. #defineSUCCESS0
  14. staticintadc_open(structinode*,structfile*);
  15. staticintadc_release(structinode*,structfile*);
  16. staticint__initadc_init(void);
  17. staticint__exitadc_exit(void);
  18. staticssize_tadc_read(structfile*,char*,size_t,loff_t*);
  19. volatileunsignedlongadc_con;
  20. unsignedlongadc_dat0;
  21. //#defineadc_con(unsignedlong)ioremap(0x58000000,4)
  22. //#defineadc_dat0(volatileunsignedlong)ioremap(0x5800000c,4)
  23. structclk*adc_clk;
  24. structfile_operationsadc_ops=
  25. {
  26. .owner=THIS_MODULE,
  27. .read=adc_read,
  28. .open=adc_open,
  29. .release=adc_release,
  30. };
  31. staticint__initadc_init(void)
  32. {
  33. intret;
  34. adc_clk=clk_get(NULL,"adc");//获取时钟
  35. clk_enable(adc_clk);//使能时钟
  36. ret=register_chrdev(ADC_MAJOR,ADC_NAME,&adc_ops);//注册设备
  37. if(ret<0)
  38. {
  39. printk("registerdevicefail/n");
  40. returnret;
  41. }
  42. adc_con=(unsignedlong)ioremap(0x58000000,4);
  43. adc_dat0=(volatileunsignedlong)ioremap(0x58000000+S3C2410_ADCDAT0,4);
  44. if(adc_con&adc_dat0==0)
  45. {
  46. printk("Failedtoioremap/n");
  47. gotohandle;
  48. }
  49. printk("Initialized.../n");
  50. returnSUCCESS;
  51. handle:
  52. unregister_chrdev(ADC_MAJOR,ADC_NAME);
  53. return-1;
  54. }
  55. staticintadc_open(structinode*inode,structfile*file)//打开设备函数
  56. {
  57. returnSUCCESS;
  58. }
  59. staticintadc_release(structinode*inode,structfile*file)//关闭设备函数
  60. {
  61. returnSUCCESS;
  62. }
  63. staticssize_tadc_read(structfile*file,
  64. char*buffer,
  65. size_tlength,
  66. loff_t*offset)//设备读取函数
  67. {
  68. unsignedintbuf;
  69. inttmp;
  70. inti;
  71. writew((1<<14)|(0x31<<6),adc_con);//设置ADCCON
  72. writew((readw(adc_con)|0x1),adc_con);//启动AD转换
  73. while(readw(adc_con)&0x1);//启动转换后,等待启动位清零
  74. while(!(readw(adc_con)&0x8000));//等待转换是否完毕
  75. //for(i=0;i<200000;i++);
  76. mdelay(100);
  77. buf=(readw(adc_dat0)&0x3ff);//取出转换后得到的有效数据
  78. copy_to_user(buffer,(char*)&buf,sizeof(buf));
  79. //printk("Thevalueis%x/n",buf);
  80. return2;
  81. }
  82. staticint__exitadc_exit(void)//驱动卸载函数
  83. {
  84. iounmap(adc_con);
  85. iounmap(adc_dat0);
  86. unregister_chrdev(ADC_MAJOR,ADC_NAME);
  87. clk_disable(adc_clk);
  88. clk_put(adc_clk);
  89. printk("Theadcisunintialized/n");
  90. returnSUCCESS;
  91. }
  92. module_init(adc_init);
  93. module_exit(adc_exit);
  94. MODULE_LICENSE("GPL");

其中控制寄存器的第15未标明AD转换是否完成,当AD完成转换时,控制寄存器自动置一,但是由于数据存在延迟,当第15位置一的时候读出的数据并不稳定,需要在其后加个延迟的函数,在内核态使用的延迟函数包含头文件./linux/delay.h

mdelay(int x);延时x毫秒

udelay(int x);延时x微秒

ndelay(int x);延时x纳秒

测试函数如下:

  1. #include
  2. #include
  3. #include
  4. #defineADC_DEVICE"/dev/my_adc"
  5. intmain()
  6. {
  7. intret;
  8. unsignedintdata;
  9. ret=open(ADC_DEVICE,0);
  10. if(ret<0)
  11. {
  12. printf("Openadcfail/n");
  13. returnret;
  14. }
  15. for(;;)
  16. {
  17. //printf("cnt=%d/n",cnt);
  18. read(ret,&data,sizeof(data));
  19. printf("Thevalueis0x%x/n",data);
  20. }
  21. close(ret);
  22. return0;
  23. }

测试结果




关键词: Linux驱动ADC驱

评论


技术专区

关闭