STM32输入捕获测量PWM频率占空比

首先配置我们的输入捕获时钟

输出PWM则使用TIM2时钟

最终代码

复制代码
#include "user.h"

#include "oled.h"

char rx_buf[128];
extern DMA_HandleTypeDef hdma_usart1_rx;


// Global variables
// TIM3 捕获溢出全局变量
uint32_t rise_time1 = 0;       // 第一个上升沿时间
uint32_t fall_time = 0;        // 下降沿时间
uint32_t rise_time2 = 0;       // 第二个上升沿时间
uint32_t rise_time1_overflow = 0; // 第一个上升沿时的溢出次数
uint32_t fall_time_overflow = 0;  // 下降沿时的溢出次数
uint32_t rise_time2_overflow = 0; // 第二个上升沿时的溢出次数
uint8_t capture_cnt = 0;       // 捕获阶段计数
uint8_t capture_flag = 0;      // 捕获完成标志
float pwm_frequency = 0;       // 最终计算的PWM频率
float pwm_duty = 0;            // 最终计算的占空比

extern volatile uint32_t tim3_overflow_count; // 声明在 stm32f1xx_it.c 中的溢出计数

void app(void){
  //OLED
  OLED_Init();
  OLED_Clear();
  OLED_Refresh();
  
  //UART
  HAL_UARTEx_ReceiveToIdle_DMA(&huart1,(uint8_t*)rx_buf,128);
  __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
  
  // 确保初始极性为上升沿
  __HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
  
  //TIM2 start
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  //TIM3 IC start  
  HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
  
  while(1){
    if (capture_flag)
    {
      print("Freq: %.2f Hz, Duty: %.2f%%\r\n", pwm_frequency, pwm_duty);
      capture_flag = 0;
    }
  }
}

//uart Idle DMA
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
  if(huart == &huart1){
    print("Received: %s",rx_buf);
    
    memset(rx_buf,0,128);
    HAL_UARTEx_ReceiveToIdle_DMA(&huart1,(uint8_t*)rx_buf,128);
    __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
  }
}

//TIM2->PWM->TIM3
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
  if (htim->Instance == TIM3 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
  {
    if (capture_cnt == 0)
    {
      // 第一个上升沿
      rise_time1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
      rise_time1_overflow = tim3_overflow_count; // 记录溢出次数
      __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
      capture_cnt = 1;
    }
    else if (capture_cnt == 1)
    {
      // 下降沿
      fall_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
      fall_time_overflow = tim3_overflow_count; // 记录溢出次数
      __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
      capture_cnt = 2;
    }
    else if (capture_cnt == 2)
    {
      // 第二个上升沿
      rise_time2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
      rise_time2_overflow = tim3_overflow_count; // 记录溢出次数
      
      uint32_t high_time_total;
      uint32_t period_total;
      
      // 计算高电平时间 (考虑溢出)
      if (fall_time_overflow == rise_time1_overflow) {
          high_time_total = fall_time - rise_time1;
      } else {
          high_time_total = (fall_time_overflow - rise_time1_overflow) * (0xFFFF + 1) + fall_time - rise_time1;
      }

      // 计算周期 (考虑溢出)
      if (rise_time2_overflow == rise_time1_overflow) {
          period_total = rise_time2 - rise_time1;
      } else {
          period_total = (rise_time2_overflow - rise_time1_overflow) * (0xFFFF + 1) + rise_time2 - rise_time1;
      }
      
      // 重置溢出计数器,确保下一次测量从0开始
      tim3_overflow_count = 0;
      
      if (period_total > 0)
      {
        pwm_frequency = 1000000.0f / (float)period_total; // TIM3 频率为 1MHz (1us/tick)
        pwm_duty = ((float)high_time_total * 100.0f) / (float)period_total;
        capture_flag = 1;
      }
      
      capture_cnt = 0;
    }
  }
}


void print(const char *format, ...){
    char buf[128];
    va_list args;
    va_start(args,format);
    vsnprintf(buf,128-1,format,args);
    va_end(args);
    HAL_UART_Transmit(&huart1,(uint8_t*)buf,strlen(buf),1000);
}
相关推荐
蜗牛攻城狮2 小时前
微前端四大方案选型对比与最佳实践:qiankun、micro-app、wujie、Module Federation
前端·微前端·qiankun·前端架构·micro-app·wujie
她说可以呀3 小时前
Vue插槽
前端·javascript·vue.js
qq_448011163 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
aixingpan3 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
2601_958352904 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
志尊宝4 小时前
AI原生前端开发(039):AI辅助的Nuxt 4全栈开发
前端·vue.js·ai-native
FRing035 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
excel6 小时前
双 Token 与前端使用 Crypto 公私钥鉴权换 Token,哪种方案更好?
前端·后端
外收内放6 小时前
Python基础语法练习题(73)
java·前端·python
风骏时光牛马6 小时前
面向复杂场景的大模型应用落地与能力优化实践
前端