使用STM32-TIM进行频率和占空比的输入捕获测量
涉及知识点:
1.输入捕获模式
2.频率的测量方法
3.主从触发模式
4.PWMI测量占空比
正文:
1.输入捕获(Input Capture)简称为IC,在输入捕获模式下,当通道输入引脚出现指定电平跳变时(可以为上升沿,下降沿或都触发),当前的CNT的值被锁存到CCR中,通过读取当前状态CCR的值我们可以得知从开始计数到指定状态时CNT所计的值。如果CNT每次被锁存之后立即清0,则可以实现实时测量频率。
2.频率的测量方法:
测频法:在指定时间内求得对上升沿的计次,则f=N/T,如果指定时间为单位时间,那么N就等于f。
测周法:利用标准频率在两个上升沿之内计次,T=(1/fc)*N => f=fc/N
中界频率为测频法与测周法误差相等的频率点,令上面两式相等得到的频率即为中界频率。
3.主从触发模式
主模式:自己作为控制端去控制其他外设
从模式:用于接收其他外设或者自身引脚的信息,产生指定动作
在本实验中,可以通过从模式进行CNT清0的操作
4.PWMI基本结构
使用两个通道,一个通道与上述输入捕获模式相同,用于测量频率,第二个通道的区别在于为下降沿触发,提前将CNT锁存到对应CCR寄存器内,并且不会清0,而是等到下一个上升沿再清0,所以第二个通道的计次就代表着高电平对应的频率或周期。
代码部分:
首先配置GPIO口和开启时钟
然后配置输出PWM波形产生一定频率的波,跟上一节相同,配置时基单元,配置输出比较通道
然后配置输入捕获通道,需要配置时基单元,设定自动重装值和预分频值得到标准频率,设置主从触发模式进行CNT清0,GPIO口与时钟相对应。
PWM波形:
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP ;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,主要控制滤波系数
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_InitStructure.TIM_Period = 100-1; //ARR
TIM_InitStructure.TIM_Prescaler = 720-1; //PSC预分频值
TIM_InitStructure.TIM_RepetitionCounter =0x00;
TIM_TimeBaseInit(TIM2,&TIM_InitStructure);
TIM_OCInitTypeDef TIM_OCInitStucture; //配置输出比较模块
TIM_OCStructInit(&TIM_OCInitStucture);
TIM_OCInitStucture.TIM_OCMode= TIM_OCMode_PWM1; //输出模式
TIM_OCInitStucture.TIM_OCPolarity = TIM_OCPolarity_High; //极性选择
TIM_OCInitStucture.TIM_OutputState = TIM_OutputState_Enable; //使能
TIM_OCInitStucture.TIM_Pulse =0 ; //配置CCR
TIM_OC1Init(TIM2,&TIM_OCInitStucture);
TIM_Cmd(TIM2,ENABLE);
}
void PWM_SetCompare1(uint16_t Compare) //用于在运行钟调节CCR,compare为比较值
{
TIM_SetCompare1(TIM2,Compare);
}
void PWM_SetPrescaler(uint16_t Prescalar) //用于改变频率
{
TIM_PrescalerConfig(TIM2,Prescalar,TIM_PSCReloadMode_Immediate);
}
输入捕获:
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启定时器3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //配置GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6; //PA6的通道1
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM3); //
TIM_TimeBaseInitTypeDef TIM_InitStructure; //时基单元的配置
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,主要控制滤波系数
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_InitStructure.TIM_Period = 65536-1; //ARR
TIM_InitStructure.TIM_Prescaler = 72-1; //PSC预分频值
TIM_InitStructure.TIM_RepetitionCounter =0x00;
TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1 ; //通道选择
TIM_ICInitStructure.TIM_ICFilter= 0xF; //滤波器参数选择,数值越大滤波效果越好
TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Rising; //捕获极性选择,上升沿触发还是下降沿触发
TIM_ICInitStructure.TIM_ICPrescaler= TIM_ICPSC_DIV1; //输出捕获模块预分频值,这里选择不分频
TIM_ICInitStructure.TIM_ICSelection= TIM_ICSelection_DirectTI; //选择交叉通道还是直连通道
TIM_ICInit(TIM3,&TIM_ICInitStructure);
TIM_PWMIConfig(TIM3,&TIM_ICInitStructure); //快捷配置PWMI模式,意为将上述参数取反配置
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1); //选择触发源
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset); //配置从模式
TIM_Cmd(TIM3,ENABLE);
}
uint32_t IC_GetFreq(void) //获取频率
{
return 1000000/ TIM_GetCapture1(TIM3);
}
uint32_t IC_GetDuty(void) //获取占空比
{
return 100*(TIM_GetCapture2(TIM3)/TIM_GetCapture1(TIM3));
}
作者:ttal6688