Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830947
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: LINUX

2017-02-21 21:18:09

6. 用户态 ADC 编程    
    EasyARM-iMX283A 提供了两种不同速度的 ADC 数据采集通道,一种 Low-Resolution
    ADC( LRADC 低分辨率),底板引出 3 路: ADC0、 ADC1、 ADC6;另一种为 High-Speed
    ADC(HSADC 高速 ADC,每秒可达 2MSPS),只有 1 路。 4 路 ADC 分别对应 EasyARMiMX283A
    排母的 A0、 A1、 A6、 HSADC。
    
    ADC0、 ADC1、 ADC6 三路通道内部含有一个除 2 模拟电路,在未开启内部除 2 电路
    时,其量程为 0~1.85V,开启除 2 电路时,量程为 0~3.7V。 ADC 参考源来自内部参考电压
    1.85V。另外,驱动提供了一个内部读取电池电压的接口,此通道内部有除 4 电路。 HSADC
    为 2M 采样率的高速 ADC,可用于摄像头数据采集。
    
6.1 ADC 驱动模块的加载
    EasyARM-iMX283A ADC 的驱动有两种,一种是 LRADC 对应的驱动。另一种为 HSADC
    对应的驱动。下面分别对两种驱动加载方式作出介绍。
    
    1. LRADC 对应的驱动加载
        ADC0、 ADC1、 ADC6 对应的驱动是以动态加载模块的形式提供,因此在 ADC 操作之
        前要先安装 lradc 驱动模块。
        驱动模块在哪里?
        root@EasyARM-iMX283 ~# insmod /root/lradc.ko
        adc module init!
        
    2. HSADC 对应的驱动加载
        内核默认以动态加载模块方式编译 HSADC 驱动。在 EasyARM-iMX283A 光盘镜像的
        linux 内核目录执行下面命令:
        root@Linux-host:~/linux-2.6.35.3# make modules
        
        就可以在“ linux-2.6.35.3/driver/misc/” 生成“ mxs-hsadc.ko” HSADC 驱动模块。加载动态
        驱动模块与上面介绍的“ 安装 lradc 驱动” 方式相同。
        如果需要静态加载此驱动,需要配置驱动为静态加载模式:
        root@Linux-host:~/linux-2.6.35.3# make menuconfig
        在内核选项里选择“ MX28 High Speed ADC”。选项路径:
        Device Drivers->
        [*] Misc devices --->
            <> MX28 High Speed ADC
            
        按空格键可以切换模块编译方式。选择“ *”,内核编译时会将高速 ADC 驱动以静态方
        式编译。重新烧写内核后高速 ADC 驱动就会生效。
        
6.2 操作接口
    本着简单易用原则, ADC 使用字符设备文件操作。下面分别介绍。
    1. LRADC 操作接口
        LRADC 操作仅使用了 ioctl 函数,读取电压操作代码如下:
        ...
        #include "lradc.h"
        #define LRADC_DEV         /dev/magic-adc"
        #define CMD_VOLTAGE     IMX28_ADC_CH0         /* 通道 0 读取命令 */
        ....
        int value, fd,;
        fd = open(LRADC_DEV, 0); /* 打开 ADC 设备 */
        ....
        ioctl(fd, , CMD_VOLTAGE, &value); /* 发送采集命令,采集数据保存在 value 中*/
        其中, value 为读取的电压值, IMX28_ADC_CH0 读取通道 0 命令号,命令号定义位于
        “ lradc.h”头文件中,通过 ioctl 系统调用后,返回值保存在 value 中,需要将这个值转换为
        电压值。具体转化见文档。
        
    2. HSADC 操作接口
    
        当加载内核自带的驱动mxs-hsadc.ko时,将会生成内核文件/dev/mxs-hsadc0:
        root@EasyARM-iMX283 /mnt/app_for_hardware# insmod mxs-hsadc.ko
        root@EasyARM-iMX283 /mnt/app_for_hardware# lsmod
        Module                  Size  Used by
        mxs_hsadc               4378  0
        root@EasyARM-iMX283 /mnt/app_for_hardware# ls /dev/mxs-hsadc0 -l
        crw-rw----    1 root     root      250,   0 Jan  1 01:22 /dev/mxs-hsadc0
    
        手动建立一个字符设备节点:
        HSADC 为字符设备,主设备号为 250,次设备号为 0,设备节点需要用户创建。创建命令如下:
        root@EasyARM-iMX283A ~# mknod /dev/hsadc c 250 0
        HSADC 只要通过 read 系统调用实现。驱动程序默认使用 12 位精度采集数据。下面的
        示例代码实现了读取 len 个数据到 buff 中。
        #define HRADC_DEV "/dev/hsadc" /* 高速设备名 */
        int read_hsadc(short *buff, int len)
        {
            static int fd,flag = 0;
            int ret,i,value;
            fd = open (HRADC_DEV,0);
            ....
            ret = read (fd ,buff,len); /* read 系统调用,返回采集数据*/
            ....
            for(i=0;i             {
                buff[i] &= 0x3ff; /* 数据低 12 位有效 */
            }
        }
        
6.3 C 程序操作示例

    下面分别给出 LRADC 和 HSADC 的 C 程序操作范例。
    1. C 程序操作 LRADC
        程序清单 6.1 所示例程实现的功能是:读取 AP-283Demo 学习套件的电阻电压和 R32
        发热电阻温度。
        代码执行流程:首先获取用户需要读取数据量。然后打开设备,发送读取命令并打印返
        回电压值,然后将读取的温度传感器的电压转化为温度并打印。
        
        程序清单 6.1 ADC 操作示例
          

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <math.h>
  6. #include <sys/ioctl.h>
  7. #include "lradc.h"

  8. #define LRADC_DEV        "/dev/magic-adc"    /* adc 设备文件名 */
  9. #define CMD_VOLTAGE     IMX28_ADC_CH0        /* 通道 0 读取命令 */
  10. #define CMD_TEMPTURE    IMX28_ADC_CH1        /* 通道 1 通读读取命令 */
  11. #define R33             2000
  12. #define V_ADC            3.3
  13. #define T1                (273.15 + 25)
  14. #define R1                27600
  15. #define B                3435*1000

  16. int main(int argc,char **argv)
  17. {
  18.     short buff[100];
  19.     int i, fd, value_R, value_T, cmd, ret, len = 2;
  20.     float voltage, RT, temp,resistance;
  21.     fd = open (LRADC_DEV,O_RDONLY); /* 打开 ADC 设备 */
  22.     if (fd < 0) {
  23.         perror("open");
  24.         close(fd);
  25.         return 0;
  26.     }
  27.     
  28.     while(1)
  29.     {    
  30.         usleep(1000000);
  31.         ret = ioctl(fd, CMD_VOLTAGE, &value_R); /* 读取通道 0 */
  32.         if(ret != 0){
  33.             perror("ioctl");
  34.             return -1;
  35.         }
  36.         
  37.         ret = ioctl(fd, CMD_TEMPTURE, &value_T); /* 读取通道 1 */
  38.         //close(fd);
  39.         if(ret != 0) {
  40.             perror("ioctl");
  41.             return -1;
  42.         }

  43.         resistance    = (value_R*1.85)/4096.0; /* 计算通道 0 测量电压 */
  44.         voltage     = (value_T*1.85)/4096.0; /* 计算通道 1 测量电压 */
  45.         RT            = (V_ADC/voltage - 1)*R33; /* 计算热敏电阻的阻值 */
  46.         temp        = 3435/log(10*RT) - 273.15; /* 计算热敏电阻的温度 */
  47.         
  48.         printf("A10 Voltage: %fV ;A11 Temperature: %f\n", resistance, temp);        
  49.     }

  50.     close(fd);
  51.     return 0;
  52. }


    注意,执行 adc 代码前,必须要加载 lradc.ko 模块。编译代码指令如下:
    
    编译应用程序:
    # arm-linux-gcc -o lradc_app -lm lradc_app.c
    
    编译驱动程序:lradc.ko
    root@Linux-host:/nfsroot/app_for_hardware/6th_adc/lradc/lradc_driver# make
    root@Linux-host:/nfsroot/app_for_hardware/6th_adc/lradc/lradc_driver# ls
    built-in.o  lradc.h   lradc.mod.c  lradc.o   modules.order   README.txt
    lradc.c     lradc.ko  lradc.mod.o  Makefile  Module.symvers
    
    加载驱动:
    # insmod lradc.ko
    执行程序:
    # ./lradc_app
    可以看到打印的温度信息:
    root@EasyARM-iMX283 /mnt/app_hardware/6th_adc/lradc/lradc_appTest# ./lradc_app
    A10 Voltage: 0.812085V ;A11 Temperature: 16.143188
        
    程序1:只打印一次sensor的值。
    程序2:每隔一秒打印一次,一直打印。
    
    
    2. C 程序操作 HSADC
        程序清单 6.2 实现的功能是:读取 AP-283Demo 学习套件的发热电阻温度。
        代码执行流程:首先获取用户需要读取数据量。然后打开设备,使用 read 系统调用读
        取数据,然后将数据取平均值并转换为温度并打印。    
        程序清单 6.2 HSADC 操作示例
       

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <math.h>

  6. #define R33         2000
  7. #define V_ADC         3.3
  8. #define T1             (273.15 + 25)
  9. #define R1             27600
  10. #define B             3435*1000
  11. #define HSADC         "/dev/mxs-hsadc0"

  12. int main(int argc,char **argv)
  13. {
  14.     unsigned int buff[100];
  15.     int i, fd, value = 0, cmd, ret, len = 2;
  16.     float voltage, RT, temp,tmp;
  17.     int cnt;
  18.     
  19.     if(argv[1] == NULL) {
  20.         printf("uasge: ./hsadc [data length]\n");
  21.         printf("data length >= 1\n");
  22.         return 0;
  23.     }
  24.     
  25.     fd = open (HSADC,O_RDONLY); /* 打开 ADC 设备 */
  26.     if (fd < 0) {
  27.         perror("open");
  28.         close(fd);
  29.         return 0;
  30.     }

  31.     while(1)
  32.     {
  33.         usleep(1000000); // 1 second

  34.         cnt = atoi(argv[1])*2;
  35.         ret = read(fd, buff, cnt); /* 读取 HSADC */
  36.         printf("ret: %d, cnt: %d\n", ret, cnt);
  37.         if(ret < 0){
  38.             perror("ioctl");
  39.             return -1;
  40.         }
  41.         //close(fd);
  42.         
  43.         ret >>= 1;
  44.         printf("ret: %d\n", ret);
  45.         
  46.         for(i = 0; i < ret; i++)
  47.         {
  48.             value += (buff[i] & 0xfff);
  49.         }
  50.         
  51.         value     = value/ret;
  52.         voltage = (value*1.85)/4096.0;         /* 计算通道 1 测量电压 */
  53.         RT         = (V_ADC/voltage - 1)*R33;     /* 计算热敏电阻的阻值 */
  54.         temp     = 3435/log(10*RT) - 273.15; /* 计算热敏电阻的温度 */
  55.         printf("A11 Temperature: %f\n",temp);
  56.         
  57.     }
  58.     
  59.     close(fd);
  60.     
  61.     return 0;
  62. }


    
    注意,执行 adc 代码前,必须要加载 mxs-hsadc.ko 模块或内核已经有静态 hsadc 驱动。
    驱动路径:/drivers/misc/mxs-hsadc.ko
    加载驱动
        #insmod mxs-hsadc.ko
    可以看到生成的设备文件为:/dev/mxs-hsadc0
    
    编译应用程序:hsadc
    # arm-linux-gcc -o hsadc hsadc.c -lm
    
    把编译好的可执行文件 adc 下载到开发板,设置可执行权限。
    root@EasyARM-iMX283 ~# chmod 777 hsadc
    将 AP-283Dem 配板排针插入 EasyARM-iMX283A 排母, 并使用杜邦线将排母对应的
    A1 与 HSADC 短接(就是母排J1的第17脚和第19脚短接), 执行代码。
    root@EasyARM-iMX283 ~# ./hsadc 10
    执行命令中,数字 10 表示需要读取 10 次采样的平均值。
阅读(1482) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~