STM32——输入捕获

输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6、TIM7,其他的定时器都有输入捕获的功能。应用场景是编码器。

测量频率

当捕获通道TIx 上出现上升沿时,发生第一次捕获,计数器CNT 的值会被锁存到捕获寄存器CCR 中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并 把捕获寄存器中的值读取到value1 中。

当出现第二次上升沿时,发生第二次捕获,计数器CNT 的值会再次被锁存到捕获寄存器CCR 中,并再次进入捕获中断,在捕获中断中,把捕获寄存器 的值读取到value3 中,并清除捕获记录标志。利用value3 和value1 的差值我们就可以算出信号的 周期(频率)。

测量脉宽

当捕获通道TIx 上出现上升沿时,发生第一次捕获,计数器CNT 的值会被锁存到捕获寄存器CCR 中,而且还会进入捕获中断,在中断服务程序中记录一次捕获(可以用一个标志变量来记录),并 把捕获寄存器中的值读取到value1 中。

然后把捕获边沿改变为下降沿捕获,目的是捕获后面的 下降沿。当下降沿到来的时候,发生第二次捕获,计数器CNT 的值会再次被锁存到捕获寄存器 CCR 中,并再次进入捕获中断,在捕获中断中,把捕获寄存器的值读取到value2,利用value2-value1的差值即可算出脉冲宽度。

PWM输入模式

由上述我们知道,输入捕获模式,不仅可以单独测量脉宽,还可以单独测量频率,那么是否可以同时测量脉宽和频率呢?(这种也是最常用的方式),答案是肯定可以,只不过需要占用两个捕获寄存器(单独测量脉宽和频率只需要一个)

具体过程:

1.信号由输入通道TI1 进入,信号会被分为两路,一路是 TI1FP1,另外一路是TI2FP2。其中一路是周期,另一路是占空比。(作为触发输入的那一路信号对应的就是 周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置极性,是上升沿还是下降 沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配置为相反的极性捕获,无需软件 配置。一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可

2.将从模式控制器配置为复位模式(配置寄存器SMCR 的位 SMS[2:0] 来实现),即当我们启动触发信号开始进行捕获的时候,同时把计数器CNT 复位清零。

3.以下图为例:

PWM 信号由输入通道TI1 进入,配置TI1FP1 为触发信号,上升沿捕获。当上升沿的时候IC1 和 IC2 同时捕获,计数器CNT 清零。

到了下降沿的时候,IC2 捕获,此时计数器CNT 的值被锁存 到捕获寄存器CCR2 中,到了下一个上升沿的时候,IC1 捕获,计数器CNT 的值被锁存到捕获寄 存器CCR1 中。

可知CCR2 测量的是脉宽,CCR1 测量的是周期。

应用:

  • 电机控制

输入捕获功能可用于监测电机的霍尔传感器反馈或者反电动势(back electromotive force, BEMF),从而确定电机的转子位置和速度,以便进行适时的换相,实现电机的高效控制。

  • 实时监控和反馈控制

位置监测与控制:通过捕获传感器反馈信号,可以实时监测设备或系统的位置,并提供精确的反馈控制,如自动化生产线、机器人操作等。

速度闭环控制:捕获速度反馈信号,用于实现速度闭环控制系统,如电梯速度控制、风扇转速控制等。

  • 串口通信同步(底层原理)

在串口通信中,数据的传输需要严格的同步,以确保发送端和接收端能够正确地识别和解析数据。输入捕获功能可以用于同步接收端的数据接收时钟,从而实现可靠的串口通信。

发送端:发送端根据通信协议的波特率(Baud Rate)产生一个连续的数据流,并将其转换成电平信号发送。波特率定义了每秒钟传输的比特数,因此发送端的时钟需要与波特率相匹配。

接收端:接收端使用输入捕获功能来捕获串口接收线上的数据边沿,通常是起始位(Start Bit)的边沿。通过捕获起始位的边沿,接收端可以确定数据的到达时间,并据此同步接收时钟。

同步原理:接收端根据捕获的起始位边沿和预设的波特率来生成一个本地时钟,该本地时钟与发送端的时钟同步。当本地时钟与发送端的时钟同步时,接收端就能够精确地在每个数据位的中间捕获数据,并正确地解析数据。

代码

cs 复制代码
#include "public.h"

void TIMx_Capture_Config(void)
{ 
	TIMx_GPIO_Config();
	TIMx_NVIC_Config();

	//配置TIM8时基
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	//APB2 84Mhz  TIM8=168Mhz
	TIM_TimeBaseStructure.TIM_Period= 50000;  //ARR计数最大值  输入捕获有什么影响?
	TIM_TimeBaseStructure.TIM_Prescaler= 168-1;//PSC分频系数
	/*
		168Mhz/168=1Mhz 数一个数:1/1000000 s  1/1Mhz =  168/168M x
	*/
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
	
	//输入捕获配置
	
	TIM_ICInitTypeDef  TIM_ICInitStructure;
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;  //输入捕获通道选择
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	//???
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//设置捕获通道的信号直连和非直连
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//1分频,即捕获信号的每个有效边沿都捕获
	TIM_ICInitStructure.TIM_ICFilter = 0x0;//滤波,经历几个周期跳变,认为波形稳定。

	TIM_PWMIConfig(TIM8, &TIM_ICInitStructure);


	/* Select the TIM8 Input Trigger: TI1FP1 */
	TIM_SelectInputTrigger(TIM8, TIM_TS_TI1FP1);
	
	TIM_SelectSlaveMode(TIM8, TIM_SlaveMode_Reset);
	TIM_SelectMasterSlaveMode(TIM8,TIM_MasterSlaveMode_Enable);
	
	TIM_Cmd(TIM8, ENABLE);
	
	TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);
	TIM_ITConfig(TIM8, TIM_IT_CC1, ENABLE);
}

static void TIMx_GPIO_Config(void)
{
	//1.TIM8 PC6 配置成输入捕获通道
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/* TIM4 clock enable */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
	/* GPIOB clock enable */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
	
	/* TIM8 chenne1 configuration : PC.6 */
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	/* Connect PC.6 pin to TIM8 */
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8);
}

static void TIMx_NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
cs 复制代码
__IO uint16_t IC1Value=0; //TIM8 IC1的值
__IO uint16_t IC2Value=0; //TIM8 IC2的值

__IO float DutyCycle=0;   //脉宽,占空比
__IO float Frequency=0;   //频率

void TIM8_CC_IRQHandler(void)
{
	
	if (TIM_GetITStatus(TIM8, TIM_IT_CC1) == SET)
	{
		TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);
		/* 获取输入捕获的值*/
		IC1Value = TIM_GetCapture1(TIM8);
		IC2Value = TIM_GetCapture2(TIM8);
		
		if(IC1Value!=0)
		{
			//占空比
			DutyCycle=(float)(IC2Value+1)/(IC1Value+1)*100;			
			//频率
			Frequency= (168000000/168)/(float)IC1Value;				
		}
		else
		{
			//周期和脉宽为0
			DutyCycle=0;
			Frequency=0;
		}		
	}
cs 复制代码
#include "public.h"
int main(void)
{
	//2号分组:2bit给抢占  2bit给响应   0-3  0-3 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
	SysTick_Init();
	
	//1.初始化定时器TIM4的通道引脚
	TIMx_GPIO_Init();
	
	//2.定时器TIM4初始化
	TIMx_PWM_Config();
	
	//修改CCR比较值,调节不同的占空比
	//TIM_SetCompare1(TIM4,1000-1);
	
	uint16_t Compare1=1;
	uint16_t flag = 1;
	
	while(1)
	{
		
		Delay_ms(2);
		
		if(flag)
			Compare1+=10;
		else 
			Compare1-=10;
		
		if(Compare1>2000-1)
			flag=0;
		if(Compare1<=10)
			flag=1;

		TIM_SetCompare1(TIM14,Compare1);
		
	}	
}
相关推荐
redcocal1 小时前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
思为无线NiceRF4 小时前
全双工多路并发、低延时数传解决行业信号拥堵问题
物联网
辰哥单片机设计5 小时前
门磁模块详解(防盗感应开关 STM32)
stm32·单片机·嵌入式硬件·传感器
夜间去看海5 小时前
基于51单片机的自动清洗系统(自动洗衣机)
嵌入式硬件·51单片机·proteus·洗衣机
yrx0203075 小时前
stm32 IIC总线busy解决方法
stm32·单片机·嵌入式硬件
YHPsophie7 小时前
ATGM331C-5T杭州中科微BDS/GNSS全星座定位授时模块应用领域
经验分享·笔记·单片机·信息与通信·交通物流
Archie_IT8 小时前
【STM32系统】基于STM32设计的SD卡数据读取与上位机显示系统(SDIO接口驱动、雷龙SD卡)——文末资料下载
arm开发·stm32·单片机·嵌入式硬件
辰哥单片机设计8 小时前
1×4矩阵键盘详解(STM32)
stm32·单片机·嵌入式硬件·矩阵·传感器
wmkswd8 小时前
CAN总线-STM32上CAN外设
stm32·单片机·嵌入式硬件