OK6410之ADC驱动程序 混杂设备
2012-04-03 15:51
393 查看
参考
/*之前自己根据裸机程序改的,给ADC寄存器地址,不行
*调试了几天,原因是" Unable to handle kernel paging request at virtual address 0x7E00B000 "
* 后来,还是按照人家的来吧!结果成功了*/
平台:ubuntu10.04 arm内核linux2.6.28
驱动程序
应用程序:
运行结果:
mini6410 实现 linux adc驱动详解--muge0913版
http://blog.csdn.net/muge0913/article/details/7059241/*之前自己根据裸机程序改的,给ADC寄存器地址,不行
*调试了几天,原因是" Unable to handle kernel paging request at virtual address 0x7E00B000 "
* 后来,还是按照人家的来吧!结果成功了*/
平台:ubuntu10.04 arm内核linux2.6.28
驱动程序
#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 <plat/regs-adc.h> #include <mach/map.h> static void __iomem * base_addr; static struct clk *adc_clock; /*#define ADCCON_BASE (0x7E00B000) #define ADCCON (*(volatile unsigned *)(ADCCON_BASE+0x00)) // ADC control #define ADCTSC (*(volatile unsigned *)(ADCCON_BASE+0x04)) // ADC touch screen control #define ADCDLY (*(volatile unsigned *)(ADCCON_BASE+0x08)) // ADC start or Interval Delay #define ADCDAT0 (*(volatile unsigned *)(ADCCON_BASE+0x0C)) // ADC conversion data 0 #define ADCDAT1 (*(volatile unsigned *)(ADCCON_BASE+0x10)) // ADC conversion data 1 #define ADCUPDN (*(volatile unsigned *)(ADCCON_BASE+0x14)) // 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) */ /*ADC寄存器地址*/ #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 /*根据s3c6410的文档,设置相应的ADC控制器位*/ #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() { printk("<0>adc_init sucessed!\n"); unsigned int preScaler = 0XFF; printk("<0>111111111!\n"); ADCCON = (1<<14)|(preScaler<<6)|(0<<3)|(0<<2); ADCCON |= ADC_START; printk("<0>2222222222!\n"); return 0; } static int adc_open(struct inode *inode ,struct file *filp) { printk("adc_open!\n"); 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) { printk("<0>adc_read!\n"); int ret=0; ADCCON |= ADC_START; while(ADCCON & 0x01);//check if Enable_start is low while(!(ADCCON &0x8000));/*检查转换是否结束*/ ret = ADCDAT0 & 0x3ff; //重点,与参考的不同,我觉得这样才是正确的 copy_to_user(buff,(char *)&ret,sizeof(ret)); return sizeof(ret); } 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(0x7E00B000,0X20);//地址映射 printk("<0>ioremap sucessed!\n"); if(base_addr == NULL) { printk(KERN_ERR"failed to remap\n"); return -ENOMEM; } adc_clock = clk_get(NULL,"adc");//激活adc时钟模块 printk("<0>clk_get sucessed!\n"); 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; int ret; fp = open("/dev/adc_dev",O_RDWR); if(fp<0) printf("open failed!\n"); printf("open sucessed!\n"); for(i=0;i<100;i++) { ret = read(fp,&adc_data,sizeof(adc_data)); printf("read sucessed!\n"); if(ret<0) { printf("read ADC failed!\n"); return -1; } else printf("Read ADC value is: %d\n",adc_data); sleep(1); } close(fp); return 0; }
运行结果:
相关文章推荐
- OK6410之ADC驱动程序 字符设备驱动
- Linux3.6.7在OK6410平台的移植(五)字符设备驱动程序之LED
- OK6410之ADC驱动软件分析---阻塞与非阻塞IO
- ok6410学习笔记(18.linux串口驱动程序设计)
- OK6410字符设备驱动点亮LED
- ok6410学习笔记(18.linux串口驱动程序设计)
- 20150226 IMX257 混杂设备miscdevice驱动程序
- 混杂设备驱动程序
- Linux按键驱动程序设计(1)-混杂设备驱动模型
- 修改飞凌OK6410的默认LCD显示设备
- 木其工作室(专业程序代写服务)[原]ok6410学习笔记(18.linux串口驱动程序设计)
- OK6410 Linux下LED驱动程序
- 6410之驱动程序的分层分离,总线设备驱动模型
- 飞凌嵌入式OK6410开发板的LED驱动程序
- OK6410按键驱动程序(Linux),测试通过后分享给大家
- OK6410按键驱动程序(改)亲测可以运行
- 修改飞凌OK6410的默认LCD显示设备
- mini6410 led驱动程序(混杂设备增加了详细注释)
- OK6410 linux第一个字符型设备驱动:LED驱动
- Linux下的led驱动程序,ok6410