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驱动程序及注释

#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");
四、测试程序

#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; }

五、运行效果




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值