工具与软件:
大家好、我有一款使用 CC1110芯片的定制器件。 我使用26MHz 晶体振荡器和32kHz 晶体振荡器。 器件由电池供电、并定期发送一些数据。 我使用 RTC 计时器来唤醒。 当使用 PM1时、该器件按预期工作。 在 PM2模式下、它会挂起。 然后,我阅读勘误表中所述的工作范围,所有工作正常, 从我们的第一个10个样本生产的大多数板。 我们有几块电路板在第一次传输后似乎因未知问题挂起、我们当时认为这些电路板不重要。 由于这些器件是手动组装的、因此我们假设焊接存在一些问题。 但现在我们要投入生产、我们的第一批200个器件、其中约50%存在相同的问题。 这些都是由一家信誉良好的工厂制造的、因此不应假设焊接不良。 问题是、当在 PM2进入睡眠模式时、器件似乎不会再次发送任何数据。 我不确定器件是否在 PM2中挂起、或者存在另一个问题:我已经尝试过的事情: 过早的 XOSC_STB 置为有效-我尝试在激活 XOSC 和切换到 XOSC 之间添加延迟、播放时间值为1ms 到100ms、这个问题并没有解决。 RX_overflow 问题:我已尝试在睡眠例程结束时添加 RFST = 0x04、因此 RF 在唤醒后强制空闲、但也未解决问题。
在 PM2和 PM1模式下、我没有进行调试、一切都正常运行。 我只能尝试一些东西、看看是否有什么东西可以正常工作。 唯一可行但未能解决我问题的方法是在唤醒后使用看门狗进行"软件"复位。 如果我在 go_to_sleep 例程结束时添加以下内容、以便芯片在唤醒后复位:
WDCTL =(WDCTL 和 Δ~WDCTL_INT)| WDCTL_INT3_msec_2;
WDCTL =(WDCTL &~WDCTL_MODE)| WDCTL_EN;
然后设备可以工作、但这不是可接受的解决方案、因为我丢失了内存内容。 我不知道这是否意味着该器件实际上会退出 PM2、因为复位确实发生、问题出在别处。 我还检查了示波器和振荡器似乎工作正常. 另外、在使用示波器进行检查时不起作用(看起来挂起)的器件上、晶体似乎定期启动、此时器件应进行下一次传输但不进行传输。 这可能是射频外设的问题吗? 在 PM2模式下、我没有调试器、因此我只能进行假设。 我使用 CCdebugger 和 IAR workbench。
这是我的 go_to_sleep 例程:
//将系统时钟源切换到 HS RCOSC 和最大 CPU 速度:
//请注意、这对电源模式3至关重要。 之间转换
//退出电源模式3系统时钟源是 HS RCOSC、
//但为了强调我们选择在这里明确的要求。
//--------------- SET RTC-------------
WORCTL |= 0x04;//重置睡眠定时器
WOREVT1 = 0x03;
WOREVT0 = 0x00;
STIE = 1;
WORCTRL |=1;
WORIRQ |= 0x10;
//--------------- 设置 RC osc---------------
SLEEP 且=~SLEEP_OSC_PD;
while (! (SLEEP & SLEEP_HFRC_S);
CLKCON =(CLKCON &~CLKCON_CLKSPD)| CLKCON_OSC | CLKSPD_DIV_2;
while (! (CLKCON & CLKCON_OSC );
SLEEP |= SLEEP_OSC_PD;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////// CC111xFx/CC251xFx 勘误手册代码部分开始////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Volatile uint8 storedDescHigh;
Volatile uint8 storedDescLow;
//存储当前 DMA 通道0描述符并中止任何正在进行的传输、
//如果通道正在使用。
storedDescHigh = DMA0CFGH;
storedDescLow = DMA0CFGL;
DMAARM |=(DMAARM_ABORT | DMAARM0);
//使用正确的源更新描述符。
dmaDesc[0]=(uint16)&PM2_BUF >> 8;
dmaDesc[1]=(uint16)&PM2_BUF;
//将描述符与 DMA 通道0关联并对 DMA 通道进行 ARM
DMA0CFGH =(uint16)&dmaDesc >> 8;
DMA0CFGL =(uint16)&dmaDesc;
DMAARM = DMAARM0;
//注意! 此时、请确保所有不会使用的中断
//按照"电源管理控制"中的说明禁用从 PM 唤醒
//产品说明书的一章。
//下面的代码是计时关键型的、应该在中完成
//按此处所示顺序排列、中间没有代码。
//与正32kHz 时钟边沿对齐、如所述
//数据表的"睡眠定时器和功耗模式"一章。
TEMP = WORTIME0;
while (temp = WORTIME0);
//确保进入 PM{2 - 3}时 XOSC 已断电、且
//闪存缓存被禁用。
MEMCTR |= MEMCTR_CACHD;
对于 PM2、SLEEP = 0x06;//7对于 PM3 6
//按照"电源管理控制"一章中的说明进入电源模式
//产品说明书中。 确保 DMA 通道0恰好在之前触发
//设置[PCON.IDLE]。
asm ("NOP");
asm ("NOP");
asm ("NOP");
if (SLEEP 和0x03)
{
asm ("MOV 0xD7、#0x01");// DMAREQ = 0x01;
asm ("NOP");//完全对齐 DMA 传输需要。
asm ("ORL 0x87、#0x01");// PCON |= 0x01 --现在处于 PM2中;
asm ("NOP");//唤醒时进行首次调用
}
//计时关键代码结束
//halPowerClkMgmtSetMainClkSrc (0);//crystal);
SLEEP 且=~0x04;//为两个振荡器(HS XOSC 和 HS RCOSC)上电
halWait (1);//延迟时间超过最大晶体启动时间
CLKCON &=~0x40;//将高速晶体振荡器设置为系统时钟
//启用 Flash 缓存。
MEMCTR &=~MEMCTR_CACHD;
//使用原始描述符和 ARM 通道 IF 更新 DMA 通道0
//它在输入 PM 之前正在使用。
DMA0CFGH = storedDescHigh;
DMA0CFGL = storedDescLow;
DMAARM = DMAARM0;
