在做完PWM输入模式后,自己有这样的想法,可不可以把捕获到的PWM信号在同一个定时器中原样输出呢,就这个问题,自己花了一天的时间去研究。怎么把读回来的频率和占空比在原来的定时器中的另一个口输出,程序在ARPE和影子寄存器中游了很久,最后反复看手册确定ARPE=0,要有事件更新时更新ARR,,这样频率更新的问题就解决了。那占空比就容易了。
程序说明:1、定时器2的PA0用于PMW输入捕获,PA2用于原样输出PWM信号。
2、定时器3的PA6用于PMW输入捕获,PB0用于原样输出PWM信号。
3、定时器3的PB6用于PMW输入捕获,PB8用于原样输出PWM信号。
4、串口用于发送捕获的PWM信号的频率和占空比。
5、目前这个程序测试过50HZ,70HZ的信号,
这里再次声明一下,如果你要捕获的PWM信号不在ARR,PSC,计算的范围内请自己先计算再使用本程序。
/******************main.c************************/
#include "sys.h" //系统子函数
#include "usart.h"//串口子函数
#include "delay.h" //延时子函数
#include "TIMER.h"//PB9用于传输数据
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);//延时函数初始化
uart_init(72,9600); //串口初始化
Timer2_Init(60000,72-1); //定时器2的PA0用于捕获,PA2用于PWM发送
Timer3_Init(60000,72-1); //定时器3的PA6用于捕获,PB0用于PWM发送
Timer4_Init(60000,72-1); //定时器4的PB6用于捕获,PB8用于PWM发送
while(1)
{
}
}
/*****************TIMER.c******************************/
#include "TIMER.h"
#include "delay.h"
#include "usart.h"//串口子函数
u16 IC1Value;
u16 IC2Value;
u16 IC3Value;
u16 IC4Value;
u16 IC5Value;
u16 IC6Value;
u16 DutyCycle1;
u16 Frequency1;
u16 DutyCycle2;
u16 Frequency2;
u16 DutyCycle3;
u16 Frequency3;
u8 flag=0;
/*定时器2*/
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&=0XFFFFFFF0;//PA0 输出
GPIOA->CRL|=0X00000004;//复用功能输出
GPIOA->ODR|=1<<0;//PA0 上拉
GPIOA->CRL&=0XFFFFFF0F;//PA1 输出
GPIOA->CRL|=0X00000040;//复用功能输出
GPIOA->ODR|=1<<1;//PA1 上拉
GPIOA->CRL&=0XFFFFF0FF;//PA2输出
GPIOA->CRL|=0X00000B00;//复用功能输出
GPIOA->ODR|=1<<2;//PA2 上拉
TIM2->ARR=arr;//设定计数器自动重装值
TIM2-> SC=psc;//预分频器不分频
TIM2->SMCR|=0x00D4;
//TIM2->SMCR|= 1<<5; //MSM=1 主/从模式
//TIM2->SMCR|= 5<<4; //TS=101 触发选择
//TIM2->SMCR|= 4<<0; //SMS=100 复位模式
//PA6 CCR1
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 允许捕获计数器的值到捕获寄存器中
//CCR2
TIM2->CCMR1|=2<<8;//CC2S=10 选择输入端
TIM2->CCER|=1<<5; //CC2P=1 选择有交转换边沿 下降沿有效
TIM2->CCER|=1<<4; //CC2E=1 允许捕获计数器的值到捕获寄存器中
TIM2->DIER|=1<<1; //允许更新捕获中断
TIM2->DIER|=1<<2; //允许更新捕获中断
//TIM2->CR1|=0x01; //使能定时器3
MY_NVIC_Init(1,1,TIM2_IRQChannel,1);//抢占1,子优先级3,组2
//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->CR1|=1<<7;
}
/*定时器3*/
void Timer3_Init(u16 arr,u16 psc) //定时器3
{
//此部分需手动修改 IO口设置
RCC->APB2ENR|=1<<0; //
RCC->APB1ENR|=1<<1; //TIM3 时钟使能
RCC->APB2ENR|=1<<2; //使能PORTA时钟
RCC->APB2ENR|=1<<3; //使能PORTA时钟
GPIOA->CRL&=0XF0FFFFFF;//PA6 输出
GPIOA->CRL|=0X04000000;//复用功能输出
GPIOA->ODR|=1<<6;//PA6 上拉
GPIOA->CRL&=0X0FFFFFFF;//PA7 输出
GPIOA->CRL|=0X40000000;//复用功能输出
GPIOA->ODR|=1<<7;//PA7 上拉
GPIOB->CRL&=0XFFFFFFF0;//PB0 输出
GPIOB->CRL|=0X0000000B;//复用功能输出
GPIOB->ODR|=1<<0;//PB0上拉
TIM3->ARR=arr;//设定计数器自动重装值
TIM3-> SC=psc;//预分频器不分频
TIM3->SMCR|=0x00D4;
//TIM3->SMCR|= 1<<5; //MSM=1 主/从模式
//TIM3->SMCR|= 5<<4; //TS=101 触发选择
//TIM3->SMCR|= 4<<0; //SMS=100 复位模式
//PA6 CCR1
TIM3->CCMR1|=1<<0;//CC1S=01 选择输入端
TIM3->CCMR1|=3<<4; //IC1F=0011配置输入滤波器
TIM3->CCER|=0<<1; //CC1P=0 选择有效转换边沿 上升沿有效
TIM3->CCMR1|=0<<2; //IC1PS=00 配置输入分频
TIM3->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
//CCR2
TIM3->CCMR1|=2<<8;//CC2S=10 选择输入端
TIM3->CCER|=1<<5; //CC2P=1 选择有交转换边沿 下降沿有效
TIM3->CCER|=1<<4; //CC2E=1 允许捕获计数器的值到捕获寄存器中
TIM3->DIER|=1<<1; //允许更新捕获中断
TIM3->DIER|=1<<2; //允许更新捕获中断
//TIM3->CR1|=0x01; //使能定时器3
MY_NVIC_Init(1,1,TIM3_IRQChannel,2);//抢占1,子优先级1,组2
//PWM
TIM3->CCMR2|=7<<4; //CH3 PWM2模式
TIM3->CCMR2|=1<<3; //CH3 预装载使能
TIM3->CCER|=1<<8; //OC3 输出使能
//TIM3->CR1=0x0080; //ARPE使能
//TIM3->CR1|=0x01; //使能定时器 3
TIM3->CR1|=1<<0; //使能定时器 3
}
/*定时器4*/
void Timer4_Init(u16 arr,u16 psc) //定时器4
{
//此部分需手动修改 IO口设置
RCC->APB1ENR|=1<<2; //TIM4 时钟使能
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0XF0FFFFFF;//PB6 输出
GPIOB->CRL|=0X04000000;//复用功能输出
GPIOB->ODR|=1<<6;//PB6 上拉
GPIOB->CRL&=0X0FFFFFFF;//PB7 输出
GPIOB->CRL|=0X40000000;//复用功能输出
GPIOB->ODR|=1<<7;//PB7 上拉
GPIOB->CRH&=0XFFFFFFF0;//PB8 输出
GPIOB->CRH|=0X0000000B;//复用功能输出
GPIOB->ODR|=1<<8;//PB8 上拉
TIM4->ARR=arr;//设定计数器自动重装值
TIM4-> SC=psc;//预分频器不分频
TIM4->SMCR|=0x00D4;
//TIM3->SMCR|= 1<<5; //MSM=1 主/从模式
//TIM3->SMCR|= 5<<4; //TS=101 触发选择
//TIM3->SMCR|= 4<<0; //SMS=100 复位模式
//PA6 CCR1
TIM4->CCMR1|=1<<0;//CC1S=01 选择输入端
TIM4->CCMR1|=3<<4; //IC1F=0011配置输入滤波器
TIM4->CCER|=0<<1; //CC1P=0 选择有效转换边沿 上升沿有效
TIM4->CCMR1|=0<<2; //IC1PS=00 配置输入分频
TIM4->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
//CCR2
TIM4->CCMR1|=2<<8;//CC2S=10 选择输入端
TIM4->CCER|=1<<5; //CC2P=1 选择有交转换边沿 下降沿有效
TIM4->CCER|=1<<4; //CC2E=1 允许捕获计数器的值到捕获寄存器中
TIM4->DIER|=1<<1; //允许更新捕获中断
TIM4->DIER|=1<<2; //允许更新捕获中断
//TIM4->CR1|=0x01; //使能定时器3
MY_NVIC_Init(1,1,TIM4_IRQChannel,3);//抢占1,子优先级3,组2
//PWM
TIM4->CCMR2|=7<<4; //CH3 PWM3模式
TIM4->CCMR2|=1<<3; //CH3 预装载使能
TIM4->CCER|=1<<8; //OC3 输出使能
//TIM4->CR1=0x0080; //ARPE使能 预装载
//TIM4->CR1|=0x01; //使能定时器 4
TIM4->CR1|=1<<0; //使能定时器 4
}
//定时器2中断服务程序
void TIM2_IRQHandler(void)
{
IC1Value = TIM2->CCR1;//读取CCR1也可以清CC1IF标志位
IC2Value = TIM2->CCR2;//读取CCR1也可以清CC2IF标志位
TIM2->CCR3 =IC1Value - IC2Value;//更新点空比
Frequency1 = 1000000/IC1Value;
DutyCycle1 = (IC2Value*100)/IC1Value;//占空比=(IC2Value/IC1Value)*100;
printf("Frequency1 = %d\r\n",Frequency1);
printf("DutyCycle1 = %d\r\n",DutyCycle1);
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)
{
IC3Value = TIM3->CCR1;//读取CCR1也可以清CC1IF标志位
IC4Value = TIM3->CCR2;//读取CCR1也可以清CC2IF标志位
TIM3->CCR3 =IC3Value-IC4Value;//更新点空比
Frequency2 = 1000000/IC3Value;
DutyCycle2 = (IC4Value*100)/IC3Value;//占空比=(IC2Value/IC1Value)*100;
printf("Frequency2 = %d\r\n",Frequency2);
printf("DutyCycle2 = %d\r\n",DutyCycle2);
}
//定时器4中断服务程序
void TIM4_IRQHandler(void)
{
IC5Value = TIM4->CCR1;//读取CCR1也可以清CC1IF标志位
IC6Value = TIM4->CCR2;//读取CCR1也可以清CC2IF标志位
TIM4->CCR3 =IC5Value -IC6Value;//更新点空比
Frequency3 = 1000000/IC5Value;
DutyCycle3 = (IC6Value*100)/IC5Value;//占空比=(IC2Value/IC1Value)*100;
printf("Frequency3 = %d\r\n",Frequency3);
printf("DutyCycle3 = %d\r\n",DutyCycle3);
}
/*******************TIMER.h********************************/
#ifndef __TIMER_H__
#define __TIMER_H__
#include "stm32f10x_lib.h"
#include "sys.h"
#define Pwm_port PBout(9)
void Pwm_port_Init(void);
void Timer3_Init(u16 arr,u16 psc);
void Timer2_Init(u16 arr,u16 psc);
void Timer4_Init(u16 arr,u16 psc); //定时器4
#endif
|