PWM模式输入
该方式是在STM32输入捕获模式基础上扩展升级的功能,可以测量PWM波的频率及占空比,需要多加一个输入捕获寄存器
基本原理
(1)实现PWM输入捕获需要占用TIMx的两个通道,以IC1、IC2为例,TI1引脚上电平可被第1通道和第2通道同时监测到,两个通道分别被设置为主机和从机,如果设置第1通道为PWM输入捕获功能,则第2通道为从机。(IC1和IC2 IC3和IC4是成对存在的)
(2)输入的PWM从高电平跳变,第1个下降沿来临时,IC1 IC2均可监测到,从机设置为复位模式,将TIMx的计数器复位至0(此时不会产生计数器更新中断,因为无溢出)
(3)下一个上升沿来临时,IC2发生捕获事件,将当前计数器CNT的值存储至CCR2中,记为IC2_DATA2
(4)第二个下降沿来临,IC1发生捕获事件,将当前计数器CNT的值存储至CCR1中,记为IC1_DATA1
5)PWM波信号频率
f=72*10^6 /(psc(预分频系数)+1)/ IC1_DATA1
占空比D=IC2_DATA2/IC1_DATA1
频率f=72*10^6 /(psc(预分频系数)+1)/ IC1_DATA1
其中预分频系数这一项可以不加,如果不设置TIM_TimeBaseStructure.TIM_Prescaler这一项,则默认预分频系数为0,即此时:
频率f=72*10^6 / IC1_DATA1
此时可监测的频率范围为 72*10^6/65536(1098.6 Hz) ---- 72MHz,低于1098.6 Hz的频率将无法监测
故设置预分频系数 psc,降低其可监测的范围(最大监测值和最小监测值都会改变)
实验(PWM输入部分代码)
基于STM32F103MiNi开发板(正点原子),以定时器3为例,TIM3_CH1(PA6引脚),由定时器4(TIM4_CH3 PB8引脚)产生PWM波,通过杜邦线外接PB8和PA6引脚
/*定时器3 PWM波输入捕获部分*/
void TIM3_Init(u16 psc) //形参为分频系数
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB1Periph_TIM3, ENABLE); //时钟初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure); //引脚初始化
TIM_TimeBaseStructure.TIM_Period = 65535; //计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复溢出次数,设置为0
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
//通道1
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //IC1
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //IC1映射到TI1上
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置分频模式,不分频
TIM_ICInitStructure.TIM_ICFilter = 0x00; //配置输入滤波模式,不滤波
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//中断优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //选择TIM3输入触发源 TI1
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /选择从机模式,复位模式
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); //开启复位模式
TIM_Cmd(TIM3,ENABLE ); //使能计数器
TIM_ITConfig(TIM3,TIM_IT_CC1,ENABLE);//使能中断
}
//中断部分
void TIM3_IRQHandler(void)
{
static float Duty;
static float IC1_DATA1; //IC1_DATA1 、IC2_DATA2 定义为float类型,否则Duty会显示0
static float IC2_DATA2; //
static u16 Frequence;
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
IC1_DATA1 = TIM_GetCapture1(TIM3);
IC2_DATA2 = TIM_GetCapture2(TIM3);
if (IC1_DATA1 != 0)
{
Frequence = (72000000/IC1_DATA1/(psc+1)); //psc为TIM3_Init(u16 psc)初始化的形参,值相同
}
else
{
Frequence = 0;
}
Duty=IC2_DATA2/IC1_DATA1; //获得占空比
printf("占空比=%%%.1f rn",(Duty*100));
printf("PWM波频率=%d Hz rn",Frequence);
}
定时器4产生PWM波部分,直接借鉴正点原子官方 PWM波输出实验即可。
工程:PWM模式输入
测量一段时间内脉冲个数求频率
用TIM3_IRQHandler()中断计数PWM波脉冲个数,此时需要用另外一个定时器TIMx作为时钟计时,此时用定时器7作为计时时钟,定时器4产生PWM波
//TIM3 初始化
void TIM3_Init(u16 arr,u16 psc) //形参为分频系数
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB1Periph_TIM3, ENABLE); //时钟初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure); //引脚初始化
TIM_TimeBaseStructure.TIM_Period =arr; //计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频系数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复溢出次数,设置为0
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
//通道1
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //IC1
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //下降沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //IC1映射到TI1上
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置分频模式,不分频
TIM_ICInitStructure.TIM_ICFilter = 0x00; //配置输入滤波模式,不滤波
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//中断优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_CtrlPWMOutputs(TIM8,ENABLE);
TIM_Cmd(TIM3,ENABLE ); //使能计数器
TIM_ITConfig(TIM3,TIM_IT_CC1,ENABLE);//使能中断
}
//中断部分
void TIM3_IRQHandler(void)
{
static u16 Frequence=0;
static float time;
static unsigned int PWMone=0;
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
Frequence++; //脉冲个数加1
if((PWMTimer - PWMOneMinute)>99) //定时1s更新一次,此处由另一定时器7提供时间基准
{
PWMOneMinute=PWMTimer; //重新开始计时
time=Frequence/10; //计算得到频率(1s内脉冲个数)
Frequence=0; //重新开始计数
printf("PWM波频率=%d Hz",Frequence);
}
}