目录
前言
一、实验相关电路图
二、实验相关理论与寄存器
1.A/D 转换的基本工作原理
2.CC2530的A/D转换模块
3.ADC模块的信号输入
4.ADC相关的几个概念
5.相关寄存器
三、源码分析
四.实验结果
前言
本实验用于学习CC2530芯片:
- 串口配置与使用
- 定时采集内部温度传感器信息后,通过串口发送到上位机
一、实验相关电路图
P0_2、 P0_3 配置为外设功能时: P0_2 为 RX, P0_3 为 TX。USART0 和 USART1 是串行通信接口,它们能够分别运行于异步 UART 模式或者同步 SPI 模式。两个 USART 具有同样的功能,可以设置在单独的 I/O 引脚。更详细的说明请参考数据手册 7.6 和16.1 节。
二、实验相关理论与寄存器
1.A/D 转换的基本工作原理
ADC,即模拟数字转换器(Analog-to-digital converter),是用于将模拟形式的连续信号转换为数字形式的离散信号的一类设备。一个模拟数字转换器可以提供信号用于测量。与之相对的设备称为数字模拟转换器, A/D 转换一般要经过采样、 保持、 量化和编码 4 个过程。
将时间上连续变化的模拟量转化为有无脉冲的数字量,这一过程就叫做数字化,实现数字化的关键设备是 ADC。
将一个时间上连续变化的模拟量转化为时间上离散变化的模拟量就是采样。
将采样结果储存起来,直到下次采样,这个过程叫作保持。
将采样—保持电路的输出电压,按某种近似方式归化到相应离散电平上,这一转化过程称为数值量化,简称量化,由于量化输出的数字信号位数有限,所以输出的数字信号和你采样得到的模拟信号会有一个误差,被称为量化误差。
量化后的数值最后还需通过编码过程用一个代码表示出来,经编码后得到的代码就是A/D转换器输出的数字量。
对一个N位ADC来说,假设其满量程电压为Vref,Vref被ADC分为2^N个区间,区间宽度用LSB(last significant bit)表示,则LSB=Vref/2^N。
例如:Vref=8V,ADC为3位,则 LSB=8/2^3=1,所以每个区间为1V,
000代表电压0≤V<1 001代表电压1≤V<2 010代表电压2≤V<3
011代表电压3≤V<4 100代表电压4≤V<5 101代表电压5≤V<6
110代表电压6≤V<7 111代表电压7≤V<8
2.CC2530的A/D转换模块
CC2530的ADC模块支持最高14位二进制的模拟数字转换,具有12位的有效数据位 (ENOB),它包括一个模拟多路转换器,具有8个各自可配置的通道,以及一个参考电压发生器。
该ADC模块有如下主要特征:
<1> 可选取的抽取率,设置分辨率(7~12位)。
<2> 8个独立的输入通道,可接收单端或差分信号。
<3> 参考电压可选为内部单端、外部单端、外部差分或AVDD5。
<4> 单通道转换结束可产生中断请求。
<5> 序列转换结束可发出DMA触发。
<6> 可将片内温度传感器作为输入。
<7> 电池电压测量功能。
3.ADC模块的信号输入
单端输入:只有一个输入引脚ADCIN,使用公共地GND作为电路的返回端,ADC的采样值=ADCIN电压-GND的电压(0V)。这种输入方式优点就是简单,缺点是如果vin受到干扰,由于GND电位始终是0V,所以最终ADC的采样值也会随着干扰而变化。
差分输入:抑制共模干扰,提高信号抗干扰能力。比单端输入多了一根线,最终的ADC采样值=(ADCIN电压)-(ADCIN-电压),由于通常这两根差分线会布在一起,所以他们受到的干扰是差不多的,输入共模干扰,在输入ADC时会被减掉,从而降低了干扰,缺点就是接线复杂一些。而且需要VIN+和VIN-两路反相的输入信号。
端口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表示;温度传感器的通道号码为14;AVDD5/3电压输入的通道号码为15。
4.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并返回转换结果。
5.相关寄存器
相关寄存器ADCCON1、ADCCON2、ADCCON3、TR0、ATEST、CLKCONCMD、CLKCONSTA配置如下表所示:
寄存器 | 位 | 描述 |
ADCCON1(0xB4)– ADC控制1 |
Bit[7] EOC | 转换结束。当ADCH被读取的时候清除。如果已读取前一数据之前,完成一个新的转换,EOC位仍然为高。 0:转换没有完成 1:转换完成 |
Bit[6] ST | 开始转换。读为1,直到转换完成 0:没有转换正在进行 1:如果ADCCON1.STSEL = 11并且没有序列正在运行就启动一个转换序列。 |
|
Bit[5:4] STSEL | 启动选择。选择该事件,将启动一个新的转换序列。 10:定时器1通道0比较事件 11:ADCCON1.ST = 1,这个位设置为高电平时,ADCCON1.STSEL 是 11,且当前没有转换正在运行时,就启动一个序列。当这个序列转换完成,这个位就被自动清除 |
|
Bit[3:2]RCTRL | 控制16位随机数发生器(第13章)。 当写01时,当操作 00:正常运行。(13X型展开) 01:LFSR的时钟一次(没有展开). 10:保留 |
|
Bit[1:0] | 保留。一直设为11 | |
ADCCON2 (0xB5)–ADC控制2 | Bit[7:6]SREF | 选择参考电压用于序列转换 00:内部参考电压 01:AIN7引脚上的外部参考电压 10:AVDD5引脚 11:AIN6-AIN7差分输入外部参考电压 |
Bit[5:4]SDIV | 为包含在转换序列内的通道设置抽取率。抽 01:128抽取率(9位ENOB) 10:256抽取率(10位ENOB) |
|
Bit[3:0]SCH | 序列通道选择。选择序列结束。一个序列可以是从AIN0到AIN7(SCH<=7)也可以从差分输入AIN0-AIN1到AIN6-AIN7(8<=SCH<=11)。对于其他的设置,只能执行单个转换。当读取的时候,这些位将代表有转换进行的通道号码。 0000:AIN0 0001:AIN1 0010:AIN2 0011:AIN3 0100:AIN4 0101:AIN5 0110:AIN6 0111:AIN7 1000:AIN0-AIN1 1001:AIN2-AIN3 1010:AIN4-AIN5 1011:AIN6-AIN7 1100:GND 1101:正电压参考 1110:温度传感器 1111:VDD/3 |
|
ADCCON3 (0xB6)–ADC控制3 | 和ADCCON2基本相同,Bit[3:0]有点差异 | Bit[3:0]单个通道选择。选择写ADCCON3触发的单个转换所在的通道号码。 当单个转换完成,该位自动清除。 |
TR0 (0x624B)– 测试寄存器0 |
Bit[0] | 设置为1来连接温度传感器到SOC_ADC。也可参见ATEST寄存器描述来使能19.15.3节的温度传感器 |
ATEST (0x61BD)– 模拟测试控制 |
Bit[5:0] | 控制模拟测试模式: 00 0001:使能温度传感器(也可见12.2.10节TR0寄存器描述)。其他值保留。 |
CLKCONCMD时钟控制命令 | Bit[7]OSC32K | 32 kHz时钟振荡器选择 0:32 kHz XOSC 1:32 kHz RCOSC |
Bit[6]OSC | 系统时钟源选择 0:32 MHz XOSC 1:16 MHz RCOSC |
|
Bit[5:3]TICKSPD | 定时器标记输出设置 000:32 MHz 001:16 MHz 010:8 MHz 011:4 MHz 100:2 MHz 101:1 MHz 110:500 kHz 111:250 kHz |
|
Bit[2:0]CLKSPD | 时钟速度 000:32 MHz 001:16 MHz 010:8 MHz 011:4 MHz 100:2 MHz 101:1 MHz 110:500 kHz 111:250 kHz |
|
CLKCONSTA | CLKCONSTA寄存器是一个只读寄存器,用来获得当前时钟状态 |
温度传感器配置:
TR0=0x01; //设置为 1 来连接温度传感器到 SOC_ADC
ATEST=0x01; //使能温度传感
AD传感器配置:
ADCCON3 = (0x3E); //选择 1.25V 为参考电压; 12 位分辨率;对片内温度传感器采样
ADCCON1 |= 0x30; //选择 ADC 的启动模式为手动
ADCCON1 |= 0x40; //启动 AD 转化
三、源码分析
main.c文件如下
/****************************************************************************
* 文 件 名: main.c
* 描 述: ADC把芯片温度通过串口发给电脑,部分芯片误差较大需校准
* 手摸芯片温度有明显变化
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "UartTimer.h"
void main(void)
{
char i;
float fSum, AvgTemp;
char strTemp[6];
InitUART(); //初始化串口
InitSensor(); //初始化 ADC
while(1)
{
fSum = 0;
for (i=0; i<64; i++)
{
fSum += GetTemperature(); //取64次温度总和
}
AvgTemp = fSum/64; //取64次温度平均数
memset(strTemp, 0, 6);
sprintf(strTemp,"%.02f", AvgTemp);//将浮点数转成字符串,保留2位小数位
UartSendString(strTemp, 5); //通过串口发给电脑显示芯片温度
DelayMS(1000); //延时
}
}
void InitSensor(void) //温度传感器初始化
{
DISABLE_ALL_INTERRUPTS(); //关闭所有中断
InitClock(); //设置系统主时钟为 32M
TR0=0x01; //设置为1来连接温度传感器到SOC_ADC
ATEST=0x01; //使能温度传感
}
//获取温度传感器 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 寄存器低 2 位无效,但由于ADC只有12位有效,所以可认为ADCL寄存器低4位无效,所以要右移4位,网络上很多代码这里都是右移两位,那是不对的
value |= (((uint)ADCH) << 4);
return (value-1367.5)/4.5-5; //根据 AD 值,计算出实际的温度,芯片手册有错,温度系数应该是4.5 /℃
//进行温度校正,这里减去5℃(不同芯片根据具体情况校正)
}
UartTimer.h文件如下:文章来源:https://www.toymoban.com/news/detail-495842.html
#include <ioCC2530.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define DISABLE_ALL_INTERRUPTS() (IEN0 = IEN1 = IEN2 = 0x00)//三个
void InitClock(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ
}
void InitT3(void) //定时器初始化
{
T3CCTL0 = 0x44; //T3CCTL0 (0xCC),CH0 中断使能,CH0 比较模式
T3CC0 = 0xFA; //T3CC0设置为250
T3CTL |= 0x9A; //启动T3计数器,计数时钟为16分频。使用MODULO模式
IEN1 |= 0x08;
IEN0 |= 0x80; //开总中断,开T3中断
}
void InitUART(void) //串口初始化函数
{
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3C; //P0用作串口
P2DIR &= ~0xC0; //P0优先作为UART0
U0CSR |= 0x80; //串口设置为UART方式
U0GCR |= 11;
U0BAUD |= 216; //波特率设为115200
UTX0IF = 1; //UART0 TX中断标志初始置位1
U0CSR |= 0x40; //允许接收
IEN0 |= 0x84; //开总中断,接收中断
}
void UartSendString(char *Data, int len) //串口发送函数
{
uint i;
for(i=0; i<len; i++)
{
U0DBUF = *Data++;
while(UTX0IF == 0);
UTX0IF = 0;
}
U0DBUF = 0x0A; //输出换行
while(UTX0IF == 0);
UTX0IF = 0;
}
void DelayMS(uint msec) //ms延时函数
{
uint i,j;
for (i=0; i<msec; i++)
for (j=0; j<1060; j++);
}
四.实验结果
文章来源地址https://www.toymoban.com/news/detail-495842.html
到了这里,关于CC2530基础实验:(9)AD采集cc2530温度串口显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!