Learn ok6410 ADC module with cainiao

Source: Internet
Author: User

Today, the company's second version of the infrared remote control has been improved, and it is also more sensitive when running on Android, gpio simulation of SPI can also work, read the book, corrected the meeting, it is more than when I return to the dormitory. Think about it. There is an ad module on ok6410. After searching for information on the Internet, I found that I could try to find out if I could. Okay, it took me almost an hour. Haha, I finally got it done.

See the code below:

 

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

 

The Code was not written by myself. For reference, I removed unnecessary code a little and added some test prints to digest it.

The above code mainly uses the two registers.

Let's take a look at the principle diagram and pins of the AD module.

Its pin is

 

Let's take a look at these two registers.

 

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

Here 1 <14 is to start the adconversion. Prescaler <6 is the value of the ADC preset 0 x ff, 0 <3 indicates that the ADC channel 0 is the ad module. Then
0 <2 is the normal operation mode.

After the analysis, the control register is the data register.

 

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

 

While (adccon & 0x01); judge whether the adconversion is complete. While (! (Adccon & 0x8000); determines whether the adswitch is over.
Ret = adcdat0 & 0x3ff;, the value after normal ADC conversion.

That's it. It's easy? Okay. You can only say that.

Then, makefile:

 

obj-m :=adc.o   


Then create a makemod. The Code is as follows:

 

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

 


Then, you only need source makemod to compile it into buzzer. Ko.

 

OK, the driver is like this, and then the application

 

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

 

Then 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

Finally, it was done on the board. Copy ADC. Ko and adcapp to the SD card and then to the board. Start test:

Init is in. If no error is displayed, everything is OK.

Then the mknod Device File

Okay, the device node is OK, and then the test program is started.

At the beginning, the potentiometer is positioned like this, and then the potentiometer is rotated.

If the rotation range is greater:

End:

 

OK. The test passed. Tomorrow is Friday, and the weekend is over. The weather is getting hotter and hotter. Continue to work hard. I found that my knowledge system is far from enough, which is quite different from my colleagues. Come on ....

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.