• 输入捕获实验


    这个实验的效果是:按住按钮,然后放开,串口会打印按住的时间.

    捕获原理如图。计数器有捕获功能。没有捕获的时候,定时器也可以在工作。设置为上升沿捕获,有上升沿的时候,会触发中断进入中断函数。

    先把定时器清零。然后在捕获期间,定时器会溢出,要计算溢出的次数。同时在中断函数中,已经修改为下降沿捕获了。

    在下降沿捕获的时候,读取当时的计数器的值。这样再加上溢出的次数,就能算出总时间了。

    中断函数的流程图如下:

    函数代码如下:

    
    

    #include "stm32f4xx.h"
    #include "gpio_config.h"
    #include "delay.h"
    #include "usart.h"

    
    

    // GPIO基本配置
    // GPIO的AF映射
    // 中断配置
    // 计时器的基本配置
    // 计时器的捕获配置
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM5_ICInitStructure;
    u8 TIM5CH1_CAPTURE_STA=0;
    u32 TIM5CH1_CAPTURE_VAL;
    int main(void)
    {
    long long temp=0;
    /* Clock Enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); // enable TIM5 clock

    /* UART1 and delay init */
    delay_init();
    uart_init(115200);

    /* GPIO init */
    GPIO_Init(GPIOA,GpioPortAMode);
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //PA0 AF to TIM5

    
    

    /*nvic init */
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;//
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //
    NVIC_Init(&NVIC_InitStructure); //
    TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新和捕获中断

    /* TIM5 init */
    // 定时器的时钟源有4个,最常用的就是内部时钟源CK_INT。经过选择器以后的时钟,叫做CK_PSC.
    //如果选择了CK_INT做时钟源,CK_INT=CK_PSC
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //即fDTS,是CK_INT与数字滤波器之间的分频比,和计数器的计数频率没关系
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
    TIM_TimeBaseStructure.TIM_Period=0XFFFFFFFF; //就是计数溢出值,也是自动重载值
    TIM_TimeBaseStructure.TIM_Prescaler=83; //计数器的预分频,具体的频率为CK_PSC/(TIM_Perscaler+1)
    TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);

    
    

    /* catch init */
    TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CCER寄存器,是通道选择,TIM5有4个通道
    TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
    TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //见通用定时器框图,是TI1/2和IC1/2时间的映射关系
    TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //类似捕获滤波,如高电平捕获,可以设置抓到1个高电平就捕获,还是连续8个高电平才捕获
    TIM5_ICInitStructure.TIM_ICFilter = 0x00;//滤波器采样频率
    TIM_ICInit(TIM5, &TIM5_ICInitStructure); //
    TIM_Cmd(TIM5,ENABLE ); //使能定时器5

    
    
    
    
    

    while(1)
    {

    
    

    delay_nms(300);

    if(TIM5CH1_CAPTURE_STA&0x80)
    {
    temp=TIM5CH1_CAPTURE_STA&0X3F;
    temp=temp*0xFFFFFFFF;
    temp+=TIM5CH1_CAPTURE_VAL;
    printf("HIGH:%lld us ",temp);
    TIM5CH1_CAPTURE_STA=0;
    }


    }

    
    


    }

    //捕获状态 TIM5CH1_CAPTURE_STA的定义
    //[7]:0,没有成功的捕获;1,成功捕获到一次.
    //[6]:0,还没捕获到低电平;1,已经捕获到低电平了.
    //[5:0]:捕获低电平后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:4294秒)

    void TIM5_IRQHandler(void)
    {

    if((TIM5CH1_CAPTURE_STA&0X80)==0)
    {
    if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) //判断是溢出中断
    {
    if(TIM5CH1_CAPTURE_STA==0x40) //是否已经捕获
    {if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F) //是否溢出太多
    {
    TIM5CH1_CAPTURE_STA=0x80; //溢出次数太多,捕获时间太长,算一次成功捕获。
    TIM5CH1_CAPTURE_VAL=0xFFFFFFFF;
    }
    else TIM5CH1_CAPTURE_STA++; //溢出次数没有太多,溢出次数加1
    }
    }

    if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)  //捕获中断
    {
    if(TIM5CH1_CAPTURE_STA==0x40) //是否已经捕获到高电平
    {
    TIM5CH1_CAPTURE_STA|=0x80; //刚才已经捕获到高电平,这次又捕获,说明捕获到低电平了,就是一次成功的捕获了
    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //为下一次捕获做准备
    TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); //读取当前计数器的值
    }
    else  //第一次捕获,说明是高电平捕获
    {TIM5CH1_CAPTURE_STA=0x0; 
    TIM5CH1_CAPTURE_VAL=0x0; //计数器清零
    TIM5CH1_CAPTURE_STA|=0x40;
    TIM_Cmd(TIM5,ENABLE );
    TIM_SetCounter(TIM5,0);
    TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); // 配置为低电平捕获
    TIM_Cmd(TIM5,ENABLE );
    }

    }

    }
    TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);

    }

    
    
    
    
    








    
    
    
    
    
  • 相关阅读:
    Unity3D 中的灯光与渲染
    利用正态分布(高斯分布)绘制噪点图
    Unity3D 调用相机
    Unity3D开发安卓应用如何设置横屏显示和竖屏显示
    Unity3D中Excel表的读取与写入
    Unity3D启动外部程序并传递参数
    Unity动画系统Animator动态添加事件
    Unity3D编辑器扩展(六)——模态窗口
    Unity3D编辑器扩展(五)——常用特性(Attribute)以及Selection类
    Unity3D编辑器扩展(四)——扩展自己的组件
  • 原文地址:https://www.cnblogs.com/nasduc/p/4862405.html
Copyright © 2020-2023  润新知