一、输入捕获简介
(1) IC(Input Capture)输入捕获
<1>输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前
CNT
的值将被锁存到 CCR中,可用于测量
PWM波形的频率
、
占空比
、
脉冲间隔
、
电平持续时间
等参数
<2>
每个
高级定时器和通用定时器
都拥有
4个输入捕获通道
<3>
可配置为
PWMI模式
,
同时测量频率和占空比
<4>
可配合
主从触发模式
,实现硬件全自动测量
(2)频率测量
测频法:适合测评低频信号,测量结果更新慢但是数值相对稳定。
测周法:适合测量高频信号,测量结果更新快数据跳变快。
二、输入捕获与PWMI基本结构
三、输入捕获测频率代码
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
uint16_t i=0;
void PWMInit(void);
void PwmSetCompare(uint16_t campare);
void PwmSetPersc(uint16_t Persc);
void ICInit(void);
uint32_t IcGetFreq(void);
int main(void)
{
PWMInit();
ICInit();
OLED_Init();
PwmSetPersc(720-1);
PwmSetCompare(50);
while(1)
{
OLED_ShowNum(1,6,IcGetFreq(),5);
}
}
/***************************************************************
* @briefvoid PWMInit(void)
* @param void
* @note 初始化PWM引脚
* @Sample PWMInit();
**************************************************************/
void PWMInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_InternalClockConfig(TIM2);//选用内部时钟
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式
TIM_TimeBaseInitStruct.TIM_Period=100-1;//周期ARR自动重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler=720-1;//PSC预分频器的值
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值
//定时频率=72M/(PSC+1)*(ARR+1)
//定时时间=1/[72/(PSC+1)]*(ARR+1)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;//中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;//
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择分组2
NVIC_Init(&NVIC_InitStruct);
TIM_OCStructInit(&TIM_OCInitStruct);//给该结构体成员都赋一个初值
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCNPolarity_High;//设置输出比较的极性
TIM_OCInitStruct.TIM_OutputState=TIM_OSSRState_Enable;//设置输出使能
TIM_OCInitStruct.TIM_Pulse=50; //设置CCR值
TIM_OC1Init(TIM2,&TIM_OCInitStruct);
TIM_Cmd(TIM2,ENABLE);//启动定时器
}
/***************************************************************
* @brief void ICInit()
* @param void
* @note 初始化输入捕获模式
* @Sample ICInit();
**************************************************************/
void ICInit(void)
{
//1、开始时钟
TIM_ICInitTypeDef TIM_ICInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//2、配置GPIO引脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//3、配置定时器时基单元
TIM_InternalClockConfig(TIM3);//选用内部时钟
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式
TIM_TimeBaseInitStruct.TIM_Period=65536-1;//周期ARR自动重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;//PSC预分频器的值 决定了测周法的标准频率fc
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值
//定时频率=72M/(PSC+1)*(ARR+1)
//定时时间=1/[72/(PSC+1)]*(ARR+1)
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
//4、配置输入捕获模式
TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;//选择通道
TIM_ICInitStruct.TIM_ICFilter=0xf;//设置输入捕获的滤波器
TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;//极性(触发方式)
TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;//分频器
TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;//选择直连通道或者交叉通道
TIM_ICInit(TIM3,&TIM_ICInitStruct);
//5、触发源选择
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
//6、配置从模式为Reset
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
//7、启动定时器
TIM_Cmd(TIM3,ENABLE);
}
/***************************************************************
* @brief void PwmSetCompare(uint16_t campare);
* @param campare
* @note 设置OCR1的值改变PWM占空比
* @Sample 无
**************************************************************/
void PwmSetCompare(uint16_t campare)
{
TIM_SetCompare1(TIM2,campare);//设置OCR1的值
}
/***************************************************************
* @brief void PwmSetPersc(uint16_t Persc)
* @param Persc
* @note 设置分频器值
* @Sample PwmSetPersc(Persc);
**************************************************************/
void PwmSetPersc(uint16_t Persc)
{
TIM_PrescalerConfig(TIM2,Persc,TIM_PSCReloadMode_Immediate);
}
/***************************************************************
* @brief uint32_t IcGetFreq(void)
* @param void
* @note 获取当前频率
* @Sample IcGetFreq();
**************************************************************/
uint32_t IcGetFreq(void)
{
return 1000000/(TIM_GetCapture1(TIM3)+1);
}
四、PWMI模式测量占空比
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
uint16_t i=0;
void PWMInit(void);
void PwmSetCompare(uint16_t campare);
void PwmSetPersc(uint16_t Persc);
void ICInit(void);
uint32_t IcGetFreq(void);
uint32_t IcGetDutey(void);
int main(void)
{
PWMInit();
ICInit();
OLED_Init();
PwmSetPersc(720-1);
PwmSetCompare(50);
while(1)
{
OLED_ShowNum(1,6,IcGetFreq(),5);
OLED_ShowNum(2,6,IcGetDutey(),2);
}
}
/***************************************************************
* @briefvoid PWMInit(void)
* @param void
* @note 初始化PWM引脚
* @Sample PWMInit();
**************************************************************/
void PWMInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_InternalClockConfig(TIM2);//选用内部时钟
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式
TIM_TimeBaseInitStruct.TIM_Period=100-1;//周期ARR自动重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler=720-1;//PSC预分频器的值
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值
//定时频率=72M/(PSC+1)*(ARR+1)
//定时时间=1/[72/(PSC+1)]*(ARR+1)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;//中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;//
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择分组2
NVIC_Init(&NVIC_InitStruct);
TIM_OCStructInit(&TIM_OCInitStruct);//给该结构体成员都赋一个初值
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCNPolarity_High;//设置输出比较的极性
TIM_OCInitStruct.TIM_OutputState=TIM_OSSRState_Enable;//设置输出使能
TIM_OCInitStruct.TIM_Pulse=50; //设置CCR值
TIM_OC1Init(TIM2,&TIM_OCInitStruct);
TIM_Cmd(TIM2,ENABLE);//启动定时器
}
/***************************************************************
* @brief void ICInit()
* @param void
* @note 初始化输入捕获模式
* @Sample ICInit();
**************************************************************/
void ICInit(void)
{
//1、开始时钟
TIM_ICInitTypeDef TIM_ICInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//2、配置GPIO引脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//3、配置定时器时基单元
TIM_InternalClockConfig(TIM3);//选用内部时钟
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式
TIM_TimeBaseInitStruct.TIM_Period=65536-1;//周期ARR自动重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;//PSC预分频器的值 决定了测周法的标准频率fc
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值
//定时频率=72M/(PSC+1)*(ARR+1)
//定时时间=1/[72/(PSC+1)]*(ARR+1)
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
//4、配置输入捕获模式
TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;//选择通道
TIM_ICInitStruct.TIM_ICFilter=0xf;//设置输入捕获的滤波器
TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;//极性(触发方式)
TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;//分频器
TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;//选择直连通道或者交叉通道
TIM_ICInit(TIM3,&TIM_ICInitStruct);
//5、快速设置PWMI模式
TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);
//6、触发源选择
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
//7、配置从模式为Reset
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
//8、启动定时器
TIM_Cmd(TIM3,ENABLE);
}
/***************************************************************
* @brief void PwmSetCompare(uint16_t campare);
* @param campare
* @note 设置OCR1的值改变PWM占空比
* @Sample 无
**************************************************************/
void PwmSetCompare(uint16_t campare)
{
TIM_SetCompare1(TIM2,campare);//设置OCR1的值
}
/***************************************************************
* @brief void PwmSetPersc(uint16_t Persc)
* @param Persc
* @note 设置分频器值
* @Sample PwmSetPersc(Persc);
**************************************************************/
void PwmSetPersc(uint16_t Persc)
{
TIM_PrescalerConfig(TIM2,Persc,TIM_PSCReloadMode_Immediate);
}
/***************************************************************
* @brief uint32_t IcGetFreq(void)
* @param void
* @note 获取当前频率
* @Sample IcGetFreq();
**************************************************************/
uint32_t IcGetFreq(void)
{
return 1000000/(TIM_GetCapture1(TIM3)+1);
}
/***************************************************************
* @brief uint32_t IcGetDutey(void)
* @param void
* @note 获取当前读取的占空比
* @Sample usage:
**************************************************************/
uint32_t IcGetDutey(void)
{
return (TIM_GetCapture2(TIM3)*100/TIM_GetCapture1(TIM3)+1);
}