- 论坛徽章:
- 0
|
mini6410 实现 linux adc驱动详解--muge0913版 .
在嵌入式学习中嵌入式linux驱动占据着十分重要的地位,它不仅牵扯到操作系统、linux内核知识,同时作为开发者你必须了解面对的硬件体系结构和工作原理。在这本人muge0913对linux ad开发做了详细的介绍。
此文章仅供技术交流请勿商用。转载请注明出处:
http://blog.csdn.net/muge0913/article/details/7059241
一、ad转换器介绍
在这里我们先从adc的工作原理出发,由浅入深的学习,对于已经掌握adc硬件知识的阅读者可跳过此部分。
adc的基础知识我们可直接参考郭天祥老师的教材,免积分下载地址:
http://download.csdn.net/detail/muge0913/3903535
二、ARM中ad转换器介绍
这里我们以arm11为例:
①简介:
.
10-bit/12-bit的CMOSADC(模数转换器)是一个8通道模拟输入的回收型设备。5MHz的A / D转换时钟,最高转换率的1MSPS转换到10-bit/12-bit二进制数字编码的模拟输入信号。A / D转换片上采样和保持功能。支持省电模式。
②特性:
③配置:如果简单的驱动ad,只配置ADCCON寄存器即可,如要实现触摸屏的工能则要其他寄存器
注:在下面代码中我们由此部分的注释
三、linux中的adc驱动程序及注释- view plaincopy to clipboardprint?
- 01.#include <linux/kernel.h>
- 02.#include <linux/module.h>
- 03.#include <linux/slab.h>
- 04.#include <linux/input.h>
- 05.#include <linux/init.h>
- 06.#include <linux/errno.h>
- 07.#include <linux/serio.h>
- 08.#include <linux/delay.h>
- 09.#include <linux/clk.h>
- 10.#include <linux/sched.h>
- 11.#include <linux/cdev.h>
- 12.#include <linux/miscdevice.h>
- 13.
- 14.
- 15.#include <asm/io.h>
- 16.#include <asm/irq.h>
- 17.#include <asm/uaccess.h>
- 18.
- 19.#include <mach/map.h>
- 20.#include <mach/regs-clock.h>
- 21.#include <mach/regs-gpio.h>
- 22.#include <plat/regs-adc.h>
- 23.static void __iomem * base_addr;
- 24.static struct clk *adc_clock;
- 25.
- 26.
- 27.#define __ADCREG(name) (*(volatile unsigned long *)(base_addr + name))
- 28.#define ADCCON __ADCREG(S3C_ADCCON) // ADC control
- 29.#define ADCTSC __ADCREG(S3C_ADCTSC) // ADC touch screen control
- 30.#define ADCDLY __ADCREG(S3C_ADCDLY) // ADC start or Interval Delay
- 31.#define ADCDAT0 __ADCREG(S3C_ADCDAT0) // ADC conversion data 0
- 32.#define ADCDAT1 __ADCREG(S3C_ADCDAT1) // ADC conversion data 1
- 33.#define ADCUPDN __ADCREG(S3C_ADCUPDN) // Stylus Up/Down interrupt status
- 34.
- 35.#define PRESCALE_DIS (0 << 14)
- 36.#define PRESCALE_EN (1 << 14)
- 37.#define PRSCVL(x) ((x) << 6)
- 38.#define ADC_INPUT(x) ((x) << 3)
- 39.#define ADC_START (1 << 0)
- 40.#define ADC_ENDCVT (1 << 15)
- 41.
- 42.#define DEVICE_NAME "adc_dev"
- 43.static int adc_init()
- 44.{
- 45. unsigned int preScaler = 0XFF;
- 46. ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);
- 47. ADCCON |= ADC_START;
- 48. return 0;
- 49.}
- 50.static int adc_open(struct inode *inode ,struct file *filp)
- 51.{
- 52. adc_init();
- 53. return 0;
- 54.}
- 55.static int adc_release(struct inode *inode,struct file *filp)
- 56.{
- 57. return 0;
- 58.}
- 59.static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)
- 60.{
- 61. ADCCON |= ADC_START;
- 62. while(ADCCON & 0x01);//check if Enable_start is low
- 63. while(!(ADCCON &0x8000));/*检查转换是否结束*/
- 64. return (ADCDAT0 & 0x3ff);
- 65.}
- 66.
- 67.static struct file_operations dev_fops =
- 68.{
- 69. .owner = THIS_MODULE,
- 70. .open = adc_open,
- 71. .release = adc_release,
- 72. .read = adc_read,
- 73.};
- 74.
- 75.static struct miscdevice misc =
- 76.{
- 77. .minor = MISC_DYNAMIC_MINOR,
- 78. .name = DEVICE_NAME,
- 79. .fops = &dev_fops,
- 80.};
- 81.
- 82.static int __init dev_init()
- 83.{
- 84. int ret;
- 85.
- 86.
- 87. base_addr =ioremap(SAMSUNG_PA_ADC,0X20);//地址映射
- 88. if(base_addr == NULL)
- 89. {
- 90. printk(KERN_ERR"failed to remap\n");
- 91. return -ENOMEM;
- 92. }
- 93.
- 94. adc_clock = clk_get(NULL,"adc");//激活adc时钟模块
- 95. if(!adc_clock)
- 96. {
- 97. printk(KERN_ERR"failed to get adc clock\n");
- 98. return -ENOENT;
- 99. }
- 100. clk_enable(adc_clock);
- 101.
- 102.
- 103. ret = misc_register(&misc);//混杂设备注册
- 104. printk("dev_init return ret:%d\n",ret);
- 105. return ret;
- 106.}
- 107.static void __exit dev_exit()
- 108.{
- 109. iounmap(base_addr);//取消映射
- 110.
- 111. if(adc_clock)//disable adc clock取消adc时钟
- 112. {
- 113. clk_disable(adc_clock);
- 114. clk_put(adc_clock);
- 115. adc_clock =NULL;
- 116. }
- 117. misc_deregister(&misc);//注销混杂设备
- 118.
- 119.}
- 120.module_init(dev_init);
- 121.module_exit(dev_exit);
- 122.
- 123.MODULE_LICENSE("GPL");
- 124.MODULE_AUTHOR("MUGE0913");
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/input.h>
- #include <linux/init.h>
- #include <linux/errno.h>
- #include <linux/serio.h>
- #include <linux/delay.h>
- #include <linux/clk.h>
- #include <linux/sched.h>
- #include <linux/cdev.h>
- #include <linux/miscdevice.h>
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
- #include <mach/map.h>
- #include <mach/regs-clock.h>
- #include <mach/regs-gpio.h>
- #include <plat/regs-adc.h>
- static void __iomem * base_addr;
- static struct clk *adc_clock;
- #define __ADCREG(name) (*(volatile unsigned long *)(base_addr + name))
- #define ADCCON __ADCREG(S3C_ADCCON) // ADC control
- #define ADCTSC __ADCREG(S3C_ADCTSC) // ADC touch screen control
- #define ADCDLY __ADCREG(S3C_ADCDLY) // ADC start or Interval Delay
- #define ADCDAT0 __ADCREG(S3C_ADCDAT0) // ADC conversion data 0
- #define ADCDAT1 __ADCREG(S3C_ADCDAT1) // ADC conversion data 1
- #define ADCUPDN __ADCREG(S3C_ADCUPDN) // Stylus Up/Down interrupt status
- #define PRESCALE_DIS (0 << 14)
- #define PRESCALE_EN (1 << 14)
- #define PRSCVL(x) ((x) << 6)
- #define ADC_INPUT(x) ((x) << 3)
- #define ADC_START (1 << 0)
- #define ADC_ENDCVT (1 << 15)
- #define DEVICE_NAME "adc_dev"
- static int adc_init()
- {
- unsigned int preScaler = 0XFF;
- ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2);
- ADCCON |= ADC_START;
- return 0;
- }
- static int adc_open(struct inode *inode ,struct file *filp)
- {
- adc_init();
- return 0;
- }
- static int adc_release(struct inode *inode,struct file *filp)
- {
- return 0;
- }
- static ssize_t adc_read(struct file *filp,char __user *buff,size_t size,loff_t *ppos)
- {
- ADCCON |= ADC_START;
- while(ADCCON & 0x01);//check if Enable_start is low
- while(!(ADCCON &0x8000));/*检查转换是否结束*/
- return (ADCDAT0 & 0x3ff);
- }
- static struct file_operations dev_fops =
- {
- .owner = THIS_MODULE,
- .open = adc_open,
- .release = adc_release,
- .read = adc_read,
- };
- static struct miscdevice misc =
- {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &dev_fops,
- };
- static int __init dev_init()
- {
- int ret;
- base_addr =ioremap(SAMSUNG_PA_ADC,0X20);//地址映射
- if(base_addr == NULL)
- {
- printk(KERN_ERR"failed to remap\n");
- return -ENOMEM;
- }
- adc_clock = clk_get(NULL,"adc");//激活adc时钟模块
- if(!adc_clock)
- {
- printk(KERN_ERR"failed to get adc clock\n");
- return -ENOENT;
- }
- clk_enable(adc_clock);
- ret = misc_register(&misc);//混杂设备注册
- printk("dev_init return ret:%d\n",ret);
- return ret;
- }
- static void __exit dev_exit()
- {
- iounmap(base_addr);//取消映射
-
- if(adc_clock)//disable adc clock取消adc时钟
- {
- clk_disable(adc_clock);
- clk_put(adc_clock);
- adc_clock =NULL;
- }
- misc_deregister(&misc);//注销混杂设备
-
- }
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("MUGE0913");
复制代码 四、测试程序- view plaincopy to clipboardprint?
- 01.#include <stdio.h>
- 02.#include <fcntl.h>
- 03.#include <unistd.h>
- 04.
- 05.int main()
- 06.{
- 07. int fp,adc_data,i;
- 08. fp = open("/dev/adc_dev",O_RDWR);
- 09. for(i=0;i<100;i++)
- 10. {
- 11. adc_data = read(fp,NULL,0);
- 12. printf("%d\n",adc_data);
- 13. sleep(1);
- 14. }
- 15. close(fp);
- 16. return 0;
- 17.}
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- int main()
- {
- int fp,adc_data,i;
- fp = open("/dev/adc_dev",O_RDWR);
- for(i=0;i<100;i++)
- {
- adc_data = read(fp,NULL,0);
- printf("%d\n",adc_data);
- sleep(1);
- }
- close(fp);
- return 0;
- }
复制代码 五、运行效果
|
|