最近毕业设计又需要实现一个小功能,使用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不断变化,说明捕获成功