• ZigBee开发(7)--基础实验AD


    一、A/D转换的基本工作原理

            将时间上连续变化的模拟量转化为脉冲有无的数字量,这一过程就叫做数字化,实现数字化的关键设备是ADC

            ADC:数模转换器,将时间和幅值连续的模拟量转化为时间和幅值离散的数字量,A/D转换一般要经过采样保持量化编码4个过程。

    二、CC2530的A/D转换模块

            CC2530的ADC模块支持最高14位二进制的模拟数字转换,具有12位的有效数据位,它包括一个模拟多路转换器,具有8个各自可配置的通道,以及一个参考电压发生器。

            该ADC模块有如下主要特征:

            <1> 可选取的抽取率,设置分辨率(7~12位)。

            <2> 8个独立的输入通道,可接收单端或差分信号。

            <3> 参考电压可选为内部单端、外部单端、外部差分或AVDD5。

            <4> 单通道转换结束可产生中断请求。

            <5> 序列转换结束可发出DMA触发。

            <6> 可将片内温度传感器作为输入。

            <7> 电池电压测量功能。

    三、ADC模块的信号输入

            端口0引脚可以配置为ADC输入端,依次为AIN0~AIN7

            <1> 可以把输入配置为单端输入或差分输入。

            <2> 差分输入对:AIN0~AIN1、AIN2~AIN3、AIN4~AIN5、AIN6~AIN7。

            <3> 片上温度传感器的输出也可以作为ADC的输入用于测量芯片的温度。

            <4> 可以将一个对应AVDD5/3的电压作为ADC输入,实现电池电压监测。

            <5> 负电压和大于VDD的电压都不能用于这些引脚。

            <6> 单端电压输入AIN0~AIN7,以通道号码0~7表示;四个差分输入对则以 通道号码8~11表示;温度传感器的通道号码为14AVDD5/3电压输入的通道号码为15

    四、ADC相关的几个概念

            <1> 序列ADC转换:可以按序列进行多通道的ADC转换,并把结果通过DMA传送到存储器,而不需要CPU任何参与。

            <2> 单通道ADC转换:在程序设计中,通过写ADCCON3寄存器触发单通道ADC转换,一旦寄存器被写入,转换立即开始。

            <3> 参考电压:内部生成的电压、AVDD5引脚、适用于AIN7输入引脚的外部电压,或者 适用于AIN6~AIN7输入引脚的差分电压。

            <4> 转换结果:数字转换结果以2的补码形式表示。对于单端,结果总是正的。对于差分配置,两个引脚之间的差分被转换,可以是负数。 当ADCCON1.EOC设置为1时,数字转换结果可以获得,且结果总是驻留在ADCH和ADCL寄存器组合的MSB段中。

            <5> 中断请求:通过写ADCCON3触发一个单通道转换完成时,将产生一个中断,而完成 一个序列转换时,是不产生中断的。当每完成一个序列转换,ADC将产生 一个DMA触发。

            <6> 寄存器:ADC有两个数据寄存器:ADCLADCH;三个控制寄存器:ADCCON1ADCCON2ADCCON3;分别用来配置ADC并返回转换结果。

    【1】配置APCFG寄存器

            当使用ADC时,端口0的引脚必须配置为ADC模拟输入。要配置一个端口0引脚为一个ADC输入,APCFG寄存器中相应的位必须设置为1。这个寄存器的默认值是0,选择端口0为非模拟输入,即作为数字I/O端口。

            注意:APCFG寄存器的设置将覆盖P0SEL的设置。

    【2】配置ADCCON3寄存器

            单通道的ADC转换,只需将控制字写入ADCCON3寄存器即可。

    【3】ADC初始化

            主要对端口的功能进行选择,设置其传输方向,并将端口设置为模拟输入。

    【4】ADC数据采集

            首先将ADCIF标志位清0,接着对ADCCON3寄存器设置,该寄存器一旦被写入,转换立即开启;然后等待ADCIF置1,这时候转换完成,读取数据即可。

    /**************************************
    程序描述:通过内部 AD 控制把温度信息通过
    串口发送给上位机,部分芯片误差
    较大,需要校准。手摸着芯片,温度
    明显变大。
    **************************************/
    #include <ioCC2530.h>
    //#include “InitUART_Timer.h” //注意在 option 里设置路径
    #include<stdio.h>
    
    #define uint unsigned int
    #define uchar unsigned char
    
    /*===================UR0初始化函数====================*/
    void usart_Init(void)
    {
      PERCFG &= ~0x01;//位置 1 P0 口
      P0SEL |= 0x0c;//P0_2,P0_3用作串口,第二功能
      P2DIR &= ~0XC0; //P0 优先作为 UART0 ,优先级
      U0CSR |= 0x80;//UART 方式
      U0UCR |= 0x0c;
      
      U0GCR |= 11;//U0GCR 与 U0BAUD 配合
      U0BAUD |= 216;// 波特率设为 115200
      
      U0CSR |= 0x40;//允许接收
      EA = 1;//开总中断
      URX0IE = 1;//开串口接收中断
      
      UTX0IF = 0;//UART0 TX 中断标志初始置位 
      URX0IF = 0;//UART0 RX 中断标志初始置位 
    }
    void usart_Send_Byte(uchar c)
    {
      U0DBUF = c;
      while( !UTX0IF );//等待发送完成标志位置1
      UTX0IF = 0;
    }
    void usart_Send_String(uchar *data,uint len)
    {
      while(len--)
      {
        usart_Send_Byte(*data++);
      }
    }
    /****************************************************************
    温度传感器初始化函数
    ****************************************************************/
    void initTempSensor(void)
    {
      EA = 0;
      CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振
      while(CLKCONSTA & 0x40); //等待晶振稳定为 32M
      CLKCONCMD &= ~0x47; //设置系统主时钟频率为
      //DISABLE_ALL_INTERRUPTS(); //关闭所有中断
      //InitClock(); //设置系统主时钟为 32M
      //TR0=0X01; //set ‘1’ to connectthe temperature sensorto theSOC_ADC.
      //ATEST=0X01; // Enablesthe temperature sensor
    }
    /****************************************************************
    读取温度传感器 AD 值函数
    ****************************************************************/
    float getTemperature(void){
      uint value;
      ADCCON3 = (0x3E); //选择 1.25V 为参考电压;12 位分辨率;对片内温度传感器采样
      ADCCON1 |= 0x30; //选择 ADC 的启动模式为手动
      ADCCON1 |= 0x40; //启动 AD 转化
      while(!(ADCCON1 & 0x80)); //等待 AD 转换完成
      value = ADCL >> 4; //ADCL 寄存器低 4 位无效
      value |= (((uint)ADCH) << 4);
      return (value-1367.5)/4.5-4; //根据 AD 值,计算出实际的温度,芯片、
    //手册有错,温度系数应该是 4.5 /℃
    //进行温度校正,这里减去 4℃(不同芯片根据具体情况校正)
    }
    /****************************************************************
    主函数
    ****************************************************************/
    void main(void)
    {
      uchar I;
      uchar TempValue[6];
      float AvgTemp;
      usart_Init(); //初始化串口
      initTempSensor(); //初始化 ADC
      while(1)
      {
        AvgTemp = 0;
        for(I = 0 ; I < 64 ; I++)
        {
          AvgTemp += getTemperature();
          AvgTemp=AvgTemp/2; //每次累加后除 2
        }
      /****温度转换成 ascii 码发送****/
        TempValue[0] = (unsigned char)(AvgTemp)/10 + 48; //十位
        TempValue[1] = (unsigned char)(AvgTemp)%10 + 48; //个位
        TempValue[2] = '.'; //小数点
        TempValue[3] = (unsigned char)(AvgTemp*10)%10+48; //十分位
        TempValue[4] = (unsigned char)(AvgTemp*100)%10+48; //百分位
        TempValue[5] = ''; //字符串结束符
        usart_Send_String( TempValue,6);
        //Delayms(2000); //使用 32M 晶振,故这里 2000 约等于 1S
      }
    }
  • 相关阅读:
    前端周刊第一期
    Java CAS 原理详解
    【转载】Linux系统调用SYSCALL_DEFINE详解
    简述伪共享和缓存一致性MESI
    exchange发邮件
    Flutter屏幕适配(自适应)方案
    dart类初始化 future方案
    windows下postgresql自启动
    How can I call an async method in StatelessWidget.build method?
    实战分层架构
  • 原文地址:https://www.cnblogs.com/tianxxl/p/9870721.html
Copyright © 2020-2023  润新知