adarly 发表于 2017-3-25 15:12:12

STM32F103 IWDG时钟准确度的疑问

看文档上面介绍IWDG使用的内部低速时钟LSI,大约40K,可是当我配置IWDG预分频为32,装载值位2500(40K/16),也就是2秒钟不喂狗重启,但我测试下来结果却是10秒钟不喂狗才重启。这是为何,40K的LSI不可能误差这么多吧?IWDG配置如下:IWDG_SetPrescaler(IWDG_Prescaler_32);

IWDG_SetReload(40000 / 16);

另外我测试了下RTC也使用内部的40K LSI,来实现秒中断,测试下来1分钟触发58次,也就是说LSI的误差在1/30左右。
看到有关文档上结束如下:
看门狗超时时间(40kHz的输入时钟(LSI))(1)

最短时间(ms)
RL = 0x000 最长时间(ms)
RL = 0xFFF预分频系数 PR位
/4 0 0.1 409.6
/8 1 0.2 819.2
/16 2 0.4 1638.4
/32 3 0.8 3276.8
/64 4 1.6 6553.6
/128 5 3.2 13107.2
/256 (6或7) 6.4 26214.4

“这些时间是按照40kHz时钟给出。实际上, MCU内部的RC频率会在30kHz到60kHz之间变化。
此外,即使RC振荡器的频率是精确的,确切的时序仍然依赖于APB接口时钟与RC振荡器时钟
之间的相位差,因此总会有一个完整的RC周期是不确定的。”


APB接口时钟与RC振荡器时钟之间的相位差,请问会对IWDG的时钟产生这么大的影响吗?有没有大神知道的?

xmshao 发表于 2017-3-26 11:30:55

不可能这么大误差 再确认下配置参数
或者说配置写进去没有?

adarly 发表于 2017-3-27 11:34:22

多谢,楼上的提醒,的确是预分频寄存器PR的值没有设进去,但重载寄存器RLR的值却设进去了。很是奇怪。
初始化步骤如下:
void IWDG_Init(void)
{
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    IWDG_SetPrescaler(IWDG_Prescaler_32);
    IWDG_SetReload(CLK_LSI / 16);
    IWDG_ReloadCounter();
    IWDG_Enable();
}

然后通过串口打印会读的寄存器值PR RLR SR_PVU SR_RVU如下:
PR, RLR, PVU, RVU
预分频寄存器PR的值却是默认的256分频!!!
于是做了如下处理:
void IWDG_Init(void)
{
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    while(IWDG_GetFlagStatus(IWDG_FLAG_PVU));
    IWDG_SetPrescaler(IWDG_Prescaler_32);
    while(IWDG_GetFlagStatus(IWDG_FLAG_RVU));
    IWDG_SetReload(CLK_LSI / 16);
    IWDG_ReloadCounter();
    IWDG_Enable();
}

实验测试,却是陷入上面的死循环,MCU起不来了。于是继续测试:
uint16 ptimeout;
uint16 rtimeout;
void IWDG_Init(void)
{
    ptimeout = 0;
    rtimeout = 0;
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    while(IWDG_GetFlagStatus(IWDG_FLAG_PVU))
    {
      ptimeout ++;
      if (ptimeout >= 500)
      {
            break;
      }
    }
    IWDG_SetPrescaler(IWDG_Prescaler_32);
    while(IWDG_GetFlagStatus(IWDG_FLAG_RVU))
    {
      rtimeout ++;
      if (rtimeout >= 500)
      {
            break;
      }
    }
    IWDG_SetReload(CLK_LSI / 16);
    IWDG_ReloadCounter();
    IWDG_Enable();
}
初始化后打印的结果如下:
PR, RLR, PVU, RVU, ptimeout, rtimeout
原来是硬件上一直没有将SR_PVU清0.。。。
无奈在上点开机几秒钟之后,再次手动初始化IWDG,此时再查下寄存器终于好了:
PR, RLR, PVU, RVU, ptimeout, rtimeout

那么问题又来了,为什么刚开机初始化时,SR_PVU一直不清0呢,有没有大神遇到过这种情况呀?

Dylan疾风闪电 发表于 2017-3-27 15:56:05

/** <summary>
* 打开IWDG。
* </summary>
* <param name="pr">40KHz看门狗时钟的预分频值。</param>
* <param name="rlr">看门狗倒计数的最大值,Max=0xFFF。</param>
* <exception cref=""></exception>
*/
void OpenIWDG(uint8_t pr, uint16_t rlr)
{
IWDG->KR = 0x5555;        //使能对IWDG->PR和IWDG->RLR的写
IWDG->PR = pr;                //LSI/32=40Khz/(4*2^pre) //4、8、16、32、64、128、256
IWDG->RLR = rlr;                //从加载寄存器 IWDG->RLR,Max=0xFFF。因为看门狗计数器正是从这个值开始向下计数。
IWDG->KR = 0xAAAA;        //reload
IWDG->KR = 0xCCCC;        //使能看门狗
}

/** <summary>
* 给IWDG喂狗。
* </summary>
* <param name=""></param>
* <exception cref=""></exception>
*/
void FeedIWDG(void)
{
IWDG->KR = 0xAAAA;        //reload
}

好像只要这样就可以的:)
页: [1]
查看完整版本: STM32F103 IWDG时钟准确度的疑问