刚又发现一个现象:用镊子短接晶振,不同情况下的对比。
A情况:程序停在进入主函数之前,但晶振短接移除后,程序继续往下走。
B情况:程序进入了主函数,外部晶振READY失败,程序停止在else{while(1);}处。
C情况:程序进入了主函数,外部晶振READY成功,程序停在系统时钟切换处while(RCC_GetSYSCLKSource() != 0x04){}。
A情况发生的条件:
1.正常工作时,短接电容,看门狗复位,程序停在进入主函数之前,短接释放,程序继续往下走。
B情况发生的条件:
1.stop模式时,短接电容,看门狗复位,程序停在else{while(1);}处,短接释放,程序停在while(1)处。
2.仿真时,拔掉仿真线,短接晶振,镊子点外部复位,是B情况。
C情况发生的条件:
B情况发生后,镊子松开晶振,然后再次短接晶振,另外一个镊子短接复位,产生C情况,如果B情况发生后,镊子不松开晶振,持续短接,另外一个镊子短接复位后,还是B情况。
问题分析:
C情况和B情况的区别是这一段程序
do
{
HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);
StartUpCounter++;
}
while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET));
C情况检测到了HSERDY,而B情况没有检测到HSERDY。
很显然,C情况发生时,镊子松开了一下晶振,晶振起振了,导致HSERDY置位。
有一种猜测,系统复位的时候,寄存器的值没有复位,因为松开镊子是在复位之前,但镊子再次短上晶振后,复位,此时外部晶振仍然是失效的,HSERDY竟然可以置位,HSERDY是不是上一次松开短接时置的位,复位并没有将其清除掉。HSERDY 寄存器复位值0x000 XX83,可以确定是0;
通过对比C情况和B情况,发现:
晶振停振期间,即:
1.系统在复位(仿真时复位拔掉仿真器);
2.休眠(stop模式时);
短接晶振,
1.短接NRST
2.看门狗自动复位
程序都会进入主循环(使用HSI),直到在初始化HSE时失败,会停下来。
为什么A进不了主函数?而B和C都能进入主函数?
我有一个猜测,那就是NRST并没有使所有寄存器值复位。推测入下:
A之所以没有进入主函数,是因为复位前,是正常工作状态,RCC寄存器配置的是外部晶振。但由于人为的短接了晶振,导致晶振停振,看门狗复位,复位后,寄存器的值并没有复位,RCC配置的仍然是HSE,且晶振仍然被短接着,CPU没有时钟,所以程序无法运行进入主函数。当松开镊子后,晶振起振,程序正常开始往下跑。
为了保险起见,我查了英文原版的数据手册,跟中文的一样,说:
A system reset sets all registers to their reset values except the reset flags in the clock controller CSR registers in the Backup domain。
除了时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器(见图4)以外,系统复位将复位所有寄存器至它们的复位状态。
但是从上边实验可以看出,复位寄存器很有可能没有被复位。
如果寄存为没有被复位,假设休眠时,HSI是Disable的,由于异常,导致复位后,HIS仍然是Disable,没有主时钟,单片机就死掉了。
我明天做几个实验:
在main函数入口处,判断是主时钟是HSE还是HSI。
正常模式下(HSE被正常初始化),我短接外部晶振,触发看门狗复位,按照数据手册,在main函数入口处,应该是HIS,但如果是HSE,那说明RCC没有复位。
再做一个实验,想办法得到休眠状态下,HIS是否是使能的。
再做一个实验,我这边1000片板子,是不是所有的单片机都是寄存器不复位的。
刚又发现一个现象:用镊子短接晶振,不同情况下的对比。
A情况:程序停在进入主函数之前,但晶振短接移除后,程序继续往下走。
B情况:程序进入了主函数,外部晶振READY失败,程序停止在else{while(1);}处。
C情况:程序进入了主函数,外部晶振READY成功,程序停在系统时钟切换处while(RCC_GetSYSCLKSource() != 0x04){}。
A情况发生的条件:
1.正常工作时,短接电容,看门狗复位,程序停在进入主函数之前,短接释放,程序继续往下走。
B情况发生的条件:
1.stop模式时,短接电容,看门狗复位,程序停在else{while(1);}处,短接释放,程序停在while(1)处。
2.仿真时,拔掉仿真线,短接晶振,镊子点外部复位,是B情况。
C情况发生的条件:
B情况发生后,镊子松开晶振,然后再次短接晶振,另外一个镊子短接复位,产生C情况,如果B情况发生后,镊子不松开晶振,持续短接,另外一个镊子短接复位后,还是B情况。
问题分析:
C情况和B情况的区别是这一段程序
do
{
HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);
StartUpCounter++;
}
while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET));
C情况检测到了HSERDY,而B情况没有检测到HSERDY。
很显然,C情况发生时,镊子松开了一下晶振,晶振起振了,导致HSERDY置位。
有一种猜测,系统复位的时候,寄存器的值没有复位,因为松开镊子是在复位之前,但镊子再次短上晶振后,复位,此时外部晶振仍然是失效的,HSERDY竟然可以置位,HSERDY是不是上一次松开短接时置的位,复位并没有将其清除掉。HSERDY 寄存器复位值0x000 XX83,可以确定是0;
通过对比C情况和B情况,发现:
晶振停振期间,即:
1.系统在复位(仿真时复位拔掉仿真器);
2.休眠(stop模式时);
短接晶振,
1.短接NRST
2.看门狗自动复位
程序都会进入主循环(使用HSI),直到在初始化HSE时失败,会停下来。
为什么A进不了主函数?而B和C都能进入主函数?
我有一个猜测,那就是NRST并没有使所有寄存器值复位。推测入下:
A之所以没有进入主函数,是因为复位前,是正常工作状态,RCC寄存器配置的是外部晶振。但由于人为的短接了晶振,导致晶振停振,看门狗复位,复位后,寄存器的值并没有复位,RCC配置的仍然是HSE,且晶振仍然被短接着,CPU没有时钟,所以程序无法运行进入主函数。当松开镊子后,晶振起振,程序正常开始往下跑。
为了保险起见,我查了英文原版的数据手册,跟中文的一样,说:
A system reset sets all registers to their reset values except the reset flags in the clock controller CSR registers in the Backup domain。
除了时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器(见图4)以外,系统复位将复位所有寄存器至它们的复位状态。
但是从上边实验可以看出,复位寄存器很有可能没有被复位。
如果寄存为没有被复位,假设休眠时,HSI是Disable的,由于异常,导致复位后,HIS仍然是Disable,没有主时钟,单片机就死掉了。
我明天做几个实验:
在main函数入口处,判断是主时钟是HSE还是HSI。
正常模式下(HSE被正常初始化),我短接外部晶振,触发看门狗复位,按照数据手册,在main函数入口处,应该是HIS,但如果是HSE,那说明RCC没有复位。
再做一个实验,想办法得到休眠状态下,HIS是否是使能的。
再做一个实验,我这边1000片板子,是不是所有的单片机都是寄存器不复位的。
举报