基于HAL库的STM32的单定时器的多路输入捕获测量脉冲频率(外部时钟实现)

目录

写在前面

一般的做法(定时器单通道输入捕获)

以外部时钟的方式(高低频都适用)

测试效果


写在前面

STM32的定时器本身有输入捕获的功能。可选择双端捕获,上升沿捕获或者是下降沿捕获。对应捕获频率来说,连续捕获上升沿或下降沿的时间间隔就是其脉冲的周期.

一般的做法(定时器单通道输入捕获)

定时器设置频率为1M.

每次进入输入捕获的中断回调函数  HAL_TIM_IC_CaptureCallback 就让其计数值CNT为0. 那么连续两次采样的计数值也就是 (TIMx->CCRx - 0) ,频率 =定时器频率/(TIMx->CCRx - 0).


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    
    

    
    if(htim->Instance == TIM2)
    {
        
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
            
            freq=htim->Instance->CCR2;
            freq = 1e6/freq;
            htim->Instance->CNT =0;
            
            
        
        }
        
    }
}

如果是单个定时器对多个通道进行采样呢?这时候就必须重新考虑如何测量频率了。通用做法:

(以上升沿为例,定时器的计数值TIMx->CNT设置为65535后溢出)

测量第一次上升沿的捕获值CCRx,即为first,并设置标记表示开始测量,若存在溢出则在定时器的溢出回调函数  HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)中记录溢出次数,直到第二个上升沿到来,计为 second,计算频率。

频率= 定时器的频率  /   (second - first +溢出次数*溢出值)

由上面的等式得出,若两个上升沿之间的计数值 > 定时器的频率 ,则脉冲的频率<1hz 属于低频。

低频是非常好测量的,难的是高频。若还想以直接的方式去测量高频,则不太现实,因为高频两个脉冲之间的间隔更短,而定时器的频率总不可能超过其系统频率,更不可能达到高频脉冲的频率。

直接不行变间接,将一段时间内的脉冲的个数进行计数统计,并记录所统计的这一段时间
频率  =  个数 /时间, 若设置时间为1s(特殊情况) 频率= 1s内的脉冲个数. 计时需要用到别的定时器。

以外部时钟的方式(高低频适用)

 

typedef struct mypwm{
  
 u32 ts; //记录的脉冲值
 u8 flag; //开始信号/结束信号
 u16 time; //记录的时间   
    
} mypwm;

mypwm m1 ={0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
    if(htim->Instance == TIM6)
    {
        
        
        if(m1.flag == 0) m1.flag = 1; //第一次进来
        else if(m1.flag == 1){ 
            
          if( ++m1.time == 1000){//增加1ms
              
              //已经测了1s
              m1.time = 0;
              m1.flag = 0;
              freq = m1.ts;
              m1.ts = 0;
              
          } 
            
            
        }
    }
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

    
    if(htim->Instance == TIM2)
    {
        
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
            
 
            
         
            if(m1.flag == 1)  m1.ts++;
            
           
           
        }
        
    }
}

测试效果

通过定位器去控制脉冲发生器的输出频率以此测量:

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
STM32基本定时器输入捕获功能可以用于测量外部信号的脉冲宽度、周期等参数。下面是使用STM32Cube HAL库进行配置的基本步骤: 1. 初始化定时器:根据所选的定时器,调用`HAL_TIM_Base_MspInit()`函数进行初始化。 2. 配置定时器参数:使用`TIM_HandleTypeDef`结构体配置定时器的基本设置,比如时钟源、预分频系数等。 3. 配置输入捕获参数:使用`TIM_IC_InitTypeDef`结构体配置输入捕获通道的参数,包括捕获极性、预分频系数等。 4. 初始化输入捕获通道:调用`HAL_TIM_IC_Init()`函数初始化输入捕获通道。 5. 启动定时器:调用`HAL_TIM_Base_Start()`函数启动定时器。 6. 获取输入捕获值:使用`HAL_TIM_IC_Start_IT()`函数启动输入捕获中断,并在中断回调函数中读取输入捕获值。 以下是一个示例代码,演示如何配置和使用基本定时器输入捕获功能: ```c #include "stm32f4xx_hal.h" /* 定时器句柄 */ TIM_HandleTypeDef htim2; /* 输入捕获值 */ uint32_t captureValue = 0; /* 定时器中断回调函数 */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { /* 读取输入捕获值 */ captureValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); } } } int main(void) { /* 初始化HAL库 */ HAL_Init(); /* 配置系统时钟 */ SystemClock_Config(); /* 初始化定时器 */ TIM2_Init(); /* 配置输入捕获通道 */ TIM2_IC_Config(); /* 启动定时器 */ HAL_TIM_Base_Start(&htim2); /* 启动输入捕获中断 */ HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); while (1) { /* 在这里可以进行其他操作 */ } } /* 定时器初始化 */ void TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFFFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim2); sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig); } /* 输入捕获通道配置 */ void TIM2_IC_Config(void) { TIM_IC_InitTypeDef sConfigIC = {0}; htim2.Channel = HAL_TIM_ACTIVE_CHANNEL_1; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFFFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1); } ``` 上述代码使用了TIM2作为定时器,并配置了通道1进行输入捕获,捕获上升沿触发的信号。在输入捕获中断回调函数中,可以读取输入捕获的值,并在主循环中进行其他操作。 请注意,上述代码仅为示例,具体的配置和使用方法需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值