原理说明
捕获信号的频率其实有很多中实现方式,外部中断、输入捕获、使用外部时钟计数器等。对STM32有一定了解的朋友们在测量频率的问题上往往都会想到利用输入捕获,输入捕获的方式在中低频率段(1HZ-200KHZ)的测量还是比较准确的。在高频段还是建议采用外部时钟计数器的方式来实现。
采用输入捕获实现频率测量的实现步骤如下:
- 设置输入捕获为上升沿检测
- 记录第一次t1发生上升沿时捕获比较寄存器(CCR)的值cap_val1
- 记录第二次t2发生上升沿时捕获比较寄存器(CCR)的值cap_val2
- 根据不同溢出情况计算前后两次捕获值之和,同时根据TIM的计数频率,我们就可以算出捕获脉冲的频率。
代码实现
代码实现的部分主要是在输入捕获中断中对捕获的不同溢出情况进行了处理,实测效果还是不错的,4通道同时测的误差也就在1%左右。
宏定义&变量定义部分:
/* IC capture edge define*/
#define IC_RISE_EDGE_1 0
#define IC_RISE_EDGE_2 1
/* Capture TIMER Prescaler and Period define */
#define TIM1_PRESCALER 168-1
#define TIM1_PERIOD 0xFFFF
/* IC capture Parameters define*/
#define TIM1_IC_FREQ 168000000/TIM1_PRESCALER
#define TIM_ICOF_MAX 0x32
static float g_TIM1IcFreq = TIM1_IC_FREQ;
static float g_TIM1Period = TIM1_PERIOD;
static float g_FbFreqBuff[SPD_FB_CHAN_NUM] = {
0.0}; /* 频率反馈值*/
static float g_DevFbRotateSpdBuff[SPD_FB_CHAN_NUM] = {
0.0}; /* 转速反馈值*/
uint16_t g_IcofCntBuff[TIM_IC_MAX] = {
0}; /* 定时器溢出计数值*/
/* 定时器捕获通道枚举定义*/
typedef enum {
TIM1_IC1 = 0,
TIM1_IC2 ,
TIM1_IC3 ,
TIM1_IC4 ,
TIM_IC_MAX ,
} TIM_IC_Typedef;
定时器初始化部分:
void MX_TIM1_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {
0};
TIM_IC_InitTypeDef sConfigIC = {
0};
TIMER1_Handler.Instance = TIM1;
TIMER1_Handler.Init.Prescaler = TIM1_PRESCALER; //168M/168 = 1M计数频率,1us计数一次;
TIMER1_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIMER1_Handler