智能创客,中国最大的极客空间,智能平台,免费教学,视频教程,手把手教你创造儿时梦想!
标题: Zigbee之旅(六):几个重要的CC2430基础实验——ADC单次采样 [打印本页]
作者: znck007 时间: 2014-2-9 10:33
标题: Zigbee之旅(六):几个重要的CC2430基础实验——ADC单次采样
一、承上启下 在无线传感器网络中,很重要的一项就是将传感器的模拟值转换成数字量,以便于传输和处理。而ADC(Analog-to-Digital Converter)正是用来完成这种转换的。
上一节,我们介绍了CC2430与PC之间的串口通信。CC2430内部已嵌入一个温度传感器,本节将在上一节的基础上,实现一个简单的关于片内温度监测的小实验:利用ADC将片内温度传感器的电压值转换成数字量,利用公式计算出温度值,然后通过串口将温度值传送到PC上并显示出来。
二、ADC单次采样(1)实验简介 利用ADC转换CC2430片内温度传感器的温度值,通过串口将温度值发送到PC并显示出来。
(2)程序流程图
(3)实验源码及剖析/*
实验说明:片内温度采集实验,通过串口0将数据发送到PC机
*/
#include
#define led1 P1_0
#define led2 P1_1
#define led3 P1_2
#define led4 P1_3
/*32M晶振初始化
-------------------------------------------------------*/
void xtal_init(void)
{
SLEEP &= ~0x04; //都上电
while(!(SLEEP & 0x40)); //晶体振荡器开启且稳定
CLKCON &= ~0x47; //选择32MHz 晶体振荡器
SLEEP |= 0x04;
}
/*LED灯初始化
-------------------------------------------------------*/
void led_init(void)
{
P1SEL = 0x00; //P1为普通 I/O 口
P1DIR |= 0x0F; //P1.0 P1.1 P1.2 P1.3 输出
led1 = 1;
led2 = 1;
led3 = 1;
led4 = 1;
}
/*UART0初始化
-------------------------------------------------------*/
void Uart0Init(unsigned char StopBits,unsigned char Parity)
{
P0SEL |= 0x0C; //初始化UART0端口
PERCFG&= ~0x01; //选择UART0为可选位置一
U0CSR = 0xC0; //设置为UART模式,而且使能接受器
U0GCR = 11;
U0BAUD = 216; //设置UART0波特率为115200bps
U0UCR |= StopBits|Parity; //设置停止位与奇偶校验
}
/*UART0发送字符
-------------------------------------------------------*/
void Uart0Send(unsigned char data)
{
while(U0CSR&0x01); //等待UART空闲时发送数据
U0DBUF = data;
}
/*UART0发送字符串
-------------------------------------------------------*/
void Uart0SendString(unsigned char *s)
{
while(*s != 0)
Uart0Send(*s++);
}
/*UART0接收数据
-------------------------------------------------------*/
unsigned char Uart0Receive(void)
{
unsigned char data;
while(!(U0CSR&0x04)); //查询是否收到数据,否则继续等待
data=U0DBUF;
return data;
}
/*延时函数
-------------------------------------------------------*/
void Delay(unsigned int n)
{
unsigned int 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++);
}
/*得到实际温度值
-------------------------------------------------------*/
float getTemperature(void)
{
unsigned int value;
ADCCON3 = (0x3E); //选择1.25V为参考电压;14位分辨率;对片内温度传感器采样
ADCCON1 |= 0x30; //选择ADC的启动模式为手动
ADCCON1 |= 0x40; //启动AD转化
while(!(ADCCON1 & 0x80)); //等待ADC转化结束
value = ADCL >> 2;
value |= (ADCH << 6); //取得最终转化结果,存入value中
return value*0.06229-311.43; //根据公式计算出温度值
}
/*主函数
-------------------------------------------------------*/
void main(void)
{
char i;
float avgTemp;
unsigned char output[]="";
xtal_init();
led_init();
led1 = 0;
Uart0Init(0x00, 0x00); //初始化串口:无奇偶校验,停止位为1位
Uart0SendString("Hello CC2430 - TempSensor!");
while(1)
{
led1 = 0;
avgTemp = 0;
for(i = 0 ; i < 64 ; i++)
{
avgTemp += getTemperature();
avgTemp = avgTemp/2; //每采样1次,取1次平均值
}
output[0] = (unsigned char)(avgTemp)/10 + 48; //十位
output[1] = (unsigned char)(avgTemp)%10 + 48; //个位
output[2] = '.'; //小数点
output[3] = (unsigned char)(avgTemp*10)%10+48; //十分位
output[4] = (unsigned char)(avgTemp*100)%10+48; //百分位
output[5] = ''; //字符串结束符
Uart0SendString(output);
Uart0SendString("℃");
led1 = 1; //LED熄灭,表示转换结束,
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
Delay(20000);
}
}
关于串口通信的代码内容,请参考上一节,在此不解释~
ADC一般涉及到6个SFR:
ADCCON1 | 用于ADC通用控制,包括转换结束标志、ADC触发方式、随机数发生器 |
ADCCON2 | 用于连续ADC转换的配置(本实验不涉及连续ADC转换,故不使用此SFR) |
ADCCON3 | 用于单次ADC转换的配置,包括选择参考电压、分辨率、转换源 |
ADCH[7:0] | ADC转换结果的高位,即ADC[13:6] |
ADCL[7:2] | ADC转换结果的低位,即ADC[5:0] |
ADCCFG | 选择 P0.0~P0.7 作为ADC输入的 AIN0~AIN7(由于本次试验选择片内温度传感器作为转换源,不涉及AIN0~AIN7,故不使用此SFR) |
(注:以上SFR的具体内容请参考CC2430中文手册)
接下来,我们来重点关注一下 getTempurature 函数,它是获取温度值的关键:
(1)首先配置ADC单次采样:令 ADCCON3=0x3E,选择1.25V为系统电压,选择14位分辨率,选择CC2430片内温度传感器作为ADC转换源
(2)然后令 ADCCON1 |= 0x30,设置ADC触发方式为手动(即当ADCCON.6=1时,启动ADC转换)
(3)接着令 ADCCON1 |= 0x40,启动ADC单次转换
(4)使用语句 while(!(ADCCON1 & 0x80)) 等待ADC转换的结束
(5)转换结果存放在ADCH[7:0](高8位),ADCH[7:2](低6位),通过:
value = ADCL >> 2;
value |= (ADCH << 6);
将转换结果存进 value 中
(6)最后利用公式 temperature= value*0.06229-311.43 ,计算出温度值并返回即可
CC2430 小贴士 你一定会对最后一个公式感到莫名其妙,为什么是一次函数?为什么其斜率为0.06229,其截距为211.43?OK,下面解惑之:
此温度传感器是位于CC2430片内的,所以必然可以在其手册中找到其介绍。果不其然,我在 电气规范 这一节中找到了相关内容,现截图如下:
此表是描述温度传感器的温度(℃)与输出电压(V)的关系。
首先看第二个红框处:温度系数。“系数”?是不是有点感觉?然后再看其单位:mV/℃,你就会恍然大悟,原来温度与电压的关系是线性的啊~ 即有:
其中V为输出电压值,T为温度值,2.45为斜率。下面就要确定截距b了。
乍一看,我们会在第一个红框处发现0℃时的电压为743mV,那么b就等于743?不然,继续往下看,你会发现其绝对误差达到了8℃之多!然后往右看,我们会发现它已经提供了最适合的截距,即:b=763,因此有如下公式:
OK,现在我们已经有了温度传感器的 输入温度T 和 输出电压V 的关系,接下来必须找到ADC的 输入电压V 与 输出值N(即14位的转换结果)的关系,才可最终找到N和T的转换公式。
转换结果N是14位的,当N=11 1111 1111 1111(二进制)时,输出电压应为最大值(即参考电压1.25V)。因此我们有下面的比例关系:
(注:由于14位的输出结果是2进制的补码,因此第14位为符号位。所以从绝对值的角度来说,有效值只有13位,因此是2的13次方)
结合两式,可导出T与N的关系:
OVER~
最后,稍微提一下为什么每次采样需要进行64循环。因为传感器在测定温度时,难免会受到干扰或者随机性的error,其得到的数据有时候会很夸张(比如说忽然出现10℃的变动,然后又瞬间回复正常。但我们知道温度的变化是一个积分的过程,很少会出现那种在瞬间产生大幅度跳跃的情况)。因此我们采用了取平均值的方法来减少此类误差。
(4)实验结果 首先打开串口调试工具,然后下载程序并启动,就会出现如下画面:
片内温度大概在14.5℃左右。笔者用身体感受寝室的室温,大概在10℃多一点。芯片内部多少要发点热,所以14℃基本正常啦~
到此,实验结束。
三、结语 本篇介绍了ADC单次采样的实现。下一节,我们来介绍一种数据传输模式 DMA(direct memory access),即“直接内存存取”。ADC/UART/RF收发器等外设单元和存储器件之间,可以直接在“DMA控制器”的控制下交换数据而几乎不需要CPU的干预,因此可大大提高了系统的整体效率。
</n;i++);
</n;i++);
</n;i++);
</n;i++);
</n;i++);
作者: lvos5237 时间: 2014-9-5 09:40
提示: 该帖被管理员或版主屏蔽
作者: whk905 时间: 2015-5-6 19:04
支持一下吧
作者: agkkl 时间: 2015-9-3 21:04
提示: 作者被禁止或删除 内容自动屏蔽
作者: kprcv 时间: 2015-9-13 02:25
提示: 作者被禁止或删除 内容自动屏蔽
作者: liji59061463 时间: 2015-9-20 21:17
好东东,谢谢楼主
作者: kycup 时间: 2015-10-3 16:28
提示: 作者被禁止或删除 内容自动屏蔽
作者: {排水钢管} 时间: 2015-10-17 06:18
提示: 作者被禁止或删除 内容自动屏蔽
作者: 手机卡了nwk 时间: 2015-10-22 23:27
就看看,不说话。
作者: tswtj 时间: 2015-11-9 22:49
提示: 作者被禁止或删除 内容自动屏蔽
作者: nsebn 时间: 2016-1-17 21:48
交流交流好啊!楼主真厉害
作者: 飞珍非仓 时间: 2016-3-12 12:26
看的激动。。。 谢谢楼主了
作者: 飞珍非仓 时间: 2016-3-15 23:53
LZ辛苦了,支持一下!
作者: 飞珍非仓 时间: 2016-3-21 20:35
知道了 不错~~~
作者: zmlxh168 时间: 2016-4-21 12:36
帖子非常好
作者: mougua783 时间: 2016-4-21 20:48
非常酷哦,不顶对不起良心
作者: dpzkm 时间: 2016-6-11 04:40
真的谢谢了!
作者: dpzkm 时间: 2016-6-11 05:31
顶你一下,好贴要顶!
作者: fzinq 时间: 2016-6-24 02:42
呵呵,谢谢楼主了~~~~~~~~~~~
作者: orlihao62 时间: 2016-9-22 12:10
她并不是铁补天
刚敲了下门正好说道
不凡兄弟
现在看来是要进攻了而后朝千秋雪狠狠攻击如今
av400,有你想看的!
自己搜索www av400 com!
作者: 荧光粉142 时间: 2016-10-14 16:51
不错,很简洁!!!!
作者: 月夜之星642 时间: 2016-10-17 08:43
好贴阿楼主,代表大家谢谢您
作者: uu新天地50 时间: 2016-10-20 20:51
提示: 作者被禁止或删除 内容自动屏蔽
作者: 南国一梦web 时间: 2016-11-1 05:29
呵呵,不错
作者: eoqngj 时间: 2016-11-1 21:35
提示: 作者被禁止或删除 内容自动屏蔽
作者: 最终不相认g 时间: 2016-11-2 04:18
不错不错,楼主是个绝对高手
作者: 风已远去jr 时间: 2016-11-6 06:17
不错~~~~~~
欢迎光临 智能创客,中国最大的极客空间,智能平台,免费教学,视频教程,手把手教你创造儿时梦想! (http://luntan.znck007.com/) |
Powered by Discuz! X3.2 |