查看: 4050|回复: 0

基于AVR XMEGA-A3BU Xplained控制器的Wifi小车制作(9)---AD

[复制链接]
  • TA的每日心情
    擦汗
    2024-9-30 02:33
  • 签到天数: 444 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-4-18 23:10:39 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 木子鱼 于 2013-5-8 20:55 编辑

           昨晚偶翻看宏晶公司的STC89C51的资料PDF,发现上面说STC89C51芯片自带有AD转换器,即它的P1口可以设定工作在ADC模式,很惊奇! 依稀记得大二上单片机课程时老师说ATMEL 89S51芯片内部没有AD,如果需要ADC就要另外扩展ADC的电路。以前吧,我很怕接触AD,觉得模拟传感器稳定性很差,精度也不高,还要自己去设定转换量化规则,所以一直都避免使用模拟传感器,也就不用去考虑ADC,然后怀着兴趣去看完了 PDF,发现原来ADC没有我想象的那么难。
            当然我知道 XMEGA-A3BU Xplained板子上自带有ADC, 共有16路 ,PA 、PB 都可用作ADC,可是官方文件说ADC的精度只有12位,共有16路,PA0-PA7,PB0-PB7,为什么不把精度做成16位? 难道是PA0-PA6,PB0-PB3,这样就有12位的精度了?  不懂!欢迎高手朋友一起探讨
              迫不及待打开ASF 看看官方给出的关于ADC的代码哈:
    方法还是跟上篇写的一样,打开ASF Explorer  点击菜单项里的ASF Wizard  然后看到有ADC  ,选中添加 ,看到了DAC ,顺便也添加进去,哈哈
                                                 ad1.jpg
    点开Quick Start Guide,看到官方给出代码:
    #define MY_ADC            ADCA     //选择AD转化器  因为有ADCA (PA)    ADCB (PB)      
    #define MY_ADC_CH     ADC_CH0

    static void adc_init(void)
    {
         struct adc_config adc_conf;
         struct adc_channel_config adcch_conf;

         adc_read_configuration(&MY_ADC, &adc_conf);
         adcch_read_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);

         adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,
                 ADC_REF_BANDGAP);//配置转换模式 unsigned, 12-bit (转换精度),内部参考输入为1V
         adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);//转换器触发方式:手动触发
         adc_set_clock_rate(&adc_conf, 200000UL);

         adcch_set_input(&adcch_conf, ADCCH_POS_PIN0, ADCCH_NEG_NONE, 1);//设置为单端输入,即只能输入正电压,不能输入负电压

         adc_write_configuration(&MY_ADC, &adc_conf);
         adcch_write_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);
    }
         到这里,我懂了上面的问题,官方说ADC的精度有12位,指的是PA0-PA7 PB0-PB7每一路都有12位的转换精度。厉害!
    然后我又在想,为什么只把精度做到12位呢? 做到20,30·····越多不是越好?也许ATMEL 公司会觉得精度做的越高,会不会越需要更多的计算量和计算时间。  突然想到进程的概念,如果CPU一直做比较运算,精度越高,需要算的位数越多,会浪费资源。
          再看怎样进行ADC的程序开发:
    sysclk_init();
    adc_init();
    uint16_t result;//定义一个变量用来存储转换后的值

    adc_enable(&MY_ADC);//使能ADC

    adc_start_conversion(&MY_ADC, MY_ADC_CH);//开始转换
    adc_wait_for_interrupt_flag(&MY_ADC, MY_ADC_CH);//检测转换完成标志位,如果转换完成了,下面就可以进行数据读取了

    result = adc_get_result(&MY_ADC, MY_ADC_CH);
    在工程文件中打开adc.h
    找到
    static inline void adc_wait_for_interrupt_flag(ADC_t *adc, uint8_t ch_mask)
    {
    do { } while (adc_get_interrupt_flag(adc, ch_mask) != ch_mask);
    adc_clear_interrupt_flag(adc, ch_mask);
    }
    在这个函数里,首先是检测转换完成标志位,如果转换完成了,该位为1,然后就把该位置0,否则就一直等待检测,好霸气的语句!
           发现ADC的编程也是有步骤的,前提是把PA口接上模拟的传感器。初始化,设定转换模式(转换精度(官方给出了8位、12位两种选择),参考值),使能,转换,判断检测,读取。觉得其中最有兴趣的应该是采样--转换--量化。
    ························································································································································································································································································································       接着昨晚的写哈,写到这里,我就想试试用ASF自己整合一个温度测量并显示的小程序,很开心,A3BU Xplained板子上 温度传感器、ADC、显示屏 这些必备资源都有。动手!现在继续往工程中添加温度传感器、显示屏的相关资源库。
           还是跟之前的方法一样,打开ASF Explorer 点击菜单项里的ASF Wizard 然后看到有
                               lcd1.jpg
    查看了A3BU Xplained板子的硬件手册,找到这款128*32 像素的LCD的型号为ST7565R  ,然后就选中添加进去,
    在ASF Wizard这里找传感器的资源库,有点小纠结,
                               ntc1.jpg
    不知选择哪个?   先试着选择  Sensor Device Stack吧  。
    打开工程文件里的sensor.h 文件,可以找到这句
    typedef enum {
    SENSOR_TYPE_UNKNOWN            = 0x0000, /**< Unknown or unspecified sensor */
    SENSOR_TYPE_ACCELEROMETER = 0x0001, /**< Single- or multi-axis * accelerometer */
    SENSOR_TYPE_BAROMETER         = 0x0002, /**< Atmospheric air pressure */
    SENSOR_TYPE_COMPASS             = 0x0004,  /**< Single- or multi-axis compass */
    SENSOR_TYPE_GYROSCOPE        = 0x0008,  /**< Single- or multi-axis gyroscope */
    SENSOR_TYPE_HUMIDITY            = 0x0010,  /**< Moisture or humidity sensor */
    SENSOR_TYPE_LIGHT                  = 0x0020,  /**< Ambient light sensor */
    SENSOR_TYPE_MAGNETIC           = 0x0040,  /**< Magnetic sensor */
    SENSOR_TYPE_PRESSURE          = 0x0080,  /**< Pressure sensor */
    SENSOR_TYPE_PROXIMITY         = 0x0100,  /**< Proximity sensor */
    SENSOR_TYPE_TEMPERATURE   = 0x0200,  /**< Single-function temperature */
    SENSOR_TYPE_VOLTAGE            = 0x0400   /**< Single-function voltage */
    } sensor_type_t;
    看到这里我头都大了,点开ASF Explorer 里上面添加进的 Sensor Device Stack
                                      sen1.jpg
    发现跟之前用的很爽的ADC指导教程不一样了,没有类似的Quick Start Guide.而且那些给出的Sensors Drivers 根本点不开,也就找不到对应的NTC传感器的相关操作函数。
    我估计在ASF,把传感器作为一种事件管理机制,首先是配置传感器类型,然后就是触发,然后就是启动ADC,进行相应的转换,读取值。感觉ASF里把传感器这一资源库做得好宏伟---吐槽一下,感觉过于复杂了,功能过多,让人眼花缭乱。
    点开Sensor Device Stack里的 API Documentation  呆了,Sensor 里面的水很深!
           又翻看在第5帖中建立的工程,找到文件里的ntc_sensor.h  和 ntc_sensor.c    (很奇怪为啥我在现在的工程中添加的Sensor资源库中木有找到这样的两个文件。)
           打开  ntc_sensor.c
    #include "stdio.h"
    #include "adc_sensors.h"
    #include "sysfont.h"
    #include "ntc_sensor.h"
    void ntc_sensor_application(void)
    {
         struct gfx_mono_bitmap tempscale;// Bitmap to hold the actual thermometer image用于显示温度值的位图   

      char temperature_string[15];   // String to hold the converted temperature reading

      uint8_t temp_scale;// Variable to hold the image thermometer scale

    int16_t temperature; // Variable for holding the actual temperature in Celsius

      ntc_measure();// Initiate a temperature sensor reading

      tempscale.type = GFX_MONO_BITMAP_RAM;// Struct for holding the temperature scale background

    tempscale.width = 6;
    tempscale.height = 32;
    tempscale.data.pixmap = tempscale_data;
      gfx_mono_draw_rect(0, 0, 128, 32, GFX_PIXEL_SET);// Screen border

      gfx_mono_draw_filled_rect(1, 1, 126, 30, GFX_PIXEL_CLR);// Clear screen

    gfx_mono_draw_progmem_string((char PROGMEM_PTR_T)header, 27, 2, &sysfont); // Draw the header

    // The NTC temperature application loop
    while (1) {
       gfx_mono_put_bitmap(&tempscale, X_POS, 0); // Draw the thermometer

        while (!ntc_data_is_ready());// wait for NTC data to ready

      temperature = ntc_get_temperature(); // Read the temperature once the ADC reading is done

        ntc_measure();// Call a new reading while doing the rest of the calculations
        temp_scale = -0.36 * temperature + 20.25;// Convert the temperature into the thermometer scale
      if (temp_scale <= 0) {
          temp_scale = 0;
      }
      // Draw the scale element on top of the background temperature image
      gfx_mono_draw_filled_rect(X_POS + 2, 3, 2, temp_scale,
        GFX_PIXEL_CLR);
      snprintf(temperature_string, sizeof(temperature_string), "%3i Celsius",
        temperature);
      // Draw the Celsius string
      gfx_mono_draw_string(temperature_string, X_POS + 12, 13, &sysfont);
      // Convert the temperature to Fahrenheit
      temperature = temperature * 1.8 + 32;
      snprintf(temperature_string, sizeof(temperature_string),
        "%3i Fahrenheit", temperature);
      // Draw the Fahrenheit temperature string
      gfx_mono_draw_string(temperature_string, X_POS + 12, 21, &sysfont);
        }
    }
    }
    上面的代码就很容易理解了,可以把新建一个工程,把上面的文件都拖进去,删去DEMO中关于keyboard 相关的操作语句,然后另外添加    adc_sensors.h  adc_sensors.c      bitmaps.h   bitmaps.c    sysfont.h  sysfont.c ,当然最重要的是asf.h  (这里面Include了关于显示屏的一些操作函数) 然后编译,就可以让显示屏一直显示当前的温度值了。




      













    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /5 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-12-21 01:15 , Processed in 0.116858 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.