打印
[应用相关]

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

[复制链接]
1567|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wakayi|  楼主 | 2021-7-4 17:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
使用芯片:STM32F103RCT6

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

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

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

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




使用特权

评论回复
沙发
wakayi|  楼主 | 2021-7-4 17:15 | 只看该作者
定时器配置

设置定时器2的计数频率为1MHz,输入捕获使用通道一,也就是PA0引脚,将PA0引脚设置为下拉模式,目的是为了在空闲时间保持信号稳定:




使用特权

评论回复
板凳
wakayi|  楼主 | 2021-7-4 17:15 | 只看该作者
中断分组设置


使用特权

评论回复
地板
wakayi|  楼主 | 2021-7-4 17:15 | 只看该作者
代码配置
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++;                                                                                // 溢出次数计数
    }
}


使用特权

评论回复
5
wakayi|  楼主 | 2021-7-4 17:15 | 只看该作者
///< 输入捕获回调函数
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;
        }
    }
}


使用特权

评论回复
6
wakayi|  楼主 | 2021-7-4 17:16 | 只看该作者
///< 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;
    }
}


使用特权

评论回复
7
wakayi|  楼主 | 2021-7-4 17:16 | 只看该作者
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();
    }
}



使用特权

评论回复
8
caoenq| | 2021-7-5 08:34 | 只看该作者
1M的频率能搞定?

使用特权

评论回复
9
香水城| | 2021-7-5 16:58 | 只看该作者
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

4083

帖子

1

粉丝