打印

惭愧的对于定时器定时的理解。十年还有错!

[复制链接]
1229|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lvben5d|  楼主 | 2019-7-27 16:03 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lvben5d 于 2019-8-8 13:19 编辑

作为32位机,比起8位机捉襟见肘少的可怜的定时器,最弱的入门级32也有4个常规定时器和1个systick。 我最常用的是向上计数模式,极少项目用作向下定时。下面以GD32F130为例,贴图容易犯错的1个地方:
        /* TIMER14 configuration */
    TMinitpara.timer_prescaler            = 7999;                 //36000 000/(8000-1)==》4.5Khz =  222us
    TMinitpara.timer_alignedmode       = TIMER_COUNTER_EDGE;
    TMinitpara.timer_counterdirection  = TIMER_COUNTER_UP;
    TMinitpara.timer_period                 = 1;                    //字节超时设计为 222us ms 扫一行  
    TMinitpara.timer_repetitioncounter  = 0;            
    timer_init(TIMER14, &TMinitpara);  
     timer_interrupt_flag_clear(TIMER14, TIMER_INT_UP);
     timer_interrupt_enable(TIMER14, TIMER_INT_UP);


void TIMER14_IRQHandler(void)
{
        timer_disable(TIMER14);
        timer_interrupt_flag_clear(TIMER14, TIMER_INT_UP);  
        timer_counter_value_config(TIMER14, 0); //
        show_256x16_oneline(Sysinfo.scan_line);
        if(16 == ++Sysinfo.scan_line)   Sysinfo.scan_line = 0; //从第1行 扫到16行 再回到1行 舟而复始 索引0 是因为数组存储
    timer_enable(TIMER14);
}
PS: 来一波广告, 喜欢MINI主机的兄弟可以采购一组。 https://item.taobao.com/item.htm?id=600110357826  本人小店



微信1.jpg (158.37 KB )

微信1.jpg

微信2.jpg (252 KB )

微信2.jpg

微信3.jpg (311.96 KB )

微信3.jpg

使用特权

评论回复
沙发
sonicll| | 2019-7-29 14:12 | 只看该作者
你这段代码有好多错误吧,prescaler,period,repetitioncounter这三个参数,应该设置成你需要的值减1才对,比如你的分频系数prescaler想要8000分频,应该赋值7999才对,同理周期100,period需要赋值99。repetitioncounter代表溢出多少次才产生更新事件,0每次溢出都更新,1每两次溢出才更新。还有你说的打开定时器就中断,是因为timer_init()函数内部在配置完寄存器后,手动产生了一次更新

使用特权

评论回复
板凳
firegod01cn| | 2019-8-7 12:01 | 只看该作者
沙发说的不错~~~楼主的理解很有问题啊 ~~ 你这样理解,程序不会出错吗?

使用特权

评论回复
地板
lvben5d|  楼主 | 2019-8-7 20:31 | 只看该作者
本帖最后由 lvben5d 于 2019-8-9 14:42 编辑
sonicll 发表于 2019-7-29 14:12
你这段代码有好多错误吧,prescaler,period,repetitioncounter这三个参数,应该设置成你需要的值减1才对 ...



使用特权

评论回复
5
sonicll| | 2019-8-8 09:14 | 只看该作者
lvben5d 发表于 2019-8-7 20:31
谢谢2楼提点, prescaler跟repetitioncounter  我查看手册你说的都很对。 period 这个不需要-1吧。 因为 ...

period也需要-1,从1数到100才是100个,从0数到100是101个,所以应该从0数到99

使用特权

评论回复
6
lvben5d|  楼主 | 2019-8-8 09:29 | 只看该作者
sonicll 发表于 2019-8-8 09:14
period也需要-1,从1数到100才是100个,从0数到100是101个,所以应该从0数到99

中断函数里 我发现还是要关闭下定时器  再打开程序才正常。void TIMER14_IRQHandler(void)
{
        timer_disable(TIMER14);
        timer_interrupt_flag_clear(TIMER14, TIMER_INT_UP);  
        timer_counter_value_config(TIMER14, 0);
        show_256x16_oneline(Sysinfo.scan_line);
        if(16 == ++Sysinfo.scan_line)   Sysinfo.scan_line = 0; //从第1行 扫到16行 再回到1行 舟而复始
        timer_enable(TIMER14);
}

使用特权

评论回复
7
sonicll| | 2019-8-8 09:35 | 只看该作者
lvben5d 发表于 2019-8-8 09:29
中断函数里 我发现还是要关闭下定时器  再打开程序才正常。void TIMER14_IRQHandler(void)
{
        timer_disa ...

具体是什么故障现象?不在中断服务函数里关闭定时器会怎么样?

使用特权

评论回复
8
lvben5d|  楼主 | 2019-8-8 09:37 | 只看该作者
本帖最后由 lvben5d 于 2019-8-8 13:14 编辑
sonicll 发表于 2019-8-8 09:35
具体是什么故障现象?不在中断服务函数里关闭定时器会怎么样?

void TIMER14_IRQHandler(void)
{
        //timer_disable(TIMER14);
        timer_interrupt_flag_clear(TIMER14, TIMER_INT_UP);  
        //timer_counter_value_config(TIMER14, 0);
        show_256x16_oneline(Sysinfo.scan_line);
        if(16 == ++Sysinfo.scan_line)   Sysinfo.scan_line = 0; //从第1行 扫到16行 再回到1行 舟而复始 索引0 是因为数组存储
    //timer_enable(TIMER14);
}
定时器向上计数,产生更新事件的时候,定时器CNT 其实没有马上回0(实际要到下一个时钟结束后),只要不关闭定时器,会继续计时,所以中断里仅仅只是清下标志位,感觉我的扫描就出不来。发现是里面 show_256x16_oneline(Sysinfo.scan_line);  执行的时间 大于220us了 ,导致MCU不断死在定时器T14里。

使用特权

评论回复
9
sonicll| | 2019-8-8 09:55 | 只看该作者
本帖最后由 sonicll 于 2019-8-8 10:07 编辑
lvben5d 发表于 2019-8-8 09:37
void TIMER14_IRQHandler(void)
{
        //timer_disable(TIMER14);

可能是show_256x16_oneline()执行时间过长的问题。

关于period的计算,我找个板子试试,我也有点儿迷糊了

使用特权

评论回复
10
sonicll| | 2019-8-8 10:38 | 只看该作者

period值确实需要设置为实际值减1,看手册里这个图。
这图里重装载寄存器值为0x63,如果重装载寄存器设置为1的话,CNT值会像0,1,0,1,0,1这样循环,也就是每两个PSC_CLK产生一次事件,所以实际周期值是2。
你1楼的计算,应该是36000000/(7999+1)/(1+1),周期444us。
需要注意,重装载寄存器设置为0的话,计数器不工作,这点在GD的手册里没有写,但实际写0确实不工作,ST的手册有明确说明


使用特权

评论回复
11
lvben5d|  楼主 | 2019-8-8 10:51 | 只看该作者
sonicll 发表于 2019-8-8 10:38
period值确实需要设置为实际值减1,看手册里这个图。
这图里重装载寄存器值为0x63,如果重装载寄存器设置 ...

你说非常好,我想如果在中断里,关闭定时器,自己在timer_counter_value_config(TIMER14, 0);   这样period 就不需要-1了。

使用特权

评论回复
12
gx_huang| | 2019-8-8 11:18 | 只看该作者
如果你只调用别人的库函数,不看数据手册,别说10年了,100年后也是这个样子的,无非1年的经验重复了100年。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

746

帖子

12

粉丝