努力成为linux kernel hacker的人李万鹏原创作品,为梦而战。转载请标明出处
http://blog.csdn.net/woshixingaaa/archive/2011/05/18/6429002.aspx
S3C2440内部ADC结构图:
对于s3c2440来说,实现A/D转换比较简单,主要应用的是ADC控制寄存器ADCCON和ADC转换数据寄存器ADCDAT0。寄存器ADCDAT0的低10位用于存储A/D转换后的数据。寄存器ADCCON的第15位用于标识A/D转换是否结束。第14位用于使能是否进行预分频,而第6位到第13位则存储的是预分频数值,因为A/D转换的速度不能太快,所以要通过预分频处理才可以得到正确的A/D转换速度,如我们想要得到A/D转换频率为1MHz,则预分频的值应为49。第3位到第5位表示的是A/D转换的通道选择。第2位可以实现A/D转换的待机模式。第1位用于是否通过读取操作来使能A/D转换的开始。第0位则是在第1位被清零的情况下用于开启A/D转换。
驱动代码:
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <mach/hardware.h> #include <asm/io.h> #include <linux/interrupt.h> #include <asm/irq.h> #include <linux/irq.h> #include <linux/miscdevice.h> #include <linux/types.h> #include <linux/clk.h> #include <linux/errno.h> #include <asm/uaccess.h> #include <mach/regs-clock.h> #include <plat/regs-adc.h> #include <linux/kernel.h> #define ADC_MINOR 100 #define ADC_NAME "lwp-adc" struct clk *adc_clk; int adc_base; int adc_finish = 0; static int adc_data; DECLARE_WAIT_QUEUE_HEAD(adc_wait); static irqreturn_t adc_interrupt(int irq, void *dev_id){ if(!adc_finish){ adc_data = readl(adc_base + S3C2410_ADCDAT0) & 0x3ff; //ad转换结束会产生中断,此时读取S3C2410_ADCDAT0的0~9位,来获取数据 adc_finish = 1; wake_up_interruptible(&adc_wait); //唤醒等待其上的进程 } return IRQ_HANDLED; } int myadc_open(struct inode *inode, struct file *file){ int ret; ret = request_irq(IRQ_ADC, adc_interrupt, IRQF_SHARED, ADC_NAME, 1); //这里注册中断,ad转换结束通知cpu有两种方式,一种靠cpu轮询标志位,一种靠中断 if(ret){ printk("IRQ %d can't get/n", IRQ_ADC); return -1; } return 0; } int myadc_close(struct inode *inode, struct file *file){ return 0; return -ENOENT; } void start_adc(){ //开始ad转换 int tmp; tmp = 0xff<<6 | 1<<14; //设置预分频使能,值为255,使用通道AIN0 writel(tmp ,adc_base + S3C2410_ADCCON); tmp = readl(adc_base + S3C2410_ADCCON); tmp |= 1<<0; //使能AD转换 writel(tmp, adc_base + S3C2410_ADCCON); } ssize_t myadc_read(struct file *filp, char __user *buff, size_t count, loff_t *offp){ start_adc(); //要读数据开始adc转换 wait_event_interruptible(adc_wait, adc_finish); //等待转换结束 adc_finish = 0; copy_to_user(buff, (char *)&adc_data, sizeof(adc_data)); //将获得的数据拷贝到用户空间,数据会在中断程序中获得 return sizeof(adc_data); } static struct file_operations adc_ops = { .owner = THIS_MODULE, .open = myadc_open, .release = myadc_close, .read = myadc_read, }; static struct miscdevice adc_misc = { .name = ADC_NAME, .minor = ADC_MINOR, .fops = &adc_ops, }; static int __init my_adc_init(void){ unsigned int ret; adc_clk = clk_get(NULL,"adc"); //由于ad转换需要时钟,所以这里获取时钟 if(!adc_clk){ printk(KERN_ERR "fail to find adc clk resource!/n"); ret = -1; goto err_clk; } clk_enable(adc_clk); //使能adc的时钟 adc_base = ioremap(S3C2410_PA_ADC, 20); //获得ADC控制寄存器的虚拟地址 if(adc_base == 0){ printk(KERN_ERR "fail to ioremap!/n"); ret = -1; goto err_nomap; } ret = misc_register(&adc_misc); //注册这个adc为混杂设备 if(IS_ERR(ret)){ goto err_register; } return 0; err_register: iounmap(adc_base); err_nomap: clk_disable(adc_clk); clk_put(adc_clk); err_clk: return ret; } static void __exit my_adc_exit(void){ misc_deregister(&adc_misc); free_irq(IRQ_ADC, 1); iounmap(adc_base); clk_disable(adc_clk); clk_put(adc_clk); } module_init(my_adc_init); module_exit(my_adc_exit); MODULE_AUTHOR("liwanpeng"); MODULE_LICENSE("GPL");
测试代码:
#include <stdio.h> #include <stdlib.h> #include <errno.h> int main(int argc, char **argv) { int fd; fd = open("/dev/lwp-adc", 0); if(fd < 0) { printf("Open ADC Device Faild!/n"); exit(1); } while(1) { int ret; int data; ret = read(fd, &data, sizeof(data)); if(ret != sizeof(data)) { if(errno != EAGAIN) { printf("Read ADC Device Faild!/n"); } continue; } else { printf("Read ADC value is: %d/n", data); } } close(fd); return 0; }
实验效果:
您还没有登录,请您登录后再发表评论
Linux驱动修炼之道-ADC驱动.pdf Linux内核访问外设I O资源的方式.pdf LINUX内核USB子系统学习笔记之初识USB.pdf kernel hacker修炼之道之驱动-流水灯.pdf kernel hacker修炼之道之驱动-混杂设备.pdf ...
内核linux4.4 驱动详情可看我博客RK3308-驱动开发(一)ADC驱动编写,是关于adc的驱动、和dts的配置说明。可供学习adc驱动 内含adc-keys.c dtsi相关配置
xMega官方驱动与示例程序-ADC
stm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT...
包含STM32单片机的ADC模块的完整的程序代码,并且包含完整的工程文件,可以直接编译成功,并且成功运行。
STM32CUBEIDE(10)----ADC在DMA模式下扫描多个通道 CSDN文字教程:https://blog.csdn.net/qq_24312945/article/details/126036132 B站教学视频:https://www.bilibili.com/video/BV1ST411w7hS
电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC...
电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-...
C语言16-ADC键盘扫描数码管显示键值和调整时间(STC32G-DEMO-CODE-220311kw)C语言16-ADC键盘扫描数码管显示键值和调整时间(STC32G-DEMO-CODE-220311kw)C语言16-ADC键盘扫描数码管显示键值和调整时间(STC32G-DEMO...
基于stm32f103C8-ADC带ucos操作系统
S32K144-PDB-ADC_backtoback-DMA-ISR-S32DS_s32k144pdb定时器ADCDMA_s32k144+ADC+PDB_s32kadc_s32k144adcdma_源码.zip
芯片手册-ADC0808-8通道8位ADC.pdf
电子-ADC1通道采集内部温度DMA中断传输.rar,单片机/嵌入式STM32-F0/F1/F2
LPC2148驱动ADC ----- A/D模数转换 这个工作区 每个工程包含3个配置选项 ISP_iFlash_Hex - 生成.Hex格式的目标文件 JLINK_iflash - 通过JLINK来烧写内部Flash的配置 JLINIX_iram - 通过JLINK来在内部RAM中调试 工程...
程序使用的是STC12C5A系列单片机,程序功能是,STC12C5A60S2-ADC-中断读ADC
ADC1开启3个规则通道,转换序列为:通道0(PA0),通道1(PA1),通道2(PA2) 在规则通道每个通道转换完成之后,DMA负责将转换的数据从ADC_DR寄存器传输到用户指定的目的地址 开启3个注入通道,转换序列为:通道0...
关于Linux的全部代码,主要是ADC-test,和Makefile.
TI的SAR-ADC方面资深应用工程师Rafael曾说过,SAR-ADC应用电路设计重点的70%-80%应放在基准源电路的设计。然而工程师们时常把基准源的电路的设计忽略。
此程序为linux下的s3c2410的ad模数转换器驱动程序,这是我买的教学试验平台带的,写的很不错,贡献出来。
适用于TQ2440开发板的adc测试实验。实验时须将开发板本身的adc驱动模块去除。
相关推荐
Linux驱动修炼之道-ADC驱动.pdf Linux内核访问外设I O资源的方式.pdf LINUX内核USB子系统学习笔记之初识USB.pdf kernel hacker修炼之道之驱动-流水灯.pdf kernel hacker修炼之道之驱动-混杂设备.pdf ...
内核linux4.4 驱动详情可看我博客RK3308-驱动开发(一)ADC驱动编写,是关于adc的驱动、和dts的配置说明。可供学习adc驱动 内含adc-keys.c dtsi相关配置
xMega官方驱动与示例程序-ADC
stm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT.zipstm32-ADC FFT...
包含STM32单片机的ADC模块的完整的程序代码,并且包含完整的工程文件,可以直接编译成功,并且成功运行。
STM32CUBEIDE(10)----ADC在DMA模式下扫描多个通道 CSDN文字教程:https://blog.csdn.net/qq_24312945/article/details/126036132 B站教学视频:https://www.bilibili.com/video/BV1ST411w7hS
电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC0808-AT89C51-毕业设计.pdf电压测量-ADC...
电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-ADC0808-AT89C51-毕业设计.docx电压测量-...
C语言16-ADC键盘扫描数码管显示键值和调整时间(STC32G-DEMO-CODE-220311kw)C语言16-ADC键盘扫描数码管显示键值和调整时间(STC32G-DEMO-CODE-220311kw)C语言16-ADC键盘扫描数码管显示键值和调整时间(STC32G-DEMO...
基于stm32f103C8-ADC带ucos操作系统
S32K144-PDB-ADC_backtoback-DMA-ISR-S32DS_s32k144pdb定时器ADCDMA_s32k144+ADC+PDB_s32kadc_s32k144adcdma_源码.zip
芯片手册-ADC0808-8通道8位ADC.pdf
电子-ADC1通道采集内部温度DMA中断传输.rar,单片机/嵌入式STM32-F0/F1/F2
LPC2148驱动ADC ----- A/D模数转换 这个工作区 每个工程包含3个配置选项 ISP_iFlash_Hex - 生成.Hex格式的目标文件 JLINK_iflash - 通过JLINK来烧写内部Flash的配置 JLINIX_iram - 通过JLINK来在内部RAM中调试 工程...
程序使用的是STC12C5A系列单片机,程序功能是,STC12C5A60S2-ADC-中断读ADC
ADC1开启3个规则通道,转换序列为:通道0(PA0),通道1(PA1),通道2(PA2) 在规则通道每个通道转换完成之后,DMA负责将转换的数据从ADC_DR寄存器传输到用户指定的目的地址 开启3个注入通道,转换序列为:通道0...
关于Linux的全部代码,主要是ADC-test,和Makefile.
TI的SAR-ADC方面资深应用工程师Rafael曾说过,SAR-ADC应用电路设计重点的70%-80%应放在基准源电路的设计。然而工程师们时常把基准源的电路的设计忽略。
此程序为linux下的s3c2410的ad模数转换器驱动程序,这是我买的教学试验平台带的,写的很不错,贡献出来。
适用于TQ2440开发板的adc测试实验。实验时须将开发板本身的adc驱动模块去除。