特多东西要学 ,分配时间不当,导致后期才开始苦练CC2530,开始把CC2530的功能逐个啃。 平时练习都是这么个习惯,先查看单片机数据手册的ADC相关部分,例程怎么设置寄存器,闭着眼睛写代码,逐步调试,我尝试着把例程的模块功能移植到我的项目工程。(失败) 尴尬的事情开始发生了 我TM直接使用完整的例程项目,得到的结果也不是正确的。(失败) 将时间上连续变化的模拟量转化为脉冲有无的数字 量,这一过程叫数字化,实现数字化的关键设备是ADC。 TI提供的CC2530的A/D转换位数是8,10,12,14, 但转换的实际有效位ENOB只有7,9,10,12(不包括: 符号位、最后1位精度损失位)。 数字转换结果可以获得,且结果总是驻留在ADCH和ADCL寄存器组合的MSB(高位)段 在此我们选用实际有效12位 我们这里以 光敏二极管  为例子,采集ADC引脚P0^0,12位精度 1.设置IO口 2.置参考电压,分辨率 通道 启动转换 1.判断是否转换完成 1. 例程项目(带错误) 2. 书本(带错误) 3. 博主(验证过程) 最后提一下本书好多错误基于CC2530-ADC采集特别坑
写篇缘由
博主是一个非常懒的人,能不关注就不用关注,哈哈哈哈。 参加职业技能大赛,而我是组里负责单片机部分,往年是只有CC2530这种单片机 。 而今年是有CC2530 +(新增的STM32的Lora和NB-iot)。 暴躁脾气的小哥
 给定自己实现一个功能,Zigbee +光敏二极管 采集(ADC值 和 电压值)数据发送到串口。什么是ADC(简单讲 模拟量–> 数字量)
 ADC:数模转换器,将时间和幅值连续的模拟量转化为时间和幅值离散的数字量,A/D转换一般要经过采样、保持、量化、编码4个过程。
 
CC2530的A/D转换位数(注意这里)
 CC2530内部ADC各精度对应位(没问题)
 下图是从CC2530的中文手册里截出来,细品,您细品,是不是数据手册表达得有点问题(红色部分是我修正的内容),
 
初始化ADC相关寄存器
 P0^0 设置为 外设功能、输入引脚、模拟引脚
 通道0  512抽取率(12位精度) 参考电压AVDD5(3.3V)void initial_AD() { //设置IO口   P0SEL|=(1<<0); //P0^0外设引脚   P0DIR&=~(1<<0); //P0^0为输入引脚   APCFG|=0x01; //P0^0模拟引脚 //ADCIF = 0;  //清除中断标志位 //设置参考电压,分辨率 通道 启动转换   ADCCON3=0xB0; //1011 0000  通道0  512抽取率 参考电压AVDD5,3.3V } 功能部分
 2.获取AD值
 3.处理AD值处理AD部分
uint getTemperature(void){ unsigned int  value; //存储AD值   AdcValue = 0;   ADCCON3|=0x3E; // 使用1.25V内部电压,12位分辨率,AD源为:片内温度传感器   ADCCON1|=0x40; //开启单通道ADC while(!(ADCCON1&0x80)); //等待AD转换完成   value =  ADCL >> 2; //ADCL寄存器低2位无效   value |= (((uint)ADCH) << 6); return value*0.0629-303.3; //根据AD值,计算出实际的温度 } 
 ADCL和ADCH都是8位,
 按照上面算法计算12位分辨率得出 Value 的值是  2^13=8192 比正常值大了一倍。()
 错误在  ADCL应该往右移3位,这里却少移1位,导致后面ADCH的位数只能整体向左挪一位。
 
 可怕的是书本也是按照这种算法写,得出的值大一倍。
 
 首先让光敏二极管尽量接近最大值,直接把光敏二极管短接了
 

 从上串口调试助手中能看到,得出的值接近8192,实锤,上述算法是有误的。
 /*************************************************************************************************/
 下面开始更正错误
 12位精度的ADC_H(7)和ADC_L(5)的高低位(橙色区域表示有效)
 大家动手指头亲自数一下有效是哪几位。
 
 处理方法:
 低位:ADCL>>3  去掉低4位包括(精度损失位和无效位)
 高位:(  ( ADCH<<1 )  >>1  )    (稳起见去掉符号位)
 
 串口助手中可以看出AD值在 2^12=4096之间 ,说明获取的AD值没问题,加上转换电压公式,可以精准算出当前测量的电压值。
 
 
 完整项目代码#include "iocc2530.h" unsigned char AD_data[]="0000-->"; unsigned char V_data[]="00000"; unsigned int adcvalue=0; //ADC值  unsigned int result=0; //电压值 /**********************/ void uart_senString(unsigned char *str); //发送字符串 void uart_senbit(unsigned char bit); //发送字符 void delay(unsigned int tt); void uart_init(); void Timeinit(); void initial_AD(); /**********************/ void main() {   CLKCONCMD &=~0x40; //切换系统时钟源为32M晶振 while(CLKCONSTA & 0x40);//等待32M外部晶振稳定   CLKCONCMD &=~0x47; //设置系统主时钟频率为32M Timeinit(); //初始化定时器 uart_init(); //初始化串口 initial_AD(); //初始化AD while(1) { while(!(ADCCON1&0x80));//等待转换完成 //获取AD值     adcvalue=ADCL>>3;      adcvalue|=(unsigned int)(ADCH<<1>>1) <<5;     AD_data[0]=adcvalue/1000%10+0x30;     AD_data[1]=adcvalue/100%10+0x30;     AD_data[2]=adcvalue/10%10+0x30;     AD_data[3]=adcvalue%10+0x30; //获取电压值     result=33000*adcvalue/40950; //AD值转换成电压     V_data[0]=(result/1000%10)+0x30;     V_data[1]='.';     V_data[2]=(result/100%10)+0x30;     V_data[3]=(result/10%10)+0x30;     V_data[4]=(result%10)+0x30; uart_senString("ADC值:"); uart_senString(AD_data); //ADC值发送到PC端 uart_senString("电压值:"); uart_senString(V_data); //电压值发送到PC端 uart_senString("rn"); delay(8000); delay(8000);     ADCCON3=0xB0; //再次启动转换 } } //中断服务函数 #pragma vector=T1_VECTOR   __interrupt void Time1() {   T1STAT &= ~0x01; } //串口接收服务函数 #pragma vector=URX0_VECTOR __interrupt void uartIE() { } void initial_AD() { //设置IO口   P0SEL|=(1<<0); //外设功能   P0DIR&=~(1<<0); //输入   APCFG|=0x01; //配置模拟IO //设置参考电压,分辨率 通道 启动转换   ADCCON3=0xB0; //1011 0000  通道0 512抽取率 参考电压AVDD5(3.3V) } void Timeinit() { //系统晶振32M   T1CC0H =0x61;   T1CC0L =0xA8; //定时0.1秒   T1CTL =0x0E; //分频系数是128,模模式    T1CCTL0 |=0x04; //通道0比较模式   T1IE=1; //使能定时器中断   T1OVFIM=1; //使能定时器溢出中断   EA=1; //总中断使能 } void uart_init() { //初始化引脚   P0SEL |=0x0C; //串口外设 //设置串口波特率   U0BAUD =59;   U0GCR =8; //设置串口控制器和串口通讯   U0UCR |=0x80; //清除和控制   U0CSR |=0xC0; //串口状态和使能 //清除中断标志位   URX0IF =0;   UTX0IF =0; //使能中断   URX0IE =1; //串口接收中断   EA=1; } void uart_senbit(unsigned char bit) {   U0DBUF=bit; while(!UTX0IF);   UTX0IF=0; } void uart_senString(unsigned char *str) { while(*str !=' ') { uart_senbit(*str++); } } void delay(unsigned int tt) { while(tt--); while(tt--); while(tt--); while(tt--); } 
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
 官方软件产品操作指南 (170)
官方软件产品操作指南 (170)