CC2530有8个ADC通道,系统框图如下:
使用ADC有两种情况:
第一种是连续转换,此时需要配置ADCCON1和ADCCON2寄存器;
第二种是单次转换,此时只需要配置寄存器ADCCON3即可。
请初学者搞清楚哈,单次转换只需要配置寄存器ADCCON3就可以。
我今天实验的情况:
使用ADC测量单节干电池的电压。
选择的参考电压基准为:AVDD=3.3V,模拟通道选择通道0.
则初始化函数为:
static uint16 readV(uint8 channal,uint8 resolution)
{
uint16 value ;
APCFG |= 1 << channal ; //注意这里是设置ADC输入通道!!
ADCIF = 0 ;
ADCCON3 = (HAL_ADC_REF_AVDD | resolution | channal) ;
while ( !ADCIF ) ;
value = ADCL ;
value |= ((uint16) ADCH) << 8 ;//这里注意一下
if(channal == HAL_ADC_DEC_064)//7位分辨率
value >>= 9 ;
else if(channal == HAL_ADC_DEC_128) //9位分辨率
value >>= 7 ;
else if(channal == HAL_ADC_DEC_256) //10位分辨率
value >>= 6 ;
else if(channal == HAL_ADC_DEC_512) //12位分辨率
value >>= 4;
return value;
}
使用如下方式调用该函数:
1 temp = readV(HAL_ADC_CHN_AIN0,HAL_ADC_DEC_256) ;//10位分辨率
2 _ltoa(temp,vdataformat.Test,16) ;
3 temp = (temp + (temp << 5) ) >> 6 ;
4 Data[0] = (uint8)temp/10 + '0' ;
5 Data[1] = '.' ;
6 Data[2] = (uint8)temp%10 + '0' ;
第1行,选择模拟通道0,10位分辨率;
第2行,将读取到的AD转换值以十六进制的形式显示出来。
第3行,这是将读取到的值转换为实际的电压值。为了显示方便,将其扩大了10倍。
实际电压值= AD转换值* 33 /1024
注意这里是10位分辨率,同时将读取的电压值扩大了10倍数。
但是,经过一天半的测试我发现上述公式不行!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
后来发现AD转换值最大是0x,也就是说是6位,所以,果断修改上述公式,如下:
实际电压值= AD转换值* 33 /64
当然,没有人会傻到让个小51单片机去计算乘法和除法;
一般处理技巧是:将乘法转换为左移运算,除法转换为右移运算;
所以:推导过程如下:
实际电压值= AD转换值* 33 /64 =(AD转换值*32 + AD转换值)/ 64
= ((AD转换值<< 5 ) + AD转换值)>> 6
呵呵,我敢说,有部分初学者肯定没用过上述方法,算上给大家个小技巧吧。
第4—6行,将数据显示出来,输出到串口上。
然后,我使用稳压电源,型号:TPR3003,输出0---3.3V,然后输如到AD通道0,测试结果如下:
当然,需要说明的是,我买CC2530是散新的,所以,我怀疑片子确实存在问题!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
此外,对于TI这款芯片,感觉数据手册写的太烂了,一个内部参考电压,整个数据手册都没说过是多少,最后从网上看到貌似是1.25V,而CC2420内部的参考电压是1.15V,貌似是,现在不确定!!!
还有就是协议栈里的ADC驱动是完全照搬的CC2430吧,不相信的朋友可以查看一下,CC2530的ADC分辨率是7位、9位、10位和12位,但是协议栈里面的驱动如下:
switch (resolution)
{
case HAL_ADC_RESOLUTION_8:
reading >>= 8;
break;
case HAL_ADC_RESOLUTION_10:
reading >>= 6;
break;
case HAL_ADC_RESOLUTION_12:
reading >>= 4;
break;
case HAL_ADC_RESOLUTION_14:
default:
reading >>= 2;
break;
}
这绝对是恶心人,上述分辨率是CC2430的,貌似是,真让人寒心!!!