stm32f4 PWM捕获 (上升沿/下降沿/高低电平时间)详解(含代码)

最近毕业设计又需要实现一个小功能,使用PWM捕获到一个信号的上升沿,并在这个信号的上升沿进行一些操作

一开始我有尝试过读取管脚的高低电平,但是由于这个信号的速度过快,高低电平是读取不到的,只能采用PWM捕获的方式,其实也比较好操作!

与以往需要两个通道来进行PWM捕获不同,这个代码只需要一个通道就可以实现

首先依然是PWM捕获的配置,代码如下:

TIM_ICInitTypeDef  TIM5_ICInitStructure;


void TIM5_CH2_Cap_Init(u32 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_ICInitTypeDef  TIM5_ICInitStructure;

	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);  	   
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 		
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //修改IO口
	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(GPIOA,&GPIO_InitStructure); 

	GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_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_ICInitStructure.TIM_Channel = TIM_Channel_2;  //修改通道
  TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	
  TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
  TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV2;	
  TIM5_ICInitStructure.TIM_ICFilter = 0x00;
  TIM_ICInit(TIM5, &TIM5_ICInitStructure);
		
	TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC2,ENABLE);	//通道对应着CC几
	
  TIM_Cmd(TIM5,ENABLE ); 	
 
  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);	
	
	
}


u32  TIM5CH2_CAPTURE_STA=0;			    				
u32	TIM5CH2_CAPTURE_VAL;
 

void TIM5_IRQHandler(void)
{ 		    
 	if((TIM5CH2_CAPTURE_STA&0X80)==0)	
	{
		if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)	
		{	     
			if(TIM5CH2_CAPTURE_STA&0X40)					
			{
				if((TIM5CH2_CAPTURE_STA&0X3F)==0X3F)
				{
					TIM5CH2_CAPTURE_STA|=0X80;				
					TIM5CH2_CAPTURE_VAL=0XFFFFFFFF;
				}
				else
					TIM5CH2_CAPTURE_STA++;
			}	 
		}
		if(TIM_GetITStatus(TIM5, TIM_IT_CC2) != RESET)
		{	
			if(TIM5CH2_CAPTURE_STA&0X40)				
			{	  			
				TIM5CH2_CAPTURE_STA|=0X80;				
			    TIM5CH2_CAPTURE_VAL=TIM_GetCapture2(TIM5);//修改通道	
	 			TIM_Cmd(TIM5,DISABLE ); 					
			    TIM_SetCounter(TIM5,0);						
			}else  													
			{
				TIM5CH2_CAPTURE_STA=0;				
				TIM5CH2_CAPTURE_VAL=0;
				TIM5CH2_CAPTURE_STA|=0X40;		
				TIM_Cmd(TIM5,ENABLE ); 
			}		    
		}			     	    					   
 	}
	TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); 
}

比较需要注意的是,除了基本的IO口修改,PWM捕获一共4个通道,还需要根据使用的IO口定义自己的通道,我这里用的是TIM5的2通道,对应着stm32f4的话是PA1

配置完成之后,TIM5CH2_CAPTURE_STA==0x40的时候,就是上升沿的时刻了

如果想要捕获下降沿,配置的时候TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  就修改成下降沿

这里还需要注意的一点是,STA和VAL都需要定义成extern

extern u32  TIM5CH2_CAPTURE_STA;			    				
extern u32	TIM5CH2_CAPTURE_VAL;	

在main里面,配置PWM捕获的速度

int main(void)
{ 
	
			TIM5_CH2_Cap_Init(0XFFFFFFFF,84-1);  //1M

	while(1)
	{ 
		
		if(TIM5CH2_CAPTURE_STA&0X80)        
		{
			temp=TIM5CH2_CAPTURE_STA&0X3F; 
			temp*=0XFFFFFFFF;		 		         
			temp+=TIM5CH2_CAPTURE_VAL;				
			

			TIM5CH2_CAPTURE_STA=0;			     
		}
    }
}

如果想要获取PWM的高低电平时间,就需要定义temp,在这里temp是高电平的时间,如果想要获取低电平时间,前面配置成获取低电平就行了

之后,我们将进行PWM捕获的管脚(这里是PA1),连接到需要进行PWM捕获的信号管脚上(而不是用输出信号的管脚直接去PWM捕获)。我只需要获取高电平,在debug里面,我们可以看到STA会0x40--0x00不断变化,说明捕获成功

  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
STM32上使用PWM时,可以使用定时器来生成PWM信号。定时器有两种工作模式:输入捕获和输出比较。其中,输出比较模式可以用来生成PWM信号。在输出比较模式下,可以通过读取定时器的寄存器的值来获取PWM的占空比和周期。具体的代码如下: ```c // 配置定时器 TIM_HandleTypeDef htim; TIM_OC_InitTypeDef sConfigOC; htim.Instance = TIM1; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 999; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 占空比为50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); // 读取PWM占空比和周期 uint32_t pulse = HAL_TIM_ReadCapturedValue(&htim, TIM_CHANNEL_1); uint32_t period = __HAL_TIM_GET_AUTORELOAD(&htim); ``` 在上面的代码中,我们使用了TIM1定时器和其中的通道1来生成PWM信号。先使用HAL_TIM_PWM_Init函数对定时器进行初始化,然后使用HAL_TIM_PWM_ConfigChannel函数对通道进行配置,最后使用HAL_TIM_PWM_Start函数启动PWM信号的输出。 获取PWM信号的占空比和周期,我们使用了HAL_TIM_ReadCapturedValue和\_\_HAL_TIM_GET\_AUTORELOAD函数。其中,HAL\_TIM\_ReadCapturedValue函数可以读取定时器的寄存器的值,从而获取PWM信号的电平时间,\_\_HAL\_TIM\_GET\_AUTORELOAD函数可以获取定时器的自动重载值,从而获取PWM信号的周期。 需要注意的是,以上代码仅供参考,实际应用中需要根据具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值