stm32定时器中断使用(ARR寄存器使用注意)

stm32定时器中断使用(ARR寄存器注意)

1.自动重装载器介绍

**自动重装载寄存器 ARR **是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。在物理上这个寄存器对应2个寄存器,一个是程序员可以写入或读出的寄存器,称为preload register(预装载寄存器),另一个是程序员看不见的、但在操作中真正起作用的寄存器,称为shadow register(影子寄存器)。

2.ARR使用注意

stm32定时器更新中断时使用自动重装载寄存器时需要注意其自身的影子寄存器

根据TIMx_CR1寄存器中APRE位的设置,preload register的内容可以随时传送到shadow register,即两者是连通的(permanently),或者在每一次更新事件(UEV)时才把preload register的内容传送到shadow register

预装载寄存器ARR传送到影子寄存器,有两种方式,一种是立刻更新,一种是等触发事件之后更新;这两种方式主要取决于寄存器TIMx->CR1中 APRE

使用Cubemx进行stm32代码生成时,通常会让你选择是否使能 auto-reload preload 选项,根据网上对HAL库的使用和博主对定时器的使用都会建议 使能 此处。

image-20230820123838268

  • Enable auto-reload preload 代码使用为如下红框处

    image-20230820124754707

    对 auto-reload preload 使能 即 APRE = 1

    此时当ARR值被修改时,必须在下一次事件UEV发生后才能更新影子寄存器的值

  • Disable auto-reload preload

    image-20230820124719879

    不使能 auto-reload preload 即 APRE = 0

    此时当ARR值被修改时,同时马上更新影子寄存器的值

个人使用时出错总结

本人使用定时器通过中断改变IO端口的高低电平输出PWM波形时,按照网上各个博主所说使能了 auto-reload preload,并且本人在定时器中断代码中直接修改ARR寄存器。最终未能输出直接想要的PWM波形。经过多日排查发现是 使能 auto-reload preload 的问题,过程比较煎熬,但是坚持过来了。

使用的中断代码如下

void TIM2_IRQHandler(void)
{
    static uint8 i = 1;
    if (TIM2->SR&0X0001) 
    {

        switch(i)
        {
            case 1: 
                //SERVO0(1);//虚拟
                TIM2PWMChange(ServoPwm[0]);
                break;
            case 2:                
                TIM2PWMChange(2500 - ServoPwm[0]);
                break;

            case 3: 
                SERVO1(1);//2-7都是真实舵机
                TIM2PWMChange(ServoPwm[1]);
                break;
            case 4: 
                SERVO1(0);
                TIM2PWMChange(2500 - ServoPwm[1]);
                break;

            case 5: 
                SERVO2(1);//2-7都是真实舵机
                TIM2PWMChange(ServoPwm[2]);
                break;
            case 6: 
                SERVO2(0);
                TIM2PWMChange(2500 - ServoPwm[2]);
                break;

            case 7: 
                SERVO3(1);//2-7都是真实舵机
                TIM2PWMChange(ServoPwm[3]);
                break;
            case 8: 
                SERVO3(0);
                TIM2PWMChange(2500 - ServoPwm[3]);
                break;

            case 9: 
                SERVO4(1);//2-7都是真实舵机
                TIM2PWMChange(ServoPwm[4]);
                break;
            case 10: 
                SERVO4(0);
                TIM2PWMChange(2500 - ServoPwm[4]);
                break;

            case 11: 
                SERVO5(1);//2-7都是真实舵机
                TIM2PWMChange(ServoPwm[5]);
                break;
            case 12: 
                SERVO5(0);
                TIM2PWMChange(2500 - ServoPwm[5]); 
                break;

            case 13: 
                SERVO6(1);//2-7都是真实舵机
                TIM2PWMChange(ServoPwm[6]);
                break;
            case 14: 
                SERVO6(0);
                TIM2PWMChange(2500 - ServoPwm[6]); 
                break; 

            case 15:                 
                TIM2PWMChange(ServoPwm[7]);
                break;
            case 16: 
                TIM2PWMChange(2500 - ServoPwm[7]);
                i = 0;
                break;  
            }   
    }
    i++;

    TIM2->SR&=~(1<<0);//清除中断标志位
}

以上代码为驱动六个舵机的代码,由于各个舵机周期必须是20ms,区间必须是500-2500,所以加入两个虚拟舵机(空操作,加以理解),以上代码参考幻尔科技LeArm机械臂代码

如果使用如上代码时 使能 auto-reload preload ,便导致当进入 case 2 时,此时进行一次中断更新,此时重装载值为 TIM2PWMChange(ServoPwm[0])ServoPwm[0] 设定的值,整体上就每次延迟一个,跟我最初设定值正好相反而且设定的值各往前一个移动。

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独吾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值