硬件:德飞莱STM32F407
功能:TIM4_CH1->PB6输出PWM,TIM3_CH1->PC6捕获高电平时间
#include "timer.h"
void TIM4_PWM_Init(void)
{
RCC->APB1ENR|=1<<2; //打开定时器4时钟
RCC->AHB1ENR|=1<<1; //打开GPIOB的时钟
GPIOB->MODER|=2<<12; //PB6 复用模式
GPIOB->OTYPER&=~(1<<6); //PB6 推挽输出
GPIOB->OSPEEDR|=11<<12; //PB6 输出速度100M
GPIOB->PUPDR|=1<<6; //PB6 上拉
GPIOB->AFR[0]|=2<<24; //PB6 AF2
TIM4->ARR=500-1;
TIM4->PSC=84-1; //频率为2K
TIM4->CCR1=250; //高电平时间为500-250 占空比为(500-250)/500=50%
TIM4->CCMR1&=~(3<<0); //配置为输出
TIM4->CCMR1|=1<<2; //输出比较快速使能
TIM4->CCMR1|=1<<3; //输出比较预装载使能
TIM4->CCMR1|=7<<4; //PWM2模式
TIM4->CCER|=1<<0; //输出使能,在相应输出引脚上输出 OC1 信号
TIM4->CCER|=1<<1; //低电平有效
TIM4->CR1|=1<<7; //自动重装载预装载使能
TIM4->CR1|=1<<0; //打开定时器4
}
void TIM3_Cap_Init(void)//TIM3_CH1定时器获取
{
RCC->APB1ENR|=1<<1; //打开定时器3时钟
RCC->AHB1ENR|=1<<2; //打开GPIOC的时钟
GPIOC->MODER|=(2<<12); //PC6 输入模式
GPIOC->PUPDR|=2<<6; //PC6 下拉
GPIOC->AFR[0]|=2<<24; //PC6 AF2
TIM3->ARR=0xFFFFFFFF; //计数周期设置为最大,计数周期65536
TIM3->PSC=72-1; //计数频率1M,每隔1us捕获一次
TIM3->CCMR1|=1<<0; //配置为输入,映射到T1上
TIM3->CCMR1&=~(3<<2); //不分频
TIM3->CCMR1&=~(15<<4); //不滤波
TIM3->CCER|=1<<0; //使能捕获
TIM3->CCER&=~(3<<1); //上升沿捕获
TIM3->DIER|=1<<0; //允许更新中断
TIM3->DIER|=1<<1; //使能通道1捕获中断
TIM3->CR1|=1<<0; //使能计数器
MY_NVIC_Init(2,1,TIM3_IRQn,2);//抢占2,子优先级1,组2
}
u8 TIM3_IRQ_STA=0;
u32 TIM3_IRQ_VAL=0;
void TIM3_IRQHandler(void)
{
u16 sr;
sr=TIM3->SR;
if(!(TIM3_IRQ_STA&0x80)) //未捕获完成
{
if(sr&0x01) //产生更新中断,上升沿时间超过一个计数周期65536us,记录超过了几次
{
if(TIM3_IRQ_STA&0X40) //已经捕获到高电平了
{
if((TIM3_IRQ_STA&0X3F)==0X3F)//高电平太长了
{
TIM3_IRQ_STA|=0X80; //高电平时间过长,强制标记成功捕获了一次
TIM3_IRQ_VAL=0XFFFFFFFF;
}else TIM3_IRQ_STA++;
}
}
if(sr&0x02) //产生捕获中断
{
if(TIM3_IRQ_STA&0x40) //此时状态为,已经捕获到上升沿,定时器设置为下降沿捕获,且进入中断,也即是捕获到上升沿之后又捕获到下降沿
{
//标记捕获完成一次
TIM3_IRQ_STA|=0x80; //标记完成一次捕获
TIM3_IRQ_VAL=TIM3->CCR1;
TIM3->CCER&=~(1<<1); //配置为上升沿捕获,开始新的一轮捕获
}
else //此时进来肯定是只捕获到上升沿,开始计数上升沿时间
{
TIM3_IRQ_STA=0; //清空状态寄存器
TIM3_IRQ_VAL=0; //清空计数
TIM3_IRQ_STA|=0x40; //标记捕获到上升沿
TIM3->CR1&=~(1<<0); //关闭定时器,配置捕获的边缘信号
TIM3->CNT=0; //清空计数器
TIM3->CCER|=1<<1; //配置为下降沿捕获
TIM3->CR1|=1<<0; //开启定时器
}
}
}
TIM3->SR=0; //清除中断标志位
}
/*main.c*/
extern u8 TIM3_IRQ_STA; //输入捕获状态
extern u32 TIM3_IRQ_VAL; //输入捕获值
while(1)
{
if(TIM3_IRQ_STA&0X80)//成功捕获到了一次高电平
{
temp=TIM3_IRQ_STA&0X3F;
temp*=0XFFFFFFFF; //溢出时间总和
temp+=TIM3_IRQ_VAL; //得到总的高电平时间
printf("HIGH >> :%lld us
",temp);//打印总的高点平时间
TIM3_IRQ_STA=0; //开启下一次捕获
}
}