博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
和菜鸟一起学OK6410之ADC模块
阅读量:4644 次
发布时间:2019-06-09

本文共 4969 字,大约阅读时间需要 16 分钟。

        今天,完善了公司第二版的红外遥控器,并且在android上跑起来时也比较灵敏了,GPIO模拟的SPI也可以工作了,看了会书,修正了会,回到宿舍也已经9点多了。想想,OK6410上还有个AD模块呢。网上找了找资料,发现还是可以去尝试下可不可以实现的。好吧,花了我快一个小时了,哈哈,终于搞定了。

        下面看代码:

 

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* device_create()*/ #include
#include
#include
#include
#include
#include
static void __iomem *base_addr; #define __ADCREG(name) (*(volatile unsigned long *)(base_addr + name)) #define ADCCON __ADCREG(S3C_ADCCON) // ADC control #define ADCDAT0 __ADCREG(S3C_ADCDAT0) // ADC conversion data 0 #define ADC_START (1 << 0) #define ADC_SIZE 0x1000 #define ADC_MAJOR 240 static int adc_major = ADC_MAJOR; struct adc_dev { struct cdev cdev; unsigned char mem[ADC_SIZE]; }; struct adc_dev *adc_devp; static int adc_init(void) { 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) {printk("$$$$$%s$$$$$\n", __func__); adc_init(); return 0; } static int adc_release(struct inode *inode, struct file *filp) { printk("$$$$$$%s$$$$$\n", __func__); return 0; } static ssize_t adc_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) { unsigned int count = size; int ret = 0; printk("$$$$$%s$$$$$\n", __func__); ADCCON |= ADC_START; while(ADCCON & 0x01);//check if Enable_start is low while(!(ADCCON &0x8000)); ret = ADCDAT0 & 0x3ff; count = copy_to_user(buf,(char *)&ret,sizeof(ret)); return sizeof(ret); } static const struct file_operations adc_fops = { .owner = THIS_MODULE, .read = adc_read, .open = adc_open, .release = adc_release, }; static void adc_setup_cdev(struct adc_dev *dev, int index) { int err, devno = MKDEV(adc_major, index); cdev_init(&dev->cdev, &adc_fops); dev->cdev.owner = THIS_MODULE; err = cdev_add(&dev->cdev, devno, 1); if (err) printk(KERN_NOTICE "Error %d adding LED%d", err, index); } struct class *myclass; int adc_dev_init(void) { int result; printk("$$$$$$%s$$$$$$\n", __func__); dev_t devno = MKDEV(adc_major, 0); if (adc_major) result = register_chrdev_region(devno, 1, "adc"); else { result = alloc_chrdev_region(&devno, 0, 1, "adc"); adc_major = MAJOR(devno); } if (result < 0) return result; adc_devp = kmalloc(sizeof(struct adc_dev), GFP_KERNEL); if (!adc_devp) { result = - ENOMEM; goto fail_malloc; } memset(adc_devp, 0, sizeof(struct adc_dev)); adc_setup_cdev(adc_devp, 0); myclass = class_create(THIS_MODULE,"test_char"); device_create(myclass, NULL, MKDEV(adc_major,0), NULL, "adc"); base_addr = ioremap(0x7E00B000,0X20); if(base_addr == NULL) { printk("failed to remap\n"); return -ENOMEM; } return 0; fail_malloc: unregister_chrdev_region(devno, 1); return result; } void adc_dev_exit(void) { cdev_del(&adc_devp->cdev); kfree(adc_devp); unregister_chrdev_region(MKDEV(adc_major, 0), 1); class_destroy(myclass); device_destroy(myclass,MKDEV(adc_major,0)); iounmap(base_addr); } MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_LICENSE("Dual BSD/GPL"); module_param(adc_major, int, S_IRUGO); module_init(adc_dev_init); module_exit(adc_dev_exit);

 

        代码不是本人写的,参考的,然后稍微去掉不必要的,加了些测试打印,用以消化。

看上面的代码,主要用到的就是那两个寄存器了。

        先看下AD模块的原理图和管脚吧

        其管脚是

 

        再来看看这两个寄存器吧

         

 

       

ADCCON = (1<<14) | (preScaler<<6) | (0<<3) | (0<<2);

        这里的1<<14就是启动AD转换。preScaler<<6就是ADC预定标器值0xff了,0<<3就表示adc通道0,就是这个AD模块了。然后 0 << 2就是正常运作模式了。

        好了分析完控制寄存器那么就是数据寄存器了。

 

while(ADCCON & 0x01);//check if Enable_start is low     while(!(ADCCON &0x8000));    ret = ADCDAT0 & 0x3ff;

 

         while(ADCCON & 0x01);判断是否AD转换好了。while(!(ADCCON &0x8000));判断AD转换是否结束。 ret = ADCDAT0 & 0x3ff;,正常的ADC转换后的值。

        就这样,搞定了,很简单?还行吧,差不多吧,只能说。

        接着就是makefile了:

 

obj-m :=adc.o

      然后建个makemod,代码如下

 

make -C /home/eastmoon/work/linux2.6.28/ M=`pwd` modules

 

        然后只要source makemod就可以编译成buzzer.ko

 

        OK,驱动就这么着了,然后就是应用程序了

 

#include 
#include
#include
#define DEVICE "/dev/myadc" int main() { int fp,adc_data,i; int ret; fp = open(DEVICE, O_RDWR); if(fp < 0) { printf("open failed!\n"); return -1; } while(1) { ret = read(fp,&adc_data,sizeof(adc_data)); 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; }

 

        接着makefile

CC = /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-gcc  adcapp:adcapp.o       $(CC) -o adcapp adcapp.oadcapp.o:adcapp.c        $(CC) -c adcapp.c clean :       rm adcapp.o

        终于搞定,于是便是到板子上去调试了。把adc.koadcapp拷贝到SD卡上,然后再拷贝到板子上。开始测试:

        Init进去了,没提示错误,表示一切OK

        接着mknod设备文件

        好了,设备节点OK,接着就是测试程序了。

        一开始电位器的位置是这样的,然后旋转电位器

        再旋转范围大点的:

        最后结束:

 

        OK,测试都通过了,明天就是周五了,又是周末了,天气是越来越热了,继续努力。发现自己的知识体系还远远不够,和同事相比还是有很大的差别啊。加油,come on。。。。

转载于:https://www.cnblogs.com/wuyida/archive/2012/07/05/6300082.html

你可能感兴趣的文章
Genymotion下载模拟器失败解决方案
查看>>
The Apostrophe and the Quote Function ‘和引用函数 未翻译完)
查看>>
win8开发入门——国际化(多语言支持)
查看>>
科学计算三维可视化---Mayavi入门(Mayavi库的基本元素和绘图实例)
查看>>
python学习笔记-问题
查看>>
您对无法重新创建的表进行了更改或者启用了“阻止保存要求重新创建表的更改”选项【转】...
查看>>
生理周期
查看>>
(蓝桥杯)第八届A组C/C++方格分割
查看>>
react 版的知乎日报
查看>>
使用CSS3制作漂亮的按钮
查看>>
sql server 2014登录账号
查看>>
使用OutputDebugString输出调试信息
查看>>
leetcode 之Candy(12)
查看>>
kv.go
查看>>
利用截取字符串,生成已声明的字符串中的4位随机验证码。
查看>>
Spring 事务模型
查看>>
【MM系列】SAP S/4 HANA BP创建客户/供应商的一点想法
查看>>
【HANA系列】SAP HANA XS使用JavaScript数据交互详解
查看>>
【HANA系列】SAP HANA SQL获取上周的周一
查看>>
对称矩阵
查看>>