测量原理:

检测到下降沿后,就开始计时,直到检测到上升沿后再停止计时,在这个过程中,我们设置的自动重装载值ARR最大为65536,所以在按键按下去后,中间可能会有N多次的溢出时间,那么我们最后可以使用这样一个计算公式,time = arr_cnt*65536+ccr_cnt,arr_cnt是自动重装载次数,ccr_cnt是寄存器中的计数,根据计算公式,就可以得到按键从捕获到下降沿到上升沿的时间了。

配置过程:

参考这一篇博客:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/142829989

 1、准备工作

我们在进行捕获的时候,通常需要一些标志位来进行操作,通常需要用到(成功捕获、下降捕获、上升捕获,时间计数)这样四个标志位,使用要给结构体把它们定义出来。

struct
{
    uint8_t succeed_flag;
    uint8_t rising_flag;
    uint8_t falling_flag;
    uint8_t time_cnt;
} caputure_status = {0};

2、编写代码

在参考博客中的回调函数HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)中,我们需要实现一个流程图:

根据这个流程图,我们可以写出捕获到下降沿的代码:

printf("捕获到下降沿\n");
memset(&caputure_status,0,sizeof(caputure_status));
caputure_status.falling_flag =1;
__HAL_TIM_DISABLE(&ic_handle);
__HAL_TIM_SET_COUNTER(&ic_handle,0);
TIM_RESET_CAPTUREPOLARITY(&ic_handle, TIM_CHANNEL_2);
TIM_SET_CAPTUREPOLARITY(&ic_handle, TIM_CHANNEL_2,TIM_ICPOLARITY_RISING);
__HAL_TIM_ENABLE(&ic_handle);

第一行:如果succeed_flag=0,判断falling_flag是否等于0,若等于,则在串口中显示“捕获到下降沿”

第二行:memset函数用于对一整个结构体的清零,这里我们就是把四个标志位全部清零。

第三行:将falling_flag = 1;

第四行:关闭定时器。

第五行:将定时器清零。

第六行:清除通道设置

第七行:设置通道为上升沿捕获

第八行:重新开启定时器

以上代码就把捕获下降沿状态转换为捕获上升沿状态。

同样的,我们可以根据流程图写出捕获上升沿的代码:

printf("捕获到上升沿\n");
caputure_status.succeed_flag =1;
last_cnt = HAL_TIM_ReadCapturedValue(&ic_handle,TIM_CHANNEL_2);
TIM_RESET_CAPTUREPOLARITY(&ic_handle, TIM_CHANNEL_2);
TIM_SET_CAPTUREPOLARITY(&ic_handle, TIM_CHANNEL_2,TIM_ICPOLARITY_FALLING);

第一行: 若检测到succeed_flag = 1,在串口输出“捕获到上升沿”

第二行:将succeed_flag置为1,也就是表明一次完整的按键检测已经完成。

第三行:将定时器中ccr的值读取出来,方便计算

第四行~第五行同上

这里不需要将结构体的标志位置为0,我们在后面调用的函数中再使用。现在已经把流程图的代码写完了,因为我们的要求是显示出按键按下的时间,所以根据计算公式,我们已经知道了ccr中的值,还不知道ARR溢出了多少次,下面就编写ARR溢出的次数。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM2)
    {
        if(caputure_status.succeed_flag == 0)
        {
            if(caputure_status.falling_flag == 1)
            {
                caputure_status.time_cnt++;
            }
        }
    }
}

调用HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)函数

第一行:判断是否在使用定时器2

第二行:判断是否成功按下

第三行:若成功按下,检测到下降沿,则溢出次数加1;

最后我们需要一个函数输出按键按下的状态和按下的时间

void pressed_time_get(void)
{
    if(caputure_status.succeed_flag == 1)
    {
        printf("按下时间:%d us\r\n",caputure_status.time_cnt*65536 + last_cnt);
        memset(&caputure_status,0,sizeof(caputure_status)); 
    }
}

第一行:如果成功按下

第二行:串口打印时间,时间是根据计算公式来的

第三行:清零结构体

在主函数中不断调用这个函数即可,注意需要延时一点点。

效果:

以上我们就完成了对按键按下时间的捕获。

作者:ljhlovezyx

物联沃分享整理
物联沃-IOTWORD物联网 » STM32测量按键按下时长

发表回复