CC2530 ADC配置步骤

描述

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

A/D转换(Analog-to-Digital Conversion)是将模拟信号转换为数字信号的过程。在各种电子系统中广泛应用,包括微控制器、数据采集系统、传感器接口等。

A/D转换器的基本工作原理如下:

(1)采样(Sampling):A/D转换开始时,模拟输入信号被以固定时间间隔采样。采样是指在一段时间内测量并记录模拟输入信号的电压值或电流值。采样速率决定了每秒对信号进行采样的次数,也称为采样频率。

(2)量化(Quantization):采样后,模拟信号的幅度需要被量化为离散的数字值。这个过程将连续的模拟信号划分为有限数量的离散级别,它决定了数字表示的精度。量化过程涉及将每个采样值映射到最接近的离散级别上。

(3)编码(Encoding):量化后,所得到的离散级别需要被编码为二进制数字。在大多数情况下,使用二进制编码来表示每个离散级别。编码的位数决定了A/D转换器的分辨率和所能表示的数字范围。

(4)样本保持(Sample and Hold):在进行A/D转换的过程中,模拟信号的值需要保持不变,以便进行准确的量化和编码。为了实现这一点,样本保持电路用于在样本期间“冻结”输入信号,直到转换完成。

(5)转换速率(Conversion Rate):A/D转换器的转换速率指的是它可以执行的转换操作的频率。转换速率取决于A/D转换器的性能和应用需求。较高的转换速率对于需要实时数据获取和高速处理的应用是重要的。

A/D转换的基本工作原理包括采样、量化、编码和样本保持等步骤。通过这些步骤,模拟信号被转换为离散的数字表示,从而使得数字系统能够处理和分析这些信号。A/D转换器在许多应用中都扮演着至关重要的角色,例如传感器数据采集、音频处理、仪器测量等。

模拟信号

第二章 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> 差分输入对:AIN0AIN1、AIN2AIN3、AIN4AIN5、AIN6AIN7。

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

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

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

<6> 单端电压输入AIN0AIN7,以通道号码07表示;四个差分输入对则以 通道号码8~11表示;温度传感器的通道号码为14;AVDD5/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有两个数据寄存器:ADCL和ADCH;三个控制寄存器:ADCCON1、ADCCON2、ADCCON3;分别用来配置ADC并返回转换结果。

第五章 ADC配置步骤

【1】配置APCFG寄存器

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

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

模拟信号

【2】配置ADCCON3寄存器

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

模拟信号

模拟信号

【3】ADC初始化

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

【4】ADC数据采集

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

第六章 源代码

【1】内置温度采集

/******************************************************************************
 CC2530模块AD测试程序
 通过内置温度传感器实现温度采集
 ******************************************************************************/
 #include < ioCC2530.h >
 #include < stdio.h >#define uint unsigned int
 // Data
 typedef unsigned char       BYTE;
 ​
 // Unsigned numbers
 typedef unsigned char       UINT8;
 typedef unsigned char       INT8U;
 typedef unsigned short      UINT16;
 typedef unsigned short      INT16U;
 typedef unsigned long       UINT32;
 typedef unsigned long       INT32U;
 ​
 // Signed numbers
 typedef signed char         INT8;
 typedef signed short        INT16;
 typedef signed long         INT32;
 ​
 #define ADC_REF_1_25_V      0x00
 #define ADC_14_BIT          0x30
 #define ADC_TEMP_SENS       0x0E#define DISABLE_ALL_INTERRUPTS() (IEN0 = IEN1 = IEN2 = 0x00)#define ADC_SINGLE_CONVERSION(settings) \\
    do{ ADCCON3 = (settings); }while(0)#define ADC_SAMPLE_SINGLE() \\
   do { ADC_STOP(); ADCCON1 |= 0x40;  } while (0)#define ADC_SAMPLE_READY()  (ADCCON1 & 0x80)#define ADC_STOP() \\
   do { ADCCON1 |= 0x30; } while (0)#define ADC14_TO_CELSIUS(ADC_VALUE)    ( ((ADC_VALUE) > > 4) - 335)/**************************
 系统时钟 不分频
 计数时钟 32分频
 **************************/
 void InitClock(void)
 {
     CLKCONCMD = 0x28;           //时器计数时钟设定为1M Hz,  系统时钟设定为32 MHz 
     while(CLKCONSTA & 0x40);    //等晶振稳定
 }
 ​
 /*****************************************
  串口初始化函数:初始化串口 UART0        
 *****************************************/
 void InitUART0(void)
 {
     PERCFG = 0x00;               //位置1 P0口
     P0SEL = 0x3c;                //P0用作串口
     
     P2DIR &= ~0XC0;                           //P0优先作为UART0    
     U0CSR |= 0x80;                        //串口设置为UART方式
     U0GCR |= 9;             
     U0BAUD |= 59;                         //波特率设为19200
 ​
     UTX0IF = 1;                               //UART0 TX中断标志初始置位1  
     U0CSR |= 0X40;                //允许接收
     IEN0 |= 0x84;                 //开总中断,接收中断
 }
 ​
 /****************************************************************
    串口发送字符串函数                        
 ****************************************************************/
 void UartTX_Send_String(char *Data,int len)
 {
   int j;
   for(j=0;j< len;j++)
   {
     U0DBUF = *Data++;
     while(UTX0IF == 0);
     UTX0IF = 0;
   }
    U0DBUF = 0x0A;        //换行
    while(UTX0IF == 0);
    UTX0IF = 0;
 }
 ​
 /****************************************************************
   延时函数              
 ****************************************************************/
 void Delay(uint n)
 {
     uint i;
     for(i=0;i< n;i++);
     for(i=0;i< n;i++);
     for(i=0;i< n;i++);
     for(i=0;i< n;i++);
     for(i=0;i< n;i++);
 }
 ​
 INT16 AvgTemp;
 ​
 /****************************************************************
 温度传感器初始化函数                      
 ****************************************************************/
 void initTempSensor(void)
 {
    DISABLE_ALL_INTERRUPTS();            //关闭所有中断
    InitClock();                         //设置系统主时钟为32M
    *((BYTE __xdata*) 0x624B) = 0x01;    //开启温度传感器
    *((BYTE __xdata*) 0x61BD) = 0x01;    //将温度传感器与ADC连接起来
 }
 ​
 /****************************************************************
 读取温度传感器AD值函数                        
 ****************************************************************/
 INT8 getTemperature(void)
 {
   UINT8   i;
   UINT16  AdcValue;
   UINT16  value;
 ​
   AdcValue = 0;
   for( i = 0; i < 4; i++ )
   {
     ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);    // 使用1.25V内部电压,12位分辨率,AD源为:温度传感器
     ADC_SAMPLE_SINGLE();                                                   //开启单通道ADC
     while(!ADC_SAMPLE_READY());                 //等待AD转换完成
     value =  ADCL > > 2;                         //ADCL寄存器低2位无效
     value |= (((UINT16)ADCH) < < 6);    
     AdcValue += value;                          //AdcValue被赋值为4次AD值之和
   }
   value = AdcValue > > 2;                        //累加除以4,得到平均值
   return ADC14_TO_CELSIUS(value);               //根据AD值,计算出实际的温度
 }
 ​
 /****************************************************************
 主函数 
 ****************************************************************/
 void main(void)
 {   
       char i;
       char TempValue[10]; 
       InitUART0();                                    //初始化串口
       initTempSensor();                               //初始化ADC
       while(1)
       {
         AvgTemp = 0;
         for(i = 0 ; i < 64 ; i++)
         {
           AvgTemp += getTemperature();              
           AvgTemp > >= 1;                              //每次累加后除2.
         }
          sprintf(TempValue, (char *)"%d ℃", (INT8)AvgTemp);
          UartTX_Send_String(TempValue,4);           
          Delay(50000);
       }
 }
 ​

【2】ADC通道0模拟数据采集

#include "ioCC2530.h"
 /*===============定时器1初始化函数==================*/
 void Init_Timer1()
 {
   T1CC0L = 0xd4;        //设置最大计数值的低8位
   T1CC0H = 0x30;        //设置最大计数值的高8位
   T1CCTL0 |= 0x04;      //开启通道0的输出比较模式
   T1IE = 1;             //使能定时器1中断
   T1OVFIM = 1;          //使能定时器1溢出中断
   EA = 1;               //使能总中断
   T1CTL = 0x0e;         //分频系数是128,模模式
 }
 unsigned char count = 0;
 unsigned char F_time = 0;
 /*================定时器1服务函数====================*/
 #pragma vector = T1_VECTOR
 __interrupt void Timer1_Sevice()
 {
   T1STAT &= ~0x01;      //清除定时器1通道0中断标志
   count++;
   if(count == 10)       //定时1秒到
   {
     F_time = 1;
     count = 0;
   }
 }
 /*===================UR0初始化函数====================*/
 void Init_Uart0()
 {
   PERCFG = 0x00;    //串口0的引脚映射到位置1,即P0_2和P0_3
   P0SEL = 0x0C;     //将P0_2和P0_3端口设置成外设功能
   U0BAUD = 59;      //16MHz的系统时钟产生9600BPS的波特率
   U0GCR = 9;
   U0UCR |= 0x80;    //禁止流控,8位数据,清除缓冲器
   U0CSR |= 0xC0;    //选择UART模式,使能接收器
   UTX0IF = 0;       //清除TX发送中断标志
   URX0IF = 0;       //清除RX接收中断标志
   URX0IE = 1;       //使能URAT0的接收中断
   EA = 1;           //使能总中断
 }
 unsigned char dat[4];
 /*===================UR0发送字符串函数==================*/
 void UR0SendString(unsigned char *str, unsigned char count)
 {
   while(count--)       
   {
     U0DBUF = *str++;    //将要发送的1字节数据写入U0DBUF
     while(!UTX0IF);     //等待TX中断标志,即数据发送完成
     UTX0IF = 0;  
   }
 }
 /*===================ADC初始化函数====================*/
 void Init_ADC0()
 {
   P0SEL |= 0x01;      //P0_0端口设置为外设功能
   P0DIR &= ~0x01;     //P0_0端口设置为输入端口
   APCFG |= 0x01;      //P0_0作为模拟I/O使用
 }
 /*===================读取ADC的数据====================*/
 void Get_ADC0_Value()
 {
   ADCIF = 0;
   //参考电压选择AVDD5引脚,256抽取率,AIN0通道0
   ADCCON3 = (0x80 | 0x10 | 0x00);
   while(!ADCIF);      //等待A/D转换完成,
   dat[0] = 0xaf;
   dat[1] = ADCH;      //读取ADC数据低位寄存器
   dat[2] = ADCL;      //读取ADC数据高位寄存器
   dat[3] = 0xfa;
 }
 /*=======================主函数======================*/
 void main()
 {
   Init_Uart0();
   Init_Timer1();
   Init_ADC0();
   while(1)
   {
     if(F_time == 1)           //定时1秒时间到
     {
       Get_ADC0_Value();       //进行A/D转换并读取数据
       UR0SendString(dat,4);   //向上位机发送数据
       F_time = 0;             //定时1秒标志清0
     }
   }
 }
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分