STM32源码阅读之HAL库(HAL_TIM_Base_Init)

基本定时器实现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

STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第1张图片STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第2张图片STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第3张图片

步骤02:查看入口函数TIM_Base_SetConfig

STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第4张图片在这里插入图片描述
STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第5张图片

/**
  * @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函数

STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第6张图片
STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第7张图片


/**
  * @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

STM32源码阅读之HAL库(HAL_TIM_Base_Init)_第8张图片

/**
  * @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);
            }

        }
    }
}

你可能感兴趣的:(HAL源码,stm32,单片机,嵌入式硬件)