测量按键按下时间

如图回顾一下上面的测量案件按下时间原理图

当检测到下降沿时, 定时器中断  计数器清零 统计在低电平期间 溢出arr的次数  根据下面公式 将psc设置为72   这样就可设置一次计数的时间为0.000001s   只需统计计数个数即可    当检测到上升沿时 记录当前ccr的值   就可统计出来

在此回调函数中 HAL_TIM_IC_CaptureCallback()  一定要注意设置succeed_flag标志位 这样当一次捕获下降沿 一次捕获上升沿后  succeed_flag 置1  激发另一个if条件语句即pressed_time_get  函数    从而计算按键按下时间   结束后一定要用memset(&capture_status, 0, sizeof(capture_status));   来清除结构体当中的值  从而为下一次再次捕获做准备  

HAL_TIM_PeriodElapsedCallback()  用此函数来计算中断溢出次数   这个也是回调函数  时内部自己运行的 即中断溢出函数   

代码如下

#include "ic.h"
#include "stdint.h"
#include "stdio.h"
#include "string.h"

struct
{
    uint8_t succeed_flag;      //检测是否成功捕获到上升or下降沿标志位
    uint8_t rising_flag;       //上升沿标致位
    uint8_t falling_flag;       //下降沿标志位
    uint8_t timout_cnt;        //溢出的次数标致位
}capture_status ={0};

uint16_t lastccr=0;


TIM_HandleTypeDef ic_handle={0};

void ic_init(uint16_t arr,uint16_t psc)
{
    TIM_IC_InitTypeDef ic_config ={0};
    ic_handle.Instance = TIM2;
    ic_handle.Init.Period = arr;
    ic_handle.Init.CounterMode =TIM_COUNTERMODE_UP;
    ic_handle.Init.Prescaler = psc;
    HAL_TIM_IC_Init(&ic_handle);                       //时基工作参数配置
    
    
    ic_config.ICPolarity = TIM_ICPOLARITY_FALLING;     //选择极性   刚开始捕获的是下降沿 故选择下降沿的模式
    ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI;  //定时器2被直接连接到相应的输入捕获通道
    ic_config.ICPrescaler = TIM_ICPSC_DIV1;            //默认不分频
    ic_config.ICFilter =0;                            //滤不滤波   不滤波设置为0
    HAL_TIM_IC_ConfigChannel(&ic_handle,&ic_config,TIM_CHANNEL_2);       //输入通道的配置   捕获的边沿   映射   分频   滤波
    __HAL_TIM_ENABLE_IT(&ic_handle,TIM_IT_UPDATE);   //更新中断使能   第二个参数为更新中断的模式
    HAL_TIM_IC_Start_IT(&ic_handle,TIM_CHANNEL_2);  //使能捕获 捕获中断及计数器
   
}

void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{

    if(htim->Instance == TIM2)
    {
     //①定义初始化结构体
    GPIO_InitTypeDef gpio_initstruct;
       //打开时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();   //打开GPIO的时钟
    __HAL_RCC_TIM2_CLK_ENABLE();  //打开定时器的时钟
    //调用GPIO初始化函数
    gpio_initstruct.Pin = GPIO_PIN_1 ;                         //LED1、LED2对应的引脚
    gpio_initstruct.Pull = GPIO_PULLUP;                        //上拉   
    gpio_initstruct.Mode =GPIO_MODE_INPUT;                //推挽复用输出
    gpio_initstruct.Speed =GPIO_SPEED_FREQ_HIGH;              //高速
    HAL_GPIO_Init(GPIOA,&gpio_initstruct);
    HAL_NVIC_SetPriority(TIM2_IRQn, 2,2);           //设置NVIC
    HAL_NVIC_EnableIRQ(TIM2_IRQn);                  //设置NVIC               
        
        
    }
}


void TIM2_IRQHandler(void)
{

    HAL_TIM_IRQHandler(&ic_handle);
    
}
//下面代码冗余 
/*
void HAL_TIM_IC_CaptureCallback (TIM_HandleTypeDef *htim)
{
   //printf("捕获到下降沿\r\n");
    if(htim->Instance == TIM2)     //回调函数中也有很多定时器  因此要确是否是定时器2
    {
        if(capture_status.succeed_flag == 0)
        {
            if(capture_status.falling_flag == 1)
            {
            printf("捕获到上升沿\r\n");
            capture_status.succeed_flag =1;
            TIM_RESET_CAPTUREPOLARITY(&ic_handle,TIM_CHANNEL_2);                           //清除通道设置  传入两个参数 一个是距离  另外一个是渠道
            TIM_SET_CAPTUREPOLARITY(&ic_handle,TIM_CHANNEL_2,TIM_ICPOLARITY_FALLING);       //设置为下降沿检测等待检测下降沿   变成初始检测状态
            memset(&capture_status,0,sizeof(capture_status));     //让结构体中的所有都置0
            }
            else
            {
            printf("捕获到下降沿\r\n");
            memset(&capture_status,0,sizeof(capture_status));     //让结构体中的所有都置0
            capture_status.falling_flag = 1;
            TIM_RESET_CAPTUREPOLARITY(&ic_handle,TIM_CHANNEL_2);              //清除通道设置  传入两个参数 一个是距离  另外一个是渠道
            TIM_SET_CAPTUREPOLARITY(&ic_handle,TIM_CHANNEL_2,TIM_ICPOLARITY_RISING);       //设置为上升沿检测等待检测上升沿   因为初始检测的是下降沿
            
            }
                
        }
    }

}
*/

void HAL_TIM_IC_CaptureCallback (TIM_HandleTypeDef *htim)
{
   //printf("捕获到下降沿\r\n");
    if(htim->Instance == TIM2)     //回调函数中也有很多定时器  因此要确是否是定时器2
    {
        if(capture_status.succeed_flag == 0)
        {
            if(capture_status.falling_flag == 1)
            {
            printf("捕获到上升沿\r\n");
            capture_status.succeed_flag=1;     //检测是否捕获到一次完整的上升沿和下降沿   
            lastccr=HAL_TIM_ReadCapturedValue(&ic_handle,TIM_CHANNEL_2);            //记录上升沿时 只需记录当前ccr的值   
            TIM_RESET_CAPTUREPOLARITY(&ic_handle,TIM_CHANNEL_2);                           //清除通道设置  传入两个参数 一个是距离  另外一个是渠道
            TIM_SET_CAPTUREPOLARITY(&ic_handle,TIM_CHANNEL_2,TIM_ICPOLARITY_FALLING);       //设置为下降沿检测等待检测下降沿   变成初始检测状态
            //memset(&capture_status,0,sizeof(capture_status));     //让结构体中的所有都置0
            }
            else
            {
            printf("捕获到下降沿\r\n");
            capture_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);        //开启定时器
            }
                
     }
 }
    

}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim)    //专门用于计数溢出中断的回调函数
{
   
    if(htim->Instance == TIM2)
    {
        if(capture_status.falling_flag  == 1)
        {
            capture_status.timout_cnt++;    //每次中断溢出后都会自增1
        }
        
        
    }


}

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

主函数如下

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "ic.h"


int main(void) {
    HAL_Init();
    stm32_clock_init(RCC_PLL_MUL9);  // 设置时钟,72MHz
    led_init();
    uart1_init(115200);  // 初始化 UART
    
    printf("hello world!\r\n");  // 通过 UART 输出 "hello world"
    ic_init(65536-1,72-1);    //可理解为总共需要计数65536个   一次计数需要72/72M的时间  
    while(1) {
        
       pressed_time_get();
       delay_ms(10);
        
//        led1_on();
//        led2_off();
//        delay_ms(500);
//        led1_toggle();
//        led2_toggle();
//        delay_ms(500);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值