GD32 Timer调试

GD32 Timr定时器看起来比较复杂啊。一看GD32E10x 的SPEC:一个高级定时器,三个通用定时器,还有一个基本定时器。

项目上想用来做分时处理程序都不知道用哪个?

就用通用的定时器 timer1

看下clock tree

TIMER1的时钟是CK_TIMER1,要提供CK_TIMER1需要TIMER1 enable并且需要提供具体的时钟

具体的时钟

if(APB1 prescale = 1 ) x 1 else x 2

这个是什么意思?

我们的CK_SYS时钟(系统时钟)经过Prescaler之后最大频率是CK_AHB(120MHz)

然后经过预分频,APB1频率最大到60MHz,如果预分频系数是1的话,则提供到TIMER的频率是x2。

也就是60*2 = 120MHz

所以TIMER1的时钟就用基于120MHz去分频

我想每200ms 获取一次timer1的中断。改怎么办?

有两个参数可以一起去实现这个功能。

1个事TIMER的prescale 可以先把这个120MHz分频,比如我分频为1MHz,那么prescale就是120,不过这里timer_initpara.prescaler不能设置为120,要设置为119.

因为具体的计算方式是120MHz/(prescaler+1) 

这样拿到了1MHz的clock.那获取每200ms的中断再要做什么呢?

这里有reload 参数timer_initpara.period ,官方成为“TIMER counter auto reload register”

这个reload参数意思是:当计数计到period参数的时候就做一次更新,从0开始重新计算,中断就产生一次。

前面1MHz 意思是1s 可以计数1000 000次。也就是1ms 可以计数1000次,我需要200ms更新一次,那就说我需要计数 200 * 1000,所以reload就是200 * 1000 = 200 000

timer_initpara.period 就是写为200 000 

看有一篇文章是基于STM32介绍的Timer 

STM32的可能是需要将200000 再减去 1

具体链接是 https://blog.csdn.net/private_void_main/article/details/81491015

可以参考下。

我还没验证过GD32的,但是我看GD的官方例子上是按我说的方式去写的

 

这是关于中断周期的设置。

另外一个我的疑惑是关于clockdivision的设置

timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;

网上那位兄弟说是“设置与进行输入捕获相关的分频 设置的这个值不会影响定时器的时钟频率,我们一般设置为TIM_CKD_DIV1,也就是不分频"

我具体也没再继续研究。

总体上关于timer的设置就是这些了。

贴下代码:

void timer_config(void)
{
    /* TIMER0 configuration: generate PWM signals with different duty cycles:
       TIMER0CLK = SystemCoreClock / 120 = 1MHz */
	
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER0);
    timer_deinit(TIMER0);

    /* TIMER0 configuration */
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 200000;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER0,&timer_initpara);
	
    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER0);
    timer_enable(TIMER0);
}

这里验证的时候遇到问题了period 设置为了200000,发现中断会一直产生。

当我把这个值设置小了之后,同时prescaler也改变

    /* TIMER1 configuration */
    timer_initpara.prescaler         = 1199;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 19999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER1,&timer_initpara);

这样就可以了按照200ms一次来一个中断。

猜测是不是period溢出了?

果然,让我把period设置为65535的时候,中断周期正常,设置为65536的时候就没有中断了。

当我再设置为65537的时候,中断就不停的出现了。

看下这个数据类型

uint32_t period;                                         /*!< period value */

是u32类型的啊,为什么会有这样的问题呢?

看下具体的寄存器

在timer_init中

    /* configure the autoreload value */
    TIMER_CAR(timer_periph) = (uint32_t)initpara->period;
#define TIMER_CAR(timerx)                REG32((timerx) + 0x2CU)           /*!< TIMER counter auto reload register */
/* bit operations */
#define REG32(addr)                  (*(volatile uint32_t *)(uint32_t)(addr))
#define TIMER1                           (TIMER_BASE + 0x00000000U)
/* advanced peripheral bus 1 memory map */
#define TIMER_BASE            (APB1_BUS_BASE + 0x00000000U)  /*!< TIMER base address               */
/* peripheral memory map */
#define APB1_BUS_BASE         ((uint32_t)0x40000000U)        /*!< apb1 base address                */

为什么呢?。。。。。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值