STM32 HAL库STM32脉冲宽度和周期测量

HAL库STM32脉冲宽度和周期测量


使用芯片:STM32F103RCT6

思路:定时器设置为1MHZ的计数频率,定时计数器增加一就是增加1us

① 首先设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;
② 然后切换为下降沿捕获,捕获下降沿记录此刻的时间计数值;
③ 最后设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;

对于16bit定时器,最大可计数0xFFFF,也就是65535us,那么:高电平持续的时间 = 定时器溢出计数 * 0xFFFF + 当前计数值
对于32bit定时器,最大可计数0xFFFFFFFF,也就是4294.967295s,这个时间足够测量脉冲宽度的了,那么:高电平持续的时间 = 当前计数值

高电平持续的时间 = ② - ①
周期 = ③ - ①


定时器配置

设置定时器2的计数频率为1MHz,输入捕获使用通道一,也就是PA0引脚,将PA0引脚设置为下拉模式,目的是为了在空闲时间保持信号稳定:
STM32 HAL库STM32脉冲宽度和周期测量_第1张图片
STM32 HAL库STM32脉冲宽度和周期测量_第2张图片
STM32 HAL库STM32脉冲宽度和周期测量_第3张图片


中断分组设置

STM32 HAL库STM32脉冲宽度和周期测量_第4张图片


代码配置

tim.c中添加如下代码:


__IO uint32_t TIM2_TIMEOUT_COUNT = 0;			///< 定时器2定时溢出计数
uint32_t TIM2_CAPTURE_BUF[3]   = {0, 0, 0};		///< 分别存储上升沿计数、下降沿计数、下个上升沿计数
__IO uint8_t TIM2_CAPTURE_STA = 0xFF;			///< 状态标记

/**
 * 设置TIM2输入捕获极性
 * @param TIM_ICPolarity:
 *        TIM_INPUTCHANNELPOLARITY_RISING  :上升沿捕获
 *        TIM_INPUTCHANNELPOLARITY_FALLING :下降沿捕获
 *        TIM_INPUTCHANNELPOLARITY_BOTHEDGE:上升沿和下降沿都捕获
 */
inline void TIM2_SetCapturePolarity(uint32_t TIM_ICPolarity)
{
    htim2.Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
    htim2.Instance->CCER |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
}

/// 定时器2时间溢出回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == htim2.Instance)
    {
        TIM2_TIMEOUT_COUNT++;										// 溢出次数计数
    }
}

///< 输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == htim2.Instance)
    {
        switch (TIM2_CAPTURE_STA)
        {
        case 1:
        {
            printf("准备捕获下降沿...\r\n");
            TIM2_CAPTURE_BUF[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
            TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_FALLING);					// 设置为下降沿触发
            TIM2_CAPTURE_STA++;
            break;
        }
        case 2:
        {
            printf("准备捕获下个上升沿...\r\n");
            TIM2_CAPTURE_BUF[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
            TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);					// 设置为上升沿触发
            TIM2_CAPTURE_STA++;
            break;
        }
        case 3:
        {
            printf("捕获结束...\r\n");
            printf("# end ----------------------------------------------------\r\n");
            TIM2_CAPTURE_BUF[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
            HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1);									// 停止捕获
            HAL_TIM_Base_Stop_IT(&htim2);												// 停止定时器更新中断
            TIM2_CAPTURE_STA++;
            break;
        }
        default:
            break;
        }
    }
}

///< TIM2轮训状态切换
inline void TIM2_Poll(void)
{
    switch (TIM2_CAPTURE_STA)
    {
    case 0:
    {
        printf("# start ----------------------------------------------------\r\n");
        printf("准备捕获上升沿...\r\n");
        TIM2_TIMEOUT_COUNT = 0;
        __HAL_TIM_SET_COUNTER(&htim2, 0);											// 清除定时器2现有计数
        memset(TIM2_CAPTURE_BUF, 0, sizeof(TIM2_CAPTURE_BUF));						// 清除捕获计数
        TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING);					// 设置为上升沿触发
        HAL_TIM_Base_Start_IT(&htim2);												// 启动定时器更新中断
        HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);									// 启动捕获中断
        TIM2_CAPTURE_STA++;
        break;
    }

    case 4:
    {
        uint32_t high  = TIM2_CAPTURE_BUF[1] - TIM2_CAPTURE_BUF[0];
        uint32_t cycle = TIM2_CAPTURE_BUF[2] - TIM2_CAPTURE_BUF[0];
        float frq = 1.0 / (((float)cycle) / 1000000.0);
        TIM2_CAPTURE_STA++;

        printf("\r\n\r\n");
        printf("################################# START #########################################\r\n");
        printf("高电平持续时间:%dms\r\n", high / 1000);
        printf("周期          :%dms\r\n", cycle / 1000);
        printf("频率          :%fHz\r\n", frq);
        printf("################################## END ##########################################\r\n\r\n");
        break;
    }

    default:
        break;
    }
}

main.c:

int main()
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    DEBUG_UART_Init();
    MX_TIM2_Init();
    printf("================================ 系统运行! ================================  \r\n");
    while(1)
    {
        TIM2_Poll();
        DEBUG_UART_RecvHandler();
    }
}

说明:串口一接串口调试助手,勾选发送新行,向单片机发送任意字符以此来启动输入捕获。


ends…

你可能感兴趣的:(STM32)