老怪. 2024-01-19 09:41 采纳率: 100%
浏览 17
已结题

GD32新品GD32VW553的滴答定时器定时不能理解问题

使用的是GD32兆易创新的新品WIFI+蓝牙的RISC-V芯片GD32VW553HMQ6,主频是160MHz,而在其例程中,关于滴答定时器的比较值是设置为系统时钟 / 4000。
我自己对滴答定时器的理解是

滴答定时器定时时间= 滴答定时器比较值 * 计数一次的时间
(1)滴答定时器比较值:在例程中比较值设置为了 SystemCoreClock / 4000,而根据VW55x用户手册,可以知道滴答定时器的时钟是AHB或者AHB/8,AHB又是160MHz,所以这个比较值为 160,000,000 / 4000 = 40,000。

(2)计数一次的时间:计数一次的时间就等于主频的倒数,为1 / 160,000,000 = 0.00000000625 (秒)

那么滴答定时器定时时间=40,000 * 0.00000000625 = 0.00025 (s) = 0.25 (ms)

现在的定时时间计算出来了,但是实际运行时间是1ms。

怎么都不对,填入比较值为 SystemCoreClock / 1000 是可以计算出为 1ms了,但是实际测试时又误差了4倍的时间。

所以现在很不理解,关于这个GD32VW553,RISC-V内核的芯片,它的滴答定时器是怎么算的?

在数据手册有说,该芯片为兆易创新和芯来科技一起完成,然后去芯来科技看内核手册《Bumblebee处理器
内核指令架构手册》,关于内核的滴答定时器的寄存器地址都对上了,滴答定时器的时钟也是来源于SOC CLK,而SOCCLK不就是160MHz吗?它的滴答定时器是怎么算的?

以下为例程中的滴答定时器初始化源码,使用以下源码才能实现1ms中断:
复制


void systick_config(void)

{

    //暂停计时 控制计时器运行或者暂停。如果该域的值为1,则计时器暂停计数,否则正常自增计数。

    SysTimer_SetControlValue(SysTimer_MTIMECTL_CMPCLREN_Msk);

    //设置计时器比较值,当计时器的计数值大于或者等于比较值,则产生计时器中断

    SysTimer_SetCompareValue(SystemCoreClock / 4000);



    __ECLIC_SetTrigIRQ(CLIC_INT_TMR, ECLIC_POSTIVE_EDGE_TRIGGER);

    //开启中断

    eclic_irq_enable(CLIC_INT_TMR, 0, 0);

}


  • 写回答

6条回答 默认 最新

  • @晓码自在 2024-01-19 10:23
    关注

    问题的答案是由GPT-4Plus模型生成,并经过@晓码自在博主的编辑修改:

    GD32VW553的滴答定时器(TIMER)的时钟源是SOC CLK,但是SOC CLK并不等于主频(CPU CLK),而是由主频除以一个预分频系数得到的。这个预分频系数可以通过寄存器SysTimer_MTIMECFGRCLKDIV位来设置,其默认值是4。因此,SOC CLK的实际频率是160MHz / 4 = 40MHz,而不是160MHz。

    如果您使用的是兆易创新提供的例程,那么您可以在gd32vw553c_start.h文件中找到以下宏定义:

    #define SystemCoreClockUpdate() (SystemCoreClock = (uint32_t)(160000000UL / (SysTimer_MTIMECFGR & SysTimer_MTIMECFGR_CLKDIV_Msk)))
    

    这个宏定义会根据SysTimer_MTIMECFGRCLKDIV位来更新SystemCoreClock的值,以反映SOC CLK的实际频率。因此,如果您在初始化滴答定时器之前调用了这个宏定义,那么SystemCoreClock的值应该是40MHz,而不是160MHz。

    这样,您的滴答定时器的计算就可以得到正确的结果了:

    滴答定时器定时时间= 滴答定时器比较值 * 计数一次的时间

    (1)滴答定时器比较值:在例程中比较值设置为了 SystemCoreClock / 4000 ,而根据上述分析,SystemCoreClock的值是 40,000,000,所以这个比较值为 40,000,000 / 4000 = 10,000。

    (2)计数一次的时间:计数一次的时间就等于SOC CLK的倒数,为1 / 40,000,000 = 0.000000025 (秒)

    那么滴答定时器定时时间=10,000 * 0.000000025 = 0.00025 (s) = 0.25 (ms)

    如果您想要实现1ms的中断,那么您需要将比较值设置为 SystemCoreClock / 1000 = 40,000。这样,滴答定时器定时时间=40,000 * 0.000000025 = 0.001 (s) = 1 (ms)。

    至于您说的实际测试时又误差了4倍的时间,我猜测可能是因为您没有正确配置ECLIC的触发模式。根据《Bumblebee处理器内核指令架构手册》,ECLIC支持四种触发模式:电平触发、上升沿触发、下降沿触发和双边沿触发。如果您使用的是双边沿触发,那么每当滴答定时器的计数值达到比较值时,都会产生一个中断,而不是只有在计数值从0开始重新计数时才产生一个中断。这样,您的中断频率就会变成2倍,而中断间隔就会变成0.5倍。因此,您需要将ECLIC的触发模式设置为上升沿触发或者下降沿触发,才能得到正确的中断间隔。


    以上方法希望对你有所帮助。如果还有疑问,欢迎随时提出。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 系统已结题 1月27日
  • 已采纳回答 1月19日
  • 赞助了问题酬金20元 1月19日
  • 创建了问题 1月19日

悬赏问题

  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 在虚拟机环境下完成以下,要求截图!
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见