这个问题的发现,是我一次写程序过程中,想查看休眠是否起了作用,调试结果让我很震撼。
芯片使用的是TI CC2430,没有使用Zigbee 协议栈,只是简单的单片机编程。开发工具使用的是IAR FOR 8051 7.30B版。不知是不是IAR的问题,其他编译环境没有测试过。
示例代码如下:
void Delay(uint n)
{
uint jj;
for(jj=0;jj<n;jj++);
for(jj=0;jj<n;jj++);
for(jj=0;jj<n;jj++);
for(jj=0;jj<n;jj++);
for(jj=0;jj<n;jj++);
}
/*****************************************
//LED闪烁函数
*****************************************/
void chg_yled(void)
{
uchar jj=10;
while(jj--)
{
YLED = !YLED;
Delay(10000);
}
}
/*********************************************************************
//主函数
*********************************************************************/
void main(void)
{
SET_MAIN_CLOCK_SOURCE(CRYSTAL);
LED_ENABLE(1); //将IO口使能
//随便弄些LED控制代码,目的是证明只会进入一次
RLED = 1;
Delay(50000);
Delay(50000);
Delay(50000);
RLED = 0; //红灯点亮
Delay(50000);
Delay(50000);
Delay(50000);
RLED = 1; //灭
chg_yled(); //闪烁黄灯
Init_SLEEP_TIMER(); //初始化休眠定时器
while(1)
{
test = 1000;
addToSleepTimer(3);
SET_POWER_MODE(2); //PM2 模式
chg_yled(); //让黄灯闪烁
}
}
#pragma vector = ST_VECTOR
__interrupt void ST_ISR(void)
{
STIF = 0;
}
实验现象:
1、如果在while(1)内部代码中加入断点,程序正常运行,CC2430标签能看到红灯只亮一次,然后间隔3S黄灯便会重复闪烁,期间红灯一直是灭的。
2、在while(1)中设置一个断点后,如在 test = 1000处下断,每次都会在test停下来,其后每次红灯每隔3S后被点亮,黄灯还是照样闪烁。总结:
虽然不知道是不是IAR为了捕获断点故意采取的这种措施,但当时仍困扰我很久,还一直认为是休眠后会从main处开始执行。总之,如果是使用了休眠模式,则不要在相关的代码处设断,否则会出现程序执行乱跳,是真实的乱跳。
还有一点,就是PM2模式休眠,低频振荡器即可以使用RC也可以使用晶振。32.768k RC振荡器是工作的,没有断电。这点从初始化的CLKCON可以看出,选择的是32kHz的RC振荡器。经测试,两者都是可以的。
SET_MAIN_CLOCK_SOURCE(CRYSTAL);
// SLEEP &= ~0x04; /*全开*/
while(!(SLEEP&0X40));/*待稳*/
asm("NOP");
CLKCON &= ~0x47; /*晶振*/
SLEEP |= 0x04; /*关掉不用的*/
CLKCON 默认值是0xC9 选中的是32.768 KHz的RC和16MHz的RC振荡器,跟~0x47进行与运算后变成0x88,意味着高频系统时钟选择为32M晶振,低频的仍是RC振荡器。
本文详细记录了一次在使用单片机编程时遇到的奇特现象,即在休眠模式下设置断点时,程序执行出现乱跳。通过实验现象分析,揭示了可能的原因,并分享了在休眠模式下设置断点时的注意事项。此外,文章还探讨了在PM2模式下使用RC振荡器和晶振的工作情况。
6777

被折叠的 条评论
为什么被折叠?



