关于CC2540的AD口输入电流过大的问题
Dear TI
想用CC2540的AD口来进行采集,开了P0.4,P0.5,P0.6,P0.7四个口,发现同样的配置。当在P0.4,P0.5口加电压的时候,系统功耗会上升很多。
在测量的时候发现,当4个AD口都不加电压的时候,功耗大约在12.5mA左右,将电压加在P0.6,P0.7上时,功耗也几乎没有变化,但当将电压加在P0.4上是,功耗瞬间上到20mA,同时再加1路到P0.5时,系统功耗上到了26mA。测试几块板子都是这个问题。
基本上排除了外围硬件问题,所以想问下TI的工程师,CC2540的P0.4,P0.5口怎么会吸收那么大的电流?有可能是我还有哪儿的配置有问题吗?还是什么问题。
这是我的ADC的GPIO的配置代码:
void hal_gpio_set_adc() { P0 &= ~(BV(4)|BV(5)|BV(6)|BV(7)); //P0口低电平 P0DIR &= ~(BV(4)|BV(5)|BV(6)|BV(7)); //P0口 模式:输入 P0INP |= (BV(4)|BV(5)|BV(6)|BV(7)); //P0口 模式:三态 P0SEL |= (BV(4)|BV(5)|BV(6)|BV(7)); //P0口 IO模式:第二功能 }
外部参考电压选的 AVDD5。
通过进一步测量发现,当将P0.4,P0.5通过1K电阻接到VCC上时,P0.4,P0.5口会流进2mA左右的电流,算出来内部大约是500欧的内阻。
通过补充测试,为排除协议栈的干扰,在新建一个空的工程之后,在里面只做了ADC的IO口的初始化,通过1K电阻接VCC,再重新测量,发现。P0.0,P0.1,P0.2,P0.6,P0.7的电流都很小,大约只有0.02——0.05mA左右。但是P0.3,P0.4,P0.5口有2.6mA左右的电流。
还希望TI的工程师能够不惜赐教~o(∩_∩)o 哈哈
你好,你的问题应该出在你对IO口的配置上;我不知道你其他地方是否有问题,但这个地方应该有问题
首先AD应配置成模拟输入方式,APCFG = BV(HAL_ADC_CHANNEL_4) |BV(HAL_ADC_CHANNEL_5)| BV(HAL_ADC_CHANNEL_6) )| BV(HAL_ADC_CHANNEL_7) ; APCFG会覆盖GPIO引脚的配置。
然后调用uint16 HalAdcRead (uint8 channel, uint8 resolution),这个函数来读取AD转换的值。我测试过AD端口的电流几乎为零。
附件上有CC254X的CPU用户指南,你可以看一下 每个外设的具体配置方法。
你好 Wenzhong Shen
谢谢您的回复,我会进行补充测试。
CC2540的用户手册我有看过,上面有提到在使用之前,需要将相应引脚的APCFG这个寄存器置1。
但是,看了HalAdcRead()这个函数的代码,当它在使用哪个端口进行测量的时候,会在HalAdcRead()中将相应位的APCFG(在函数里面是ADCFG,发现和宏APCFG是一个地址)置1;并在测量完成了,将APCFG清0。所以APCFG这个寄存器并不需要我设置啊。
这是我暂时的看法,在进行过进一步的测试之后,再给您回复~o(∩_∩)o 哈哈
你好 Wenzhong Shen
感谢你的指导,确实如你所说,是APCFG的问题。
P0SEL | ADCCON2 | P0SEL | P0.0 | P0.1 | P0.2 | P0.3 | P0.4 | P0.5 | P0.6 | P0.7 | 备注 |
0x00 | \ | \ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | IO口三态,不开启第二功能 |
0xff | 0x00 | 0x00 | 0 | 0 | 0 | 2.2 | 2.2 | 2.2 | 0 | 0 | 开启IO口第二功能 |
0xff | 0xb0 | 0x00 | 0 | 0 | 0 | 2.1 | 2.1 | 2.1 | 0 | 0 | 只配置 ADCCON2 |
0xff | 0xb0 | 0xff | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 令 APCFG=0xff |
这是在AD口接1K电阻到VCC后的补充测量结果。确实如你所说,是APCFG的配置对其有影响。通过实验发现
1.IO口只设置为3态输入,不开启第2功能的时候 无电流
2.开启第2功能的时候,不开启ADC 有电流
3.开启第2功能,并将APCFG全置1的时候 无电流
总结:
还不知道是CC2540内部的什么外设,在初始化的时候占用了IO口,导致始终有电流流入。而在设置APCFG让AD模块独占IO口之后,电流消失。
办法:
重写了原有的 HalAdcRead()函数,取消掉其中对APCFG的配置部分。并且默认让IO口属于3态输入状态,只有真正需要测量的时候,才设置P0SEL,让它开启第二功能。
感想:
还是不知道,具体是内部的什么吸收了那么大的电流。虽然这样处理解决了一部分问题,但仍然不是长久之策。因为如果解决不了这个问题的话,如果使用TI官方提供的HalAdcRead()函数,在不需要测量AD的时候,脚上是始终会消耗电流的,只能将第2功能暂时关闭来解决。
还是希望能够找到那个外设,然后把它给停掉,这才是最终的解决之道。
不过暂时就只能到这里了~
最后:
再次向你表示感谢~o(∩_∩)o 哈哈
你好,原有的 HalAdcRead()函数,没有对APCFG进行配置,我不知道你用的BLE stack的哪个版本,我用的是BLE stack 1.4.0 。 下面附上原版的HalAdcRead()函数。正确的配置是,只需要在使用ADC前,对APCFG配置一下就可以了。很简单。不用配置3态输入和第二功能
uint16 HalAdcRead (uint8 channel, uint8 resolution)
{
int16 reading = 0;
#if (HAL_ADC == TRUE)
uint8 i, resbits;
uint8 adcChannel = 1;
/*
* If Analog input channel is AIN0..AIN7, make sure corresponing P0 I/O pin is enabled. The code
* does NOT disable the pin at the end of this function. I think it is better to leave the pin
* enabled because the results will be more accurate. Because of the inherent capacitance on the
* pin, it takes time for the voltage on the pin to charge up to its steady-state level. If
* HalAdcRead() has to turn on the pin for every conversion, the results may show a lower voltage
* than actuality because the pin did not have time to fully charge.
*/
if (channel <= HAL_ADC_CHANNEL_7)//转换序列0到7
{
for (i=0; i < channel; i++)
{
adcChannel <<= 1;
}
/* Enable channel */
ADCCFG |= adcChannel;
}
/* Convert resolution to decimation rate */
switch (resolution)
{
case HAL_ADC_RESOLUTION_8:
resbits = HAL_ADC_DEC_064;
break;
case HAL_ADC_RESOLUTION_10:
resbits = HAL_ADC_DEC_128;
break;
case HAL_ADC_RESOLUTION_12:
resbits = HAL_ADC_DEC_256;
break;
case HAL_ADC_RESOLUTION_14:
default:
resbits = HAL_ADC_DEC_512;
break;
}
/* writing to this register starts the extra conversion */
ADCCON3 = channel | resbits | adcRef;
/* Wait for the conversion to be done */
while (!(ADCCON1 & HAL_ADC_EOC));
/* Disable channel after done conversion */
if (channel <= HAL_ADC_CHANNEL_7)
ADCCFG &= (adcChannel ^ 0xFF);
/* Read the result */
reading = (int16) (ADCL);
reading |= (int16) (ADCH << 8);
/* Treat small negative as 0 */
if (reading < 0)
reading = 0;
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;
}
#else
// unused arguments
(void) channel;
(void) resolution;
#endif
return ((uint16)reading);
}
奥,对不起,是我疏忽, HalAdcRead()确实有对APCFG进行了配置,原来APCFG和ADCCFG是指向同一个寄存器。
不过,你不用对IO进行第二功能和3态输入的配置
你好 Wenzhong Shen
谢谢你的指点,我都注意到了用户手册上的原话:
"The settings in the APCFG register override the settings in P0SEL."
但是却没有想到,我自己配置了P0SEL可能正是输入电流过大的原因。
但如果照手册上说只是覆盖了P0SEL的配置的话,那是不是说三态其实还是需要自己配置的~o(∩_∩)o 哈哈