STM32F407输入捕获

文章目录

  • F407定时器输入捕获实验
    • 支持输入捕获的定时器有哪些
    • 输入捕获工作过程
      • 输入捕获测量高电平脉宽原理
      • 滤波器设置
    • 配置步骤
      • 开启TIM5时钟与端口时钟
      • 配置PA0为用能复用功能(AF2)
      • 初始化端口并开启下拉电阻
      • 初始化TIM5
      • 设置TIM5的输入捕获参数
        • TIM_Channel通道
        • TIM_ICPolarit极性
        • TIM_ICSelection输入捕获映射通道
        • TIM_ICPrescaler输入捕获预分频
        • TIM_ICFilter输入捕获滤波器
      • 代码
      • 中断优先级分组,设置中断优先级
      • 使能捕获和更新中断
      • 编写中断服务函数
      • 使能定时器
      • 获取通道捕获值
    • 捕获代码
      • 定时器5中断代码
      • 主函数代码

F407定时器输入捕获实验

STM32F407输入捕获_第1张图片

支持输入捕获的定时器有哪些

F4开发指南,15.1,P221
在这里插入图片描述

输入捕获工作过程

STM32F407输入捕获_第2张图片

输入捕获测量高电平脉宽原理

F4开发指南,15.1,P221
STM32F407输入捕获_第3张图片
STM32F407输入捕获_第4张图片

滤波器设置

STM32F407输入捕获_第5张图片
Fdts是时钟分频后的时钟频率,可以在定时器中设置。
STM32F407输入捕获_第6张图片

配置步骤

获取TIM5_CH1(P A0)上面的高电平脉冲宽度,并从串口打印捕获结果。

开启TIM5时钟与端口时钟

开启TIM5时钟的方法为:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);   //TIM5时钟使能

配置PA0为用能复用功能(AF2)

配置PA0为复用功能,要设置PA0引脚映射AF2,连接到TIM5上面。方法为:

GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //GPIOF9复用位定时器14 

初始化端口并开启下拉电阻

初始化GPIO的模式为复用功能,同时这里我们还要设置为开启下拉。方法为:

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIOA0 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉 
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化P A0 

初始化TIM5

TIM_TimeBaseStructure.TIM_Prescaler=psc;   //定时器分频 
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 
TIM_TimeBaseStructure.TIM_Period=arr;    //自动重装载值 
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;  
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);//初始化TIM5 

设置TIM5的输入捕获参数

设置TIM5_CCMR1寄存器

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) 

同样,我们来看看参数设置结构体TIM_ICInitTypeDef的定义:

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_Channel通道

#define TIM_Channel_1                      ((uint16_t)0x0000)
#define TIM_Channel_2                      ((uint16_t)0x0004)
#define TIM_Channel_3                      ((uint16_t)0x0008)
#define TIM_Channel_4                      ((uint16_t)0x000C)
                                 
#define IS_TIM_CHANNEL(CHANNEL) (((CHANNEL) == TIM_Channel_1) || \
                                 ((CHANNEL) == TIM_Channel_2) || \
                                 ((CHANNEL) == TIM_Channel_3) || \
                                 ((CHANNEL) == TIM_Channel_4))

TIM_ICPolarit极性

是 用 来 设 置 输 入 信 号 的 有 效 捕 获 极 性 :

#define  TIM_ICPolarity_Rising 上升沿捕获            ((uint16_t)0x0000) 
#define  TIM_ICPolarity_Falling   下降沿捕获         ((uint16_t)0x0002)
#define  TIM_ICPolarity_BothEdge    双沿捕获       ((uint16_t)0x000A)
#define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) || \
                                      ((POLARITY) == TIM_ICPolarity_Falling)|| \
                                      ((POLARITY) == TIM_ICPolarity_BothEdge))

STM32F407输入捕获_第7张图片

TIM_ICSelection输入捕获映射通道

输入捕获映射通道
IC1直接映射在TI1上,选择TIM_ICSelection_DirectTI。
STM32F407输入捕获_第8张图片

#define TIM_ICSelection_DirectTI           ((uint16_t)0x0001) /*!< TIM Input 1, 2, 3 or 4 is selected to be  connected to IC1, IC2, IC3 or IC4, respectively */
#define TIM_ICSelection_IndirectTI         ((uint16_t)0x0002) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to IC2, IC1, IC4 or IC3, respectively. */
#define TIM_ICSelection_TRC                ((uint16_t)0x0003) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */
#define IS_TIM_IC_SELECTION(SELECTION) (((SELECTION) == TIM_ICSelection_DirectTI) || \
                                        ((SELECTION) == TIM_ICSelection_IndirectTI) || \
                                        ((SELECTION) == TIM_ICSelection_TRC))

TIM_ICPrescaler输入捕获预分频

用 来 设 置 输 入 捕 获 分 频 系 数 :
不 分 频 , 所 以 选 中TIM_ICPSC_DIV1,还有2,4,8分频可选。

#define TIM_ICPSC_DIV1                     ((uint16_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input. */
#define TIM_ICPSC_DIV2                     ((uint16_t)0x0004) /*!< Capture performed once every 2 events. */
#define TIM_ICPSC_DIV4                     ((uint16_t)0x0008) /*!< Capture performed once every 4 events. */
#define TIM_ICPSC_DIV8                     ((uint16_t)0x000C) /*!< Capture performed once every 8 events. */
#define IS_TIM_IC_PRESCALER(PRESCALER) (((PRESCALER) == TIM_ICPSC_DIV1) || \
                                        ((PRESCALER) == TIM_ICPSC_DIV2) || \
                                        ((PRESCALER) == TIM_ICPSC_DIV4) || \
                                        ((PRESCALER) == TIM_ICPSC_DIV8))

TIM_ICFilter输入捕获滤波器

设置滤波器长度
取值范围0x00-0x16。

代码

  TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1映射到TI1上 
  TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获 
  TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 
  TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //配置输入分频,不分频  
  TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波 
  TIM_ICInit(TIM5, &TIM5_ICInitStructure); 

中断优先级分组,设置中断优先级

使能捕获和更新中断

设置TIM5的DIER寄存器
使用定时器的开中断函数TIM_ITConfig即可使能捕获和更新中断:

TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断和捕获中断 

编写中断服务函数

if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET){}//判断是否为更新中断 
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET){}//判断是否发生捕获事件 
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);//清除中断和捕获标志位

使能定时器

设置TIM5的CR1寄存器
启动TIM5的计数器,开始输入捕获。

TIM_Cmd(TIM5,ENABLE );  //使能定时器5 

获取通道捕获值

uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx)

捕获代码

要捕获的是高电平信号的脉宽

  • 第一次捕获是上升沿,第二次捕获时下降沿,必须在捕获上升沿之后,设置捕获边沿为下降沿,同时,如果脉宽比较长,那么定时器就会溢出,对溢出必须做处理。

在这里插入图片描述

定时器5中断代码

void TIM5_IRQHandler(void)
{ 		    

 	if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获	
	{
		if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)//溢出,reset=0
		{	     
			if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
			{
				if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了00111111
				{
					TIM5CH1_CAPTURE_STA|=0X80;		//标记成功捕获了一次
					TIM5CH1_CAPTURE_VAL=0XFFFFFFFF;
				}else TIM5CH1_CAPTURE_STA++;
			}	 
		}
		if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
		{	
			if(TIM5CH1_CAPTURE_STA&0X40)		//捕获到一个下降沿 		
			{	  			
				TIM5CH1_CAPTURE_STA|=0X80;		//标记成功捕获到一次高电平脉宽
			  TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);//获取当前的捕获值.
	 			TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
			}else  								//还未开始,第一次捕获上升沿
			{
				TIM5CH1_CAPTURE_STA=0;			//清空
				TIM5CH1_CAPTURE_VAL=0;
				TIM5CH1_CAPTURE_STA|=0X40;		//标记捕获到了上升沿
				TIM_Cmd(TIM5,DISABLE ); 	//关闭定时器5
	 			TIM_SetCounter(TIM5,0);
	 			TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);		//CC1P=1 设置为下降沿捕获
				TIM_Cmd(TIM5,ENABLE ); 	//使能定时器5
			}		    
		}			     	    					   
 	}
	TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}

主函数代码

int main(void)
{ 
	long long temp=0;  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);//初始化串口波特率为115200
	
 	TIM14_PWM_Init(500-1,84-1);       	//84M/84=1Mhz的计数频率计数到500,PWM频率为1M/500=2Khz     
 	TIM5_CH1_Cap_Init(0XFFFFFFFF,84-1); //以1Mhz的频率计数 。把ARR设置到了最大值。分频到1M
   	while(1)
	{
 		delay_ms(10);	 
 		if(TIM5CH1_CAPTURE_STA&0X80)        //成功捕获到了一次高电平
		{
			temp=TIM5CH1_CAPTURE_STA&0X3F; 
			temp*=0XFFFFFFFF;		 		         //溢出时间总和。每次溢出的次数就是0xFFFFFFFF,有temp次
			temp+=TIM5CH1_CAPTURE_VAL;		   //得到总的高电平时间
			printf("HIGH:%lld us\r\n",temp); //打印总的高点平时间
			TIM5CH1_CAPTURE_STA=0;			     //开启下一次捕获
		}
	}
}

STM32F407输入捕获_第9张图片

你可能感兴趣的:(嵌入式开发,stm32,单片机,嵌入式硬件)