你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103 IWDG时钟准确度的疑问

[复制链接]
adarly 提问时间:2017-3-25 15:12 /
看文档上面介绍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[11:0] = 0x000
最长时间(ms)
RL[11:0] = 0xFFF
预分频系数 PR[2:0]
/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 (67) 6.4 26214.4

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


APB接口时钟与RC振荡器时钟之间的相位差,请问会对IWDG的时钟产生这么大的影响吗?有没有大神知道的?
收藏 1 评论3 发布时间:2017-3-25 15:12

举报

3个回答
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[6], RLR[2500], PVU[0], RVU[0]
预分频寄存器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[6], RLR[2500], PVU[0], RVU[0], ptimeout[500], rtimeout[0]
原来是硬件上一直没有将SR_PVU清0.。。。
无奈在上点开机几秒钟之后,再次手动初始化IWDG,此时再查下寄存器终于好了:
PR[3], RLR[2500], PVU[0], RVU[0], ptimeout[0], rtimeout[0]

那么问题又来了,为什么刚开机初始化时,SR_PVU一直不清0呢,有没有大神遇到过这种情况呀?
Dylan疾风闪电 回答时间:2017-3-27 15:56:05
  1. /** <summary>
  2.   * 打开IWDG。
  3.   * </summary>
  4.   * <param name="pr">40KHz看门狗时钟的预分频值。</param>
  5.   * <param name="rlr">看门狗倒计数的最大值,Max=0xFFF。</param>
  6.   * <exception cref=""></exception>
  7.   */
  8. void OpenIWDG(uint8_t pr, uint16_t rlr)
  9. {
  10.   IWDG->KR = 0x5555;        //使能对IWDG->PR和IWDG->RLR的写
  11.   IWDG->PR = pr;                //LSI/32=40Khz/(4*2^pre) //4、8、16、32、64、128、256
  12.   IWDG->RLR = rlr;                //从加载寄存器 IWDG->RLR,Max=0xFFF。因为看门狗计数器正是从这个值开始向下计数。
  13.   IWDG->KR = 0xAAAA;        //reload
  14.   IWDG->KR = 0xCCCC;        //使能看门狗
  15. }

  16. /** <summary>
  17.   * 给IWDG喂狗。
  18.   * </summary>
  19.   * <param name=""></param>
  20.   * <exception cref=""></exception>
  21.   */
  22. void FeedIWDG(void)
  23. {
  24.   IWDG->KR = 0xAAAA;        //reload
  25. }
复制代码


好像只要这样就可以的

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版