基本定时器实现ms定时的过程
参数配置
/*设置预分频值,默认是72M*/
htim7.Init.Prescaler = 71;
/*设置自动重新加载寄存器的周期值*/
htim7.Init.Period = 999;
/*指定计数器模式。*/
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
/*指定自动重新加载预加载。*/
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
/*设置时钟分配*/
htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
/*指定重复计数器值*/
htim7.Init.RepetitionCounter = 0;
步骤01: 查看入口函数HAL_TIM_Base_Init
步骤02:查看入口函数TIM_Base_SetConfig
/**
* @brief 时基配置
* @param TIMx TIM peripheral
* @param Structure TIM Base configuration structure
* @retval None
*/
void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure) {
uint32_t tmpcr1;
tmpcr1 = TIMx->CR1;
/* 设置 TIM 时基单位参数 ---------------------------------------*/
if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx)) { /*针对高级定时器和通用定时器*/
/* 选择计数器模式 */
tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);/**/
tmpcr1 |= Structure->CounterMode;
}
if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx)) {/*针对高级定时器和通用定时器*/
/* 设置时钟分频 */
tmpcr1 &= ~TIM_CR1_CKD;
tmpcr1 |= (uint32_t) Structure->ClockDivision;
}
/* @note 设置自动重新加载预加载(这里就是在修改寄存器了) */
MODIFY_REG(tmpcr1, TIM_CR1_ARPE, Structure->AutoReloadPreload);
/* 更新程序里面的控制寄存器1的值*/
TIMx->CR1 = tmpcr1;
/* 设置自动重新加载值 */
TIMx->ARR = (uint32_t) Structure->Period;
/* 设置预分频器值 */
TIMx->PSC = Structure->Prescaler;
if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx)) {/*针对高级定时器*/
/* 设置重复计数器值 */
TIMx->RCR = Structure->RepetitionCounter;
}
/* 生成更新事件以立即重新加载预分频器和重复计数器(仅适用于高级计时器)值 */
TIMx->EGR = TIM_EGR_UG;
}
步骤03: 查看HAL_TIMEx_MasterConfigSynchronization函数
/**
* @brief 在主模式下配置 TIM。
* @param htim TIM handle.
* @param sMasterConfig 指向包含所选触发器输出 (TRGO) 和主从模式的TIM_MasterConfigTypeDef结构的指针。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
TIM_MasterConfigTypeDef *sMasterConfig) {
uint32_t tmpcr2;
uint32_t tmpsmcr;
/* 参数校验 */
assert_param(IS_TIM_MASTER_INSTANCE(htim->Instance));
assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
/* 检查并上锁 */
__HAL_LOCK(htim);
/* 逻辑上状态变化 */
htim->State = HAL_TIM_STATE_BUSY;
/* 获取 TIMx CR2 寄存器值 */
tmpcr2 = htim->Instance->CR2;
/* 获取从模式控制寄存器 */
tmpsmcr = htim->Instance->SMCR;/*针对高级定时器和通用定时器*/
/* 复位主模式选择 */
tmpcr2 &= ~TIM_CR2_MMS;
/*选择在主模式下送到从定时器的同步信息(TRGO)*/
/* 基本定时器支持: 复位、使能、更新 */
tmpcr2 |= sMasterConfig->MasterOutputTrigger;
/* @note 更新CR2寄存器的值 */
htim->Instance->CR2 = tmpcr2;
if (IS_TIM_SLAVE_INSTANCE(htim->Instance)) {/*针对高级定时器和通用定时器*/
/* Reset the MSM Bit */
tmpsmcr &= ~TIM_SMCR_MSM;
/* Set master mode */
tmpsmcr |= sMasterConfig->MasterSlaveMode;
/* @note 更新SMCR寄存器的值 */
htim->Instance->SMCR = tmpsmcr;
}
/* 逻辑上状态变化 */
htim->State = HAL_TIM_STATE_READY;
/* 检查并解锁 */
__HAL_UNLOCK(htim);
return HAL_OK;
}
步骤04:查看HAL_TIM_Base_Start_IT
/**
* @brief 在中断模式下启动 TIM 基生成。
* @param htim TIM Base handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) {
uint32_t tmpsmcr;
/* 参数检查 */
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* 检查 TIM 状态 */
if (htim->State != HAL_TIM_STATE_READY) {
return HAL_ERROR;
}
/* 设置 TIM 状态 */
htim->State = HAL_TIM_STATE_BUSY;
/* 启用 TIM 更新中断 */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
/* 启用外设,但在触发模式下除外,在触发模式下,通过触发器自动完成使能 */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance)) { /*针对高级定时器和通用定时器*/
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr)) {
__HAL_TIM_ENABLE(htim);
}
} else {
__HAL_TIM_ENABLE(htim);
}
/* Return function status */
return HAL_OK;
}
步骤05:最简化写法
void tim6_simple() {
__HAL_RCC_TIM6_CLK_ENABLE();
/* 中断配置 */
HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM6_IRQn);
TIM6->CR1 |= TIM_AUTORELOAD_PRELOAD_DISABLE;
TIM6->PSC = 71;
TIM6->ARR = 999;
/* 复位主模式选择 */
TIM6->CR2 &= ~TIM_CR2_MMS;
/*选择在主模式下送到从定时器的同步信息(TRGO)*/
/* 基本定时器支持: 复位、使能、更新 */
TIM6->CR2 |= TIM_TRGO_RESET;
TIM_ENABLE_IT(TIM6, TIM_IT_UPDATE);
TIM_ENABLE(TIM6);
}
步骤06: 中断函数重写(需要开启对应的中断)
#define TIM_ENABLE(__HANDLE__) ((__HANDLE__)->CR1|=(TIM_CR1_CEN))
#define TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->DIER |= (__INTERRUPT__))
#define TIM_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->SR &(__FLAG__)) == (__FLAG__))
#define TIM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->DIER & (__INTERRUPT__)) \
== (__INTERRUPT__)) ? SET : RESET)
#define TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->SR = ~(__INTERRUPT__))
void TIM6_IRQHandler(void) {
static volatile u32 cnt = 0;
/* TIM 更新事件 */
if (TIM_GET_FLAG(TIM6, TIM_FLAG_UPDATE) != RESET) {
if (TIM_GET_IT_SOURCE(TIM6, TIM_IT_UPDATE) != RESET) {
TIM_CLEAR_IT(TIM6, TIM_IT_UPDATE);
cnt++;
if (cnt >= 1000) {
cnt = 0;
pin_toggle(GPIOB, LED_G);
}
}
}
}