前言:
温度传感器是我们学习 MCU 经常使用的传感器,在 CC2530 里就集成里片内的温度传感器,有人会想到如果芯片发热怎么办?这个你得问问 TI 的工程师了。而且部分芯片偏差较大,通常需要软件校准。不过这也不失为一个尝试。
实验功能: 将采集到内部温度传感器信息通过串口发送到上位机。
实验讲解: CC2530 的内部温度检测需要配置的寄存器比较多, 包括温度和 AD的
CLKCONCMD,PERCFG,U0CSR,U0GSR,U0BAUD,CLKCONSTA,IEN0,U0DUB,ADCCON1,ADCCON3,ADCH,ADCL
各寄存器功能如下表所示: (详细参考 CC2530 datasheet.pdf)
按照表格寄存器内容,我们对 temperature sensor 和 AD 的寄存器进行配置。具体配置如下:
温度传感器配置:
TR0 = 0X01; //set ‘1’ to connectthe temperature sensorto the
SOC_ADC.ATEST= 0X01; // Enablesthe temperature sensorAD
传感器配置:
ADCCON3 = (0x3E); //选择 1.25V 为参考电压; 14 位分辨率; 片内采样
ADCCON1 |= 0x30; //选择 ADC 的启动模式为手动
ADCCON1 |= 0x40; //启动 AD 转换
过程实现:
本实验用到了自定义头文件,需要将路径手动包含到过程配置中
在此补充,芯片之前一直都是选的CC2530F256,芯片直接选择8051也可以,因为CC2530F256本质上就是增强型的8051芯片
在此处包含头文件目录
程序:
InitUART_Timer.h
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
#define LED1 P1_0 //定义LED1为P10口控制
#define LED2 P1_1 //定义LED2为P11口控制
#define LED3 P1_4 //定义LED3为P14口控制
// 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 DISABLE_ALL_INTERRUPTS() (IEN0 = IEN1 = IEN2 = 0x00)//三个
/**************************
系统时钟 不分频
计数时钟 32分频
**************************/
void InitClock(void)
{
CLKCONCMD &= ~0x40; // 设置系统时钟源为 32MHZ晶振
while(CLKCONSTA & 0x40); // 等待晶振稳定
CLKCONCMD &= ~0x47; // 设置系统主时钟频率为 32MHZ
}
/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x13; //P1_0、P1_1定义为输出
LED1 = 0; //LED1灯熄灭
LED2 = 0;
LED3 = 0;
}
/****************************
T3初始化
****************************/
void InitT3(void)
{
T3CCTL0 = 0X44; // T3CCTL0 (0xCC),CH0 中断使能,CH0 比较模式
T3CC0 = 0xFA; // T3CC0设置为250
T3CTL |= 0x9A; // 启动T3计数器,计数时钟为16分频。使用MODULO模式
IEN1 |= 0X08;
IEN0 |= 0X80; //开总中断,开T3中断
}
/*****************************************
串口初始化函数:初始化串口 UART0
*****************************************/
void InitUART0(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 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++);
}
/****************************
//延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时i毫秒 (16M晶振时候大约数,32M需要修改,系统不修改默认使用内部16M)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
main.c
#include <ioCC2530.h>
#include "InitUART_Timer.h" //注意在option里设置路径
#include "stdio.h"
/****************************************************************
温度传感器初始化函数
****************************************************************/
void initTempSensor(void)
{
DISABLE_ALL_INTERRUPTS(); //关闭所有中断
InitClock(); //设置系统主时钟为 32M
TR0=0X01; //set '1' to connectthe temperature sensorto the SOC_ADC.
ATEST=0X01; // Enablesthe temperature sensor
}
/****************************************************************
读取温度传感器 AD 值函数
****************************************************************/
float getTemperature(void){
uint value;
ADCCON3 = (0x3E); //选择1.25V为参考电压;14位分辨率;对片内温度传感器采样
ADCCON1 |= 0x30; //选择ADC的启动模式为手动
ADCCON1 |= 0x40; //启动AD转化
while(!(ADCCON1 & 0x80)); //等待 AD 转换完成
value = ADCL >> 4; //ADCL 寄存器低 2 位无效
value |= (((UINT16)ADCH) << 4);
return (value-1367.5)/4.5-5; //根据 AD 值,计算出实际的温度,芯片手册有错,温度系数应该是4.5 /℃
//进行温度校正,这里减去5℃(不同芯片根据具体情况校正)
}
/****************************************************************
主函数
****************************************************************/
void main(void)
{
char i;
char TempValue[6];
float AvgTemp;
InitUART0(); //初始化串口
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] = '\0'; //字符串结束符
UartTX_Send_String( TempValue,6);
Delayms(2000); //使用32M晶振,故这里2000约等于1S
}
}
实验现象: