太不科学了!!!为什么这个程序是对的?!!一个输入捕获程序,大神们来围观下!

2019-07-21 03:01发布

我写了一段输入捕获程序,是从PB1输出一个周期20ms,高电平6ms的PWM波;由PA0捕获,再把捕获到的波原样从PF9输出,程序代码如下:

#include "sys.h"
#include "delay.h"

#define PWM3_WIDTH TIM3->CCR4
#define PWM14_WIDTH TIM14->CCR1
u32 TIM5_CH1_Cap_Value;

void TIM3_PWM_Init(u16 arr,u16 psc)
{
    RCC->APB1ENR|=1<<1;
RCC->AHB1ENR|=1<<1;
GPIO_Set(GPIOB,PIN1,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);
GPIO_AF_Set(GPIOB,1,2);

TIM3->ARR=arr;
TIM3->SC=psc;

TIM3->CCMR2|=7<<12;
TIM3->CCMR2|=1<<11;
TIM3->CCER|=1<<12;
TIM3->CCER|=1<<13;
TIM3->CR1|=1<<7;
TIM3->CR1|=1<<4;
TIM3->CR1|=1<<0;
}
void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{  
RCC->APB1ENR|=1<<3;
RCC->AHB1ENR|=1<<0;
GPIO_Set(GPIOA,PIN0,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);
GPIO_AF_Set(GPIOA,0,2);
 
  TIM5->ARR=arr;    
TIM5->SC=psc;  

TIM5->CCMR1|=1<<0;
  TIM5->CCMR1|=0<<2;
  TIM5->CCMR1|=0<<4;

TIM5->CCER|=1<<0;
TIM5->CCER|=0<<1;

TIM5->EGR=1<<0;
TIM5->DIER|=1<<0;  
TIM5->DIER|=1<<1;  
TIM5->CR1|=0x01;

MY_NVIC_Init(2,0,TIM5_IRQn,2);
}

void TIM14_PWM_Init(u16 arr,u16 psc)
{   
RCC->APB1ENR|=1<<8;
RCC->AHB1ENR|=1<<5;
GPIO_Set(GPIOF,PIN9,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);
GPIO_AF_Set(GPIOF,9,9);
TIM14->ARR=arr;
TIM14->SC=psc;
TIM14->CCMR1|=6<<4;
TIM14->CCMR1|=1<<3;
TIM14->CCER|=1<<0;
TIM14->CCER|=1<<1;
TIM14->CR1|=1<<7;
TIM14->CR1|=1<<0;      
}
/*
u32 PWM3(u16 mode)
{   
u8 static flag3;
u16 static pwm3_variable=2000;
if(pwm3_variable==2000)
flag3=0;
if(pwm3_variable>10000)
flag3=1;
if(flag3==0)
pwm3_variable++;
else
pwm3_variable--;
return pwm3_variable;     
}*/

void TIM5_IRQHandler(void)
{
    u16 tim5sr;
tim5sr=TIM5->SR;

if(tim5sr&0x02)
   TIM5_CH1_Cap_Value=TIM5->CCR1;

TIM5->SR=0;
}

int main()
{
    Stm32_Clock_Init(336,8,2,7);
delay_init(168);

TIM3_PWM_Init(20000-1,84-1);
TIM5_CH1_Cap_Init(20000-1,84-1);
TIM14_PWM_Init(20000-1,84-1);
while(1)
{
PWM3_WIDTH=6000;
   WM14_WIDTH=TIM5_CH1_Cap_Value;
}
}


亲们有示波器可以copy试试,用杜邦线把PB1输给PA0,然后看PB1和PF9的输出波形一样不一样。完全没问题!

但是!!!这特喵的是不科学的啊!!!亲们!!因为你们看这一段:
void TIM5_IRQHandler(void)
{
    u16 tim5sr;
tim5sr=TIM5->SR;

if(tim5sr&0x02)
   TIM5_CH1_Cap_Value=TIM5->CCR1;

TIM5->SR=0;
}
我明明把捕获下降沿的语句给删掉了啊!!现在按理说,只有初始化的时候我设置了上升沿捕获,然后就直接读CCR1了!!这时候明明输入的PWM才刚刚开始,负责捕捉的TIM5->CCR1里应该什么都没有才对啊!!为什么就成功读出来了?

简直不科学,大神们说说为什么啊?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
kittyhoney
1楼-- · 2019-07-21 04:48
我的理解是,当输入捕获开始后,每发生一次捕获,那么CCR1的值就会+1

也就是说,在这个程序里,设置了上升沿捕获,然后触发了,马上就读CCR1的值,这时候CCR1的值其实是0。

但是由于我并没有把各寄存器清零,所以虽然第一次捕获已经读了一个0,第一个捕获周期已经读完了,但这第一个周期的持续高电平却在让CCR1++。

那么,到了第二个周期上升沿刚一来,除了发读CCR1的命令,这时候读出来的正好是上个周期的高电平值。然后输出出来,虽然看起来没问题,但其实测出的PWM刚好是上个周期的值。

亲们,我这样理解对吗?

这个程序能够成功,核心原因是输入的PWM和捕获的周期都是20ms,一模一样分毫不差,所以不读下降沿并计算脉宽也不要紧。但如果输入的周期与捕获周期有误差,那么读出来就不对…………我猜…………
lycreturn
2楼-- · 2019-07-21 09:48
 精彩回答 2  元偷偷看……

一周热门 更多>