其实这样的功能只要用一个定时器就可以完成了,不过为了更深地了解定时器输入捕获的功能,我自己设置了用定时器分开定时,外部中断读取信号的方法。只供参考学习。
程序说明:1、定时器2用于产生PWM信号 PA2
2、定时器3用于定时计算PWM信号的频率和占空比
3、串口发送数值
这里声明一下,如果你要捕获的PWM信号不在ARR,PSC计算的范围内,请自己先计算再使用本程序。
#include "stm32f10x_lib.h"
#include "sys.h"
#include "delay.h" //延时子函数
#include "usart.h"
#include "led.h"
#define Input1 PBin(0)// PB0
u16 Counter1;
u16 Counter2;
void EXTIX_Init(void);
void Timer2_Init(u16 arr,u16 psc); //定时器2用于产生PWM信号 PA2
void Timer3_Init(u16 arr,u16 psc);//定时器3用于定时计算PWM信号的频率和占空比 ,这里7200-1=10K
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);//延时函数初始化
uart_init(72,9600);
LED_Init();
EXTIX_Init();//外部中断初始化PB0
Timer2_Init(6000,720-1); //定时器2用于产生PWM信号 PA2
Timer3_Init(6000,7200-1); //定时器3用于定时计算PWM信号的频率和占空比 ,这里7200-1=10K
while(1)
{
printf("counter1 = %d
",(Counter1*100)/Counter2); //计算出占空比
printf("counter2 = %d
",10000/Counter2);//计算出频率
}
}
/*外部中断用于PWM输入口*/
void EXTIX_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0XFFFFFFF0;//PB0设置成输入
GPIOB->CRL|=0X00000008;
GPIOB->ODR|=1<<0; //PB0上拉
Ex_NVIC_Config(GPIO_B,0,3);//上升下降沿触发
MY_NVIC_Init(2,1,EXTI0_IRQChannel,2);//抢占2,子优先级1,组2
}
//外部中断15~10服务程序
void EXTI0_IRQHandler(void)
{
if(Input1 ==0)//先是上升沿触发中断
{
Counter1 = TIM3->CNT;//读取高电平时间
}
if(Input1 ==1)//第二次中断是下降沿
{
Counter2 = TIM3->CNT;//读取总时间
delay_us(5);//这里要延时一点点再清计算器
TIM3->CNT = 0;//请计数器
}
EXTI->
R=1<<0; //清除LINE0上的中断标志位
}
/*定时器2用于产生PWM信号*/
void Timer2_Init(u16 arr,u16 psc) //定时器2用于adc采样
{
//此部分需手动修改 IO口设置
RCC->APB1ENR|=1<<0; //TIM2 时钟使能
RCC->APB2ENR|=1<<0; //
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRL&=0XFFFFF0FF;//PA2输出
GPIOA->CRL|=0X00000B00;//复用功能输出
GPIOA->ODR|=1<<2;//PA2 上拉
TIM2->ARR=arr;//设定计数器自动重装值
TIM2->
SC=psc;//预分频器不分频
//PWM
TIM2->CCMR2|=7<<4; //CH3 PWM2模式
TIM2->CCMR2|=1<<3; //CH3 预装载使能
TIM2->CCER|=1<<8; //OC3 输出使能
TIM2->CR1=0x0080; //ARPE使能
//TIM2->CR1|=0x01; //使能定时器 3
TIM2->CR1|=1<<0; //使能定时器 2
TIM2->CCR3 = 3000; //占空比初值 = 1440*50% = 720
}
/*定时器3用于产后PWM信号*/
void Timer3_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1;//TIM2时钟使能
TIM3->ARR=arr; //设定计数器自动重装值//刚好1ms
TIM3->
SC=psc; //预分频器,
TIM3->DIER|=1<<0; //允许更新中断
TIM3->DIER|=1<<6; //允许触发中断
TIM3->CR1|=0x01; //使能定时器3
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//溢出中断
{
LED0=~LED0;
}
TIM3->SR&=~(1<<0);//清除中断标志位
}
一周热门 更多>