CC2530的ADC工作原理与应用

Posted 364.99°

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC2530的ADC工作原理与应用相关的知识,希望对你有一定的参考价值。

1.A/D转换的基本工作原理

在这里插入图片描述

  1. 数字化: 将时间上连续变化的模拟量转化为脉冲有无的数字量(ADC)
  2. ADC: 数模转换器,将时间和幅值连续的模拟量转化为时间和幅值离散的数字量
  3. 过程: 采样、保持、量化、编码

常用ADC: 逐次逼近型、双积分型、∑-△型
在这里插入图片描述
A/D转换器的几个技术指标:

  1. 量程: ADC所能输入模拟信号的类型和电压范围(参考电压),信号类型包括单极性和双极性
  2. 转换位数: 量化过程中的量化位数n,A/D转换后的输出结果用n位二进制数表示
  3. 分辨率: ADC能够分辨的模拟信号最小变化量,分辨率 = 量程 / 2^n
  4. 转换时间: ADC完成一次完整的A/D转换所用时间,包括采样、保持、量化、编码的全过程

ADC的四个基本过程
采样、保持、量化、编码
在这里插入图片描述
在这里插入图片描述


例: 有一个温度测控系统,已知温度传感器在0到100度之间为线性输出,参考电压为5V,采用8为的A/D转换器,0度的时候,测的电压为1.8伏,100度的时候,测的电压为4.3伏。

问: 系统的分辨率是多少?采集到数据10010001,表示多大电压?温度是多少?

由于采用的是8位ADC,参考电压为5V,所以分辨率为:
5* 1/2^8= 5/256 = 0.0195V= 1.95mV (最小能分辨的电压,分辨率)
0.0195 * 40= 0.78度(最小能分辨的温度)
由于温度是线性变化,先求得斜率k,得到温度和电压的关系表达式:
k= (100- 0)/(4.3-1.8)=40,y = 40*(x-1.8) (x为采样得到的电压)
因为10010001B=91H= 145,所以0.0195* 145= 2.83V
温度: (2.83V- 1.8V)* 40= 41.2℃

2.CC2530的A/D转换模块

在这里插入图片描述

此ADC模块的主要特征:

  1. 可选取的抽取率,设置分辨率(7~12位)
  2. 8个独立的输入通道,可接收单端或差分信号
  3. 参考电压可选为内部单端、外部单端、外部差分或AVDD5
  4. 单通道转换结束可产生中断请求
  5. 序列转换结束可发出DMA触发
  6. 可将片内温度传感器作为输入
  7. 电池电压测量功能

3.ADC模块的信号输入

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

  1. 输入端可配置为单端输入差分输入
  2. 差分输入对: AIN0~AIN1、AIN2 ~ AIN3、AIN4 ~ AIN5 、AIN6 ~ AIN7
  3. 片上温度传感器的输出也可以作为ADC的输入用于测量芯片的温度
  4. 可以将一个对应AVDD5/3的电压作为ADC的输入,实现电池电压检测
  5. 负电压大于VDD的电压不能用于P0这些引脚
  6. 单端电压输入AINO~ AIN7,以通道号码0~7表示
  7. 四个差分输入对则以通道号码8~11表示
  8. 温度传感器的通道号码为14
  9. AVDD5/3电压输入的通道号码为15

4.ADC相关的几个概念

  1. 序列ADC转换: 可以按序列进行多通道的ADC转换,并把结果通过DMA传送到存储器,而不需要CPU任何参与。
  2. 单通道ADC转换: 通过写ADCCON3寄存器触发单通道ADC转换,一旦寄存器被写入,转换立即开始
  3. 参考电压: 内部生成的电压、AVDD5引脚、适用于AIN7输入引脚的外部电压,或者适用于AIN6~ AIN7输入引脚的差分电压
  4. 转换结果:
    4.1. 数字转换结果以二进制的补码形式表示
    4.2. 对于单端,结果总是
    4.3. 对于差分配置,两个引脚之间的差分被转换,可以是负数
    4.4. 当ADCCON1.EOC设置为1时,数字转换结果可以读取
    4.5. 转换结果总是驻留ADCHADCL寄存器组合的MSB段中
  5. 中断请求:
    5.1. 通过写ADCCON3触发一个单通道转换完成时,将产生一个中断
    5.2. 完成一个序列转换时,ADC将产 生一个DMA触发,而不产生中断
  6. 三个控制寄存器: ADCCON1、ADCCON2、ADCCON3,用来配置ADC
  7. 两个数据寄存器: ADCL和ADCH,用来返回转换结果

5.1.案例——定时采集电压数据发送到上位机

要求:

将光照度传感器接到的Zigbee小模块上,每隔1秒以单通道的式采样一次该传 感器的电压值,并按照指定的格式将数据传送到上位机。上位机与CC2530的 串口0相连,系统时钟为16MHz,波特率为9600BPS, 发送数据采用查询的方式。数据帧有4个字节,格式如下:
0xFA (帧头)    ADCH    ADCL    0xAF (帧尾)
在这里插入图片描述

设计思路:

  1. 初始化定时器1,实现0.1秒定时
  2. 在定时中断函数中实现1秒定时
  3. 按照参数要求初始化串口0
  4. 设计字节数组发送函数
  5. 初始化ADC (单通道采集)
  6. 实现数据采集并发送到上位机

配置APCFG寄存器

  1. 当使用ADC时,端口0的引脚必须配置为ADC模拟输入
  2. 要配置一个端口0引脚为一个ADC输入,APCFG寄 存器中相应的位必须设置为1。这个寄存器的默认值是0,选择端口0为非模拟输入,即作为数字I/O端口
  3. 注意: APCFG寄存器的设置将覆盖POSEL的设置
  4. APCFG模拟I/O配置寄存器:
    在这里插入图片描述

配置ADCCON3寄存器

  1. 单通道的ADC转换,只需要将控制字写入ADCCON3寄存器即可
  2. ADCCON3控制寄存器(单通道相关):
    在这里插入图片描述

ADC初始化

  1. 对端口的功能进行选择
  2. 设置其传输方向
  3. 将端口设为模拟输入

ADC数据采集

  1. 将ADCIF标志位清0
  2. 配置ADCCON3寄存器,该寄存器一旦被写入,转换立即开始
  3. 等待ADCIF置1,标示转换完成
  4. 读取数据

代码:

#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,即PO_2和P0_3
  P0SEL = 0x0C;               //将PO_ 2和PO_ _3端口设置成外设功能
  U0BAUD = 59;                //16MHz的 系统时钟产生9600BPS的波特率
  U0GCR = 9;
  U0UCR |= 0x80;              //禁止流控, 8位数据,清除缓冲器
  U0CSR |= 0xCe;              //选择UART模式,使能接收器
  UTX0IF = 0;                 //清除TX发送中断标志
  URX0IF = 0;                 //清除RX接收中断标志
  URX0IE = 1;                 //使能URAT0的接收中断
  EA = 1;                     //使能总中断
}

/*=============================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/0使用
}

unsigned char dat[4];
/*===========================读取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;
}

/*===========================main函数=========================================*/
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
    }
  }
}

以上是关于CC2530的ADC工作原理与应用的主要内容,如果未能解决你的问题,请参考以下文章

CC2530的定时/计数器原理与应用

CC2530入门教程-05CC2530的串行接口原理与应用

CC2530的ADC采集外部电压

CC2530的串口通信原理与应用

ALB技术笔记基于多线程方式的串行通信接口数据接收案例

cc2530f256是STM32单片机的一款吗