在日常使用定时器的时候我们往往会通过改变重装载值来实现不同时间的一个定时,就像我在一个项目功能中,使用的定时器7,刚开始我设置的是
//该CPU时钟是48M,分频系数为48,则48M/48=1M--->对应的是1us
//整个产生的中断时间=(分频系数+1)/系统时钟×(重装载值+1),这里对应的就是4800/48M*52=0.0052s=5.2ms
htim7.Instance = TIM7;
htim7.Init.Prescaler = 4800-1; //分频系数 0.1ms
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数器
htim7.Init.Period = 52-1; //自动装载值
htim7.Instance->CNT=0;
htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;//时钟分频因子
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_Base_Init(&htim7);
HAL_TIM_Base_Start_IT(&htim7);
这样的话定时器7就是每5.2ms进入一次中断,同时我代码中还有一个外部中断,我在外部中断中改变定时器7的ARR值,
__HAL_TIM_DISABLE(&htim7);
htim7.Instance->CNT=0;
htim7.Instance->ARR=105-1;
__HAL_TIM_ENABLE(&htim7);
想让他后面10.5ms进入一次中断,(注意重新设置重装载值的时候最好先关闭定时器,设置参数,再开启),按照之前对重装载值的理解,只要修改ARR寄存器,就会修改他的周期时间,那么产生更新中断的时间也就变了,但是我通过逻辑分析仪测出的现象是,代码执行完我外部中断中修改ARR的命令,并没有在10.5ms后进入定时器7的中断服务函数,而是先在5.2ms后进入中断服务函数,再在10.5ms后进入定时器7的中断服务函数。然后通过查找资料,定时器的寄存器有一个这样的功能:
这里有一个ARR的缓冲器,关于这个缓冲器我是这样理解的,
当开启缓冲器的时候,修改ARR的值,他会先将这个值放到缓冲器里,那么这样的话这个值作用的就是下下一个周期;当关闭缓冲器,修改ARR的值,直接作用于下个周期。即:
TIM_CR1_ARPE=1,有缓冲区,对ARR修改影响的是下下一个周期的定时长度;
TIM_CR1_ARPE=0,无缓冲区,对ARR修改影响的是下一个周期的定时长度;
然后在发现在初始化的时候
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
这个参数定义的就是开启缓冲器的开关
#define TIM_AUTORELOAD_PRELOAD_DISABLE (0x0000U) /*!< TIMx_ARR register is not buffered */
#define TIM_AUTORELOAD_PRELOAD_ENABLE (TIM_CR1_ARPE) /*!< TIMx_ARR register is buffered */
之后我将这个参数改为TIM_AUTORELOAD_PRELOAD_DISABLE 时,通过验证,确实是这个问题,故分享出来给大家参考,有不当之处还请指出,谢谢!