首页 > 其他分享 >和菜鸟一起学OK6410之ADC模块

和菜鸟一起学OK6410之ADC模块

时间:2023-01-15 16:03:32浏览次数:34  
标签:__ struct int 菜鸟 dev adc include OK6410 ADC


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

        下面看代码:



#include <linux/module.h>  

#include <linux/types.h>

#include <linux/fs.h>

#include <linux/errno.h>

#include <linux/mm.h>

#include <linux/sched.h>

#include <linux/init.h>

#include <linux/cdev.h>

#include <asm/io.h>

#include <asm/system.h>

#include <asm/uaccess.h>

#include <linux/device.h> /* device_create()*/

#include <asm/io.h>

#include <asm/irq.h>

#include <asm/uaccess.h>

#include <mach/map.h>

#include <plat/regs-adc.h>

#include <mach/map.h>





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 <[email protected]>");

MODULE_LICENSE("Dual BSD/GPL");



module_param(adc_major, int, S_IRUGO);



module_init(adc_dev_init);

module_exit(adc_dev_exit);

 

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

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

AD模块的原理图和管脚吧

和菜鸟一起学OK6410之ADC模块_fp


        其管脚是

和菜鸟一起学OK6410之ADC模块_fp_02

 

        再来看看这两个寄存器吧


和菜鸟一起学OK6410之ADC模块_makefile_03

         

和菜鸟一起学OK6410之ADC模块_makefile_04


 

       

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

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

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

和菜鸟一起学OK6410之ADC模块_module_05

 


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 <stdio.h>     

#include <fcntl.h>

#include <unistd.h>



#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.o

adcapp.o:adcapp.c

$(CC) -c adcapp.c



clean :

rm adcapp.o

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

和菜鸟一起学OK6410之ADC模块_module_06


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

mknod设备文件

和菜鸟一起学OK6410之ADC模块_fp_07


OK,接着就是测试程序了。

和菜鸟一起学OK6410之ADC模块_struct_08


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

和菜鸟一起学OK6410之ADC模块_module_09


        再旋转范围大点的:

和菜鸟一起学OK6410之ADC模块_module_10


        最后结束:


 

和菜鸟一起学OK6410之ADC模块_makefile_11

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

标签:__,struct,int,菜鸟,dev,adc,include,OK6410,ADC
From: https://blog.51cto.com/u_15940062/6008793

相关文章