项目场景:
STM32F103系列通过 CubeMX 生成 TIMER 更新中断的驱动程序,实现溢出中断
问题描述:
调试模式下的代码运行现象与烧录单板运行时的现象不一致
准确来说:调试模式下定时器溢出时可以进入中断,在烧录至单板,复位运行无法正常进入中断
根据这个现象,没法持续进入中断的原因,初步怀疑是中断标志没清,为了验证参详,先理论分析分析
原因分析:
1、根据《STM32中文参考手册_V10.pdf》第 13.3.1 章节可以看到,用户可以通过使能或除能 TIMx_CR1 寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容可以立即或在每次产生更新事件UEV时,才从影子寄存器传送到真的寄存器里;通俗的理解,其实分频值 Prescaler 的设置和自动装载值?Period (ARR)等值在我们进行配置时,都会预先写入缓存寄存器进行锁存,只有产生更新事件时,寄存器才会把锁存打开,从影子寄存器里面拿到我们设置的那些值,所以说,如果想当前的配置生效,可以人为创建一个更新事件。
2、根据《STM32中文参考手册_V10.pdf》第 14.4.1 章节可以看到对于定时器的控制寄存器1(TIMx_CR1)的描述,是对上面解析的最好说明
3、手册解释过了,需要回归代码了
?(大家可以忽略我这个函数作用,我就当时手痒,拿硬件定时器来做了个 delay 玩玩)对于这个?TIM_HandleTypeDef 结构体,所有对于 TIMx_CR1 寄存器的配置都在于它的成员?Instance 中,很明显,我们通过 CubeMx 生成出来的代码,并没有对其进行过配置,也就是说,CR1 寄存器 位[7]?ARPE 和 位[2] URS、位[1] UDIS的值都为0,想要把配置的值生效于即将产生的中断,则需要生成一次 UEV 事件。大胆猜测 HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) 函数为了把值直接配置进去寄存器中,产生了一次中断
??这里进入Debug模式下,发现确实会置起中断标志
解决方案:
在??HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) 函数后,使用 HAL 库语句对中断标志进行人为清除
void WARSHIP_TIMER_Delayms(uint32_t ms)
{
/* USER CODE BEGIN TIM7_Init 0 */
/* USER CODE END TIM7_Init 0 */
/* USER CODE BEGIN TIM7_Init 1 */
htim7.Instance = TIM7;
htim7.Init.Prescaler = 7200 - 1; //时钟分频值,得出计数器时钟为10K
htim7.Init.CounterMode = TIM_COUNTERMODE_UP; //计数模式-向上计数
htim7.Init.Period = ms * 10; //自动装载值
htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟分频因子
htim7.Init.RepetitionCounter = 0;
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&htim7);
//下面这一句是影响运行现象的主要原因,必须在初始化后进行标志的清除
__HAL_TIM_CLEAR_IT(&htim7, TIM_IT_UPDATE);
TIMER_Delay2Target_Flag = 0;
/* USER CODE END TIM7_Init 1 */
/* USER CODE BEGIN TIM7_Init 2 */
HAL_TIM_Base_Start_IT(&htim7);
while (!TIMER_Delay2Target_Flag);
/* USER CODE END TIM7_Init 2 */
}
然后即可发现,调试和直接烧录运行,现象一致?
~ 以上内容,只是个人理解所得,可能有所不足,如有大神有其他见解,欢迎指正 ~
|