刚刚开始做定时器输入捕获的时候在这个论坛上找了好久,都没有人分享,也有很多人问,无奈自己动手写了。花了一天的时间,这个东西真的不好写了,对比了库的例子,仿真,等。可以说付出了很多。现在完成了和大家分享。希望大家多多支持。这个程序是在定时器输入捕获的基础上看手册完成的,程序说明:1、程序中定时器4的PB6用于输出频率为1K,占空比为50%的PWM信号。
2、定时器2的PA0用于输入捕获,当程序下到板子上,只有两个脚连在一起才会发生捕获。
3、串口用于发送捕获的值到PC机上。
4、定时器2的CCR1存PWM信号的频率,CCR2存高电平时间。
这里声明一下,如果你要捕获的PWM信号不在ARR,PSC计算的范围内,请自己先计算再使用本程序。
#include "stm32f10x_lib.h"
#include "sys.h"
#include "delay.h" //延时子函数
#include "usart.h"
u16 IC1Value;
u16 IC2Value;
u16 DutyCycle;
u16 Frequency;
void PWM_Init(u16 arr,u16 psc);
void Capture_Init(u16 arr,u16 psc);
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);//延时函数初始化
uart_init(72,9600);
PWM_Init(1000,72-1); //不分频。PWM频率=72000/1440=5Khz
Capture_Init(2000,72-1);
while(1)
{
Frequency = 1000000/IC1Value;
DutyCycle = (IC2Value*100)/IC1Value;//占空比=(IC2Value/IC1Value)*100;
printf("Frequency = %d
",Frequency);
printf("DutyCycle = %d
",DutyCycle);
printf("suqingxiao
");
}
}
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void PWM_Init(u16 arr,u16 psc)
{
//此部分需手动修改 IO口设置
RCC->APB2ENR|=1<<0; //
RCC->APB1ENR|=1<<2; //TIM4 时钟使能
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0XF0FFFFFF;//PB6 输出
GPIOB->CRL|=0X0B000000;//复用功能输出
GPIOB->ODR|=1<<6;//PB6 上拉
TIM4->ARR=arr;//设定计数器自动重装值
TIM4->
SC=psc;//预分频器不分频
TIM4->CCMR1|=7<<4; //CH1 PWM2模式
TIM4->CCMR1|=1<<3; //CH1 预装载使能
TIM4->CCER|=1<<0; //OC1 输出使能
TIM4->CR1=0x0080; //ARPE使能
TIM4->CR1|=0x01; //使能定时器 3
TIM4->CCR1 = 500; //占空比初值 = 1440*50% = 720
}
void Capture_Init(u16 arr,u16 psc)
{
//此部分需手动修改 IO口设置
RCC->APB2ENR|=1<<0; //
RCC->APB1ENR|=1<<0; //TIM2 时钟使能
RCC->APB2ENR|=1<<2; //使能PORTA时钟
TIM2->ARR=arr; //设定计数器自动重装值//刚好1ms
TIM2->
SC=psc; //预分频器,
GPIOA->CRL&=0XFFFFFFF0;//PA0 输出
GPIOA->CRL|=0X00000004;//复用功能输出
GPIOA->ODR|=1<<0;//PA0 上拉
TIM2->SMCR|=0x00D4;
//TIM2->SMCR|= 1<<5; //MSM=1 主/从模式
//TIM2->SMCR|= 5<<4; //TS=101 触发选择
//TIM2->SMCR|= 4<<0; //SMS=100 复位模式
TIM2->CCMR1|=1<<0;//CC1S=01 选择输入端
TIM2->CCMR1|=3<<4; //IC1F=0011配置输入滤波器
TIM2->CCER|=0<<1; //CC1P=0 选择有效转换边沿 上升沿有效
TIM2->CCMR1|=0<<2; //IC1PS=00 配置输入分频
TIM2->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
TIM2->CCMR1|=2<<8;//CC2S=10 选择输入端
TIM2->CCER|=1<<5; //CC2P=1 选择有交转换边沿 下降沿有效
TIM2->CCER|=1<<4; //CC2E=1 允许捕获计数器的值到捕获寄存器中
TIM2->DIER|=1<<1; //允许更新捕获中断
TIM2->CR1|=0x01; //使能定时器2
MY_NVIC_Init(1,3,TIM2_IRQChannel,2);//抢占1,子优先级3,组2
}
//定时器2中断服务程序
void TIM2_IRQHandler(void)
{
IC1Value = TIM2->CCR1;//读取CCR1也可以清CC1IF标志位
IC2Value = TIM2->CCR2;//读取CCR1也可以清CC2IF标志位
TIM2->SR&=~(1<<1);//清除中断标志位
}
还有上面Capture_Init(2000,72-1); 里面的参数与PWM_Init(1000,72-1); 里面的参数有什么具体关系呢? 谢谢!
关系是:Capture_Init(2000,72-1)中的2000是用于计数的,就是触发后到下一次触发的计数,如果捕获的PWM信号周期太长20000不够会有溢出的。PWM_Init(1000,72-1); 中的1000是重载,当设置72-1时,分频为1M,重载1000,就是1M/1000=1K。
如果Capture_Init(2000,72-1)设置72-1,说明分频为1M,1M的频率在计数1K的信号那计数器要计数1000次,这个1000次要在Capture_Init(2000,72-1)中的2000内,
如果1000次大于Capture_Init(2000,72-1)中的2000,那就会溢出了。
所以,如果PWM_Init(1000,72-1); 中的1000这个数很大,那Capture_Init(2000,72-1)中的2000要比它大就得了。这样就不会溢出了。
一周热门 更多>