2021年9月29日 星期三

热消息:CC2530 ADC配置步骤

时间:2023-07-06 15:06:14来源 : DS小龙哥-嵌入式技术

第一章 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 numberstypedef 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     }   } }

关键词:

(责任编辑:黄俊飞)

推荐内容

Back to Top