输入捕获简介:
STM32F4除了基本定时器TIM6和TIM7,其他定时器都具有输入捕获功能。输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,通常用于测量输入信号的脉宽、测量 PWM 输入信号的频率及占空比。输入捕获的工作原理比较简单,在输入捕获模式下,当相应的 ICx 信号检测到跳变沿后,将使用捕获/比较寄存器(TIMx_CCRx)来锁存计数器的值。简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。

最开始设置的捕获极性如果是上升沿的话,当捕获到上升沿的时候将计数器cnt置0,计数器开始计数,再设置捕获为下降沿捕获,当捕获到下降沿的时候将cnt的值给CCRx2中,在整个高电平的过程中cnt会产生溢出,溢出后又从0开始计数,所以需要几率溢出次数。
CNT计数的次数等于:N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间。
输入捕获配置步骤:
(1)使能定时器及端口时钟,并设置引脚复用器映射和引脚模式等

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式


(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等

voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

(3)设置通用定时器的输入捕获参数,开启输入捕获功能

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef*
TIM_ICInitStruct);
typedef struct
{uint16_t TIM_Channel; //通道uint16_t TIM_ICPolarity; //捕获极性uint16_t TIM_ICSelection;//映射uint16_t TIM_ICPrescaler;//分频系数uint16_t TIM_ICFilter; //滤波器长度
} TIM_ICInitTypeDef;
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);

(4)开启捕获和定时器溢出(更新)中断

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);

(5)设置定时器中断优先级,使能定时器中断通道
NVIC初始化库函数是NVIC_Init()

(6)编写定时器中断服务函数

TIM5_IRQHandler
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
TIM_SetCounter(TIM5,0); //定时器初值为0

(7)使能定时器

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

使用TIM5的CH1检测输入信号高电平脉宽,将检测的高电平脉宽时间通过printf函数打印出来,同时让D1指示灯不
断闪烁表示系统正常运行。由于TIM5的CH1与KEY_UP共用一个管脚,所以可以使用KEY_UP来产生输入信号。

input.c

#include "input.h"u8 TIM5_CH1_CAPTURE_STA=0; //输入捕获的状态  在源文件中声明过的全局变量
u32 TIM5_CH1_CAPTURE_VAL=0;//输入捕获值(TIM2/TIM5是32位)void TIM5_CH1_Input_Init(u32 arr,u16 psc)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定时器参数结构体TIM_ICInitTypeDef TIM_ICInitStructure;//输入捕获结构体NVIC_InitTypeDef NVIC_InitStructure;//NVIC初始化结构体GPIO_InitTypeDef GPIO_InitStructure;//端口结构体RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能端口A时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能TIM5时钟GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);//管脚复用,将PA0映射到TIM5上//初始化PA0端口GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//管脚设置GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100MGPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化结构体//初始化定时器参数TIM_TimeBaseInitStructure.TIM_Period=arr;   //自动装载值,定时器5是32位的注意形参大小TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;  //时钟分割,时钟分频 通常不需要修改TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);    //初始化定时器5//设置通用定时器的输入捕获参数,开启输入捕获功能TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; PA0是定时器5通道1TIM_ICInitStructure.TIM_ICFilter=0x00;  //不使用,直接设置成0TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//设置为上升沿捕获TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //不分频,设置成1分频TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1TIM_ICInit(TIM5,&TIM_ICInitStructure);//初始化输入捕获结构体//配置溢出中断TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//开启更新和通道1捕获中断//配置中断通道NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;//中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;      //子优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //IRQ通道使能NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化VIC寄存器TIM_Cmd(TIM5,ENABLE); //使能定时器
}//中断服务函数
void TIM5_IRQHandler(void)
{if((TIM5_CH1_CAPTURE_STA&0x80)==0) //最高位代表上升沿捕获完成,但是最开始肯定没有上升沿,所以为0{if(TIM_GetITStatus(TIM5,TIM_IT_Update)) //读取更新中断状态标志,读取溢出次数{if(TIM5_CH1_CAPTURE_STA&0X40)//捕获到了高电平{if((TIM5_CH1_CAPTURE_STA&0x3f)==0x3f) //高电平时间太长,说明后6位全部为1,累计到最大值{TIM5_CH1_CAPTURE_STA|=0x80; //标志一次捕获成功,时间过长强制让其捕获完成TIM5_CH1_CAPTURE_VAL=0xffffffff;}else{TIM5_CH1_CAPTURE_STA++;//没有累计到最大值,让其累加1}}}if(TIM_GetITStatus(TIM5,TIM_IT_CC1)) //发生捕获中断{if(TIM5_CH1_CAPTURE_STA&0X40)//捕获到了低电平,//次高位为表示已经捕获{TIM5_CH1_CAPTURE_STA|=0x80; //成功捕获一次高电平TIM5_CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);  //读取通道1ccrx的值TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置上升沿捕获,//最开始肯定没有被捕获TIM5_CH1_CAPTURE_STA次高位肯定为0,进入else,进入上升沿捕获}else{TIM5_CH1_CAPTURE_STA=0;//置0防止干扰TIM5_CH1_CAPTURE_VAL=0;TIM5_CH1_CAPTURE_STA|=0x40; //捕获到高电平 标志   //设置次高位为1,让其为已经捕获的状态TIM_Cmd(TIM5,DISABLE);    //关闭定时器TIM_SetCounter(TIM5,0); //定时器初值置0TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置下降沿捕获TIM_Cmd(TIM5,ENABLE);   //开启定时器}}}TIM_ClearITPendingBit(TIM5,TIM_IT_CC1|TIM_IT_Update);//清空中断标志位
}

input.h

#ifndef __input_H
#define __input_H#include "system.h"extern u8 TIM5_CH1_CAPTURE_STA;//保存输入捕获状态的标志,最高是否捕获成功,次高位是否捕获到上升沿,低六位累计溢出次数
extern u32 TIM5_CH1_CAPTURE_VAL; //保存输入捕获的值CCRxvoid TIM5_CH1_Input_Init(u32 arr,u16 psc);
void TIM5IRQHandler(void);#endif

main

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "input.h"int main()
{u8 i=0;long long indata=0;SysTick_Init(168);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组LED_Init();USART1_Init(9600);TIM5_CH1_Input_Init(0xffffffff,83);  //以1M频率计数while(1){if(TIM5_CH1_CAPTURE_STA&0x80) //成功捕获{indata=TIM5_CH1_CAPTURE_STA&0x3f;indata*=0xffffffff; //溢出次数乘以一次的计数次数时间 usindata+=TIM5_CH1_CAPTURE_VAL;//加上高电平捕获的时间printf("高电平持续时间:%lld us\r\n",indata); //总的高电平时间TIM5_CH1_CAPTURE_STA=0; //开始下一次捕获}i++;if(i%20==0){led1=!led1;}myDelay_ms(10);}
}

STM32——输入捕获相关推荐

  1. STM32输入捕获模式设置并用DMA接收数据

    参考: STM32的PWM输入模式设置并用DMA接收数据 Input capture mode The input stage samples the corresponding TIx input ...

  2. stm32 输入捕获 测量脉宽

    选用通用定时器TIM5的CH1. PA0接一个按键,默认接GND,当按键按下时,IO口被拉高,此时,可利用定时器的输入捕获功能,测量按键按下的这段高电平的时间. 宏定义方便程序升级.移植,举个例子: ...

  3. STM32 输入捕获 测量频率 PWM占空比

    看了网上关于STM32输入捕获的资料,有几篇介绍的很不错,但是内容上还有一点问题,稍加修改,大家可以参考一下. 重要概念理解(对于理解输入捕获功能很重要,特别看了数据手册CCR1\CCR2\CCR3\ ...

  4. STM32输入捕获实验

    STM32 输入捕获工作过程(通道1为例) 通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TI ...

  5. STM32输入捕获测试频率和正负脉宽

    @STM32输入捕获测试频率和正负脉宽 本博客相关程序调用转载正点原子 正点原子@ALIENTEK 广州市星翼电子科技有限公司 这次做的主要是测试频率,但系,也趁此机会捕获了高低脉宽的时间,题目所说的 ...

  6. stm32 输入捕获学习(二)

    (本文参考STM32  开发指南 V1.3   -- ALIENTEK 战舰 STM32 开发板库函数教程 ) 1. 实验设计 我们用 TIM5 的通道 1(PA0)来做输入捕获,捕获 PA0 上高电 ...

  7. stm32 输入捕获学习(一)

    输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.STM32 的输入捕获,简单地说就是通过检测 TIMx_CHx 上的边沿信 ...

  8. STM32 输入捕获功能

    目录 01.STM32捕获功能 02.输入捕获过程 03.代码配置 本文将介绍通过STM32的定时器输入捕获,如果对定时器不太熟悉的同学可以看下之前的文章<STM32基础定时器详解>,关于 ...

  9. STM32 输入捕获测量脉冲周期/频率

    STM32捕获模式连续测量脉冲周期/频率,使用类似中断的方式,使用STM32内部的硬件滤波器,脉冲周期量程很大(固定时间脉冲计数的方式,量程有限). 硬件: STM32F103R8T6  TIM2  ...

  10. STM32 输入捕获的脉冲宽度及频率计算

    输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...

最新文章

  1. SSM(springMVC-spring-mybatis)环境搭建-01-建立Maven-web项目
  2. SQL on Linux Run on Docker
  3. POJ 3264: Balanced Lineup
  4. MongoDB实战(4)MapReduce
  5. 数人云CEO王璞:容器正成为软件交付的标准
  6. 【Matlab 控制】利用 XY Graph 画图
  7. android 7.0 更新apk,Android更新apk兼容7.0和8.0
  8. Spring Cloud微服务之子模块的创建(二)
  9. 核心控制芯片选型建议书(中低端)
  10. 反射 数据类型_这是一份超全面详细的Java反射机制学习指南
  11. 错误:找不到或无法加载主类
  12. hp laserjet 1213 linux驱动下载,惠普HP LaserJet Pro M1213nf 一体机驱动
  13. 模型预测控制(MPC)简介
  14. si4463如何读取RSSI
  15. 关于XDR的这些问题你都了解吗?
  16. 【大数据技术详解】搭建redis集群服务的步骤和配置以及解决创建集群时会遇到的错误:NodeX replied with error:ERRInvalid node address specified
  17. springboot @Value取不到值
  18. 入门必学的sql语句
  19. 在阿里云购买云服务器并安装宝塔面板
  20. Java--进制转换(一)

热门文章

  1. Ubuntu20.04外接显示器
  2. 【回归预测】基于TPA-LSTM(时间注意力注意力机制长短期记忆神经网络)实现数据多输入单输出回归预测附matlab代码
  3. SpringMVC静态资源配置
  4. 基于Xilinx artix 7的FPGA高级应用(二):千兆以太网通信(原理篇)
  5. 论文投稿指南——SCI投稿各阶段邮件模板
  6. DeepMind新AI可生成逼真视频
  7. C语言 —— pta寻找孪生素数 (20 分)
  8. 何鸿略加入华为消费者业务 任大中华区副总裁
  9. 你的孤独,虽败犹荣——读书笔记
  10. 基于CNN的象棋棋子识别