问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32F103C8T6测量脉冲波信号频率和占空比

创作时间:
作者:
@小白创作中心

STM32F103C8T6测量脉冲波信号频率和占空比

引用
CSDN
1.
https://blog.csdn.net/Cc20200930/article/details/145801644

本文介绍了一种使用STM32F103C8T6微控制器测量脉冲波信号频率和占空比的方法。通过配置CubeMX和编写相应的代码,可以实现对10kHz以下脉冲信号的精确测量,测量误差不大于2%,显示精度不低于1Hz。文章详细介绍了硬件配置、代码实现以及调试过程中的注意事项,对于从事嵌入式系统开发的工程师具有一定的参考价值。

一、题目

测量脉冲波信号的频率,测量误差不大于 2%,显示精度不低于 1Hz。对脉冲波的占空比进行测量并显示,精度不低于 2%。

二、思路

本文给出的方法主要是测量低频的方法。在测 10 kHz 以下有用。

三、CubeMX 配置

  • 时钟配置
  • 串口 debug
  • IIC
  • TIM3
  • NVIC 设置
  • GPIO 设置

四、代码

变量定义

/* USER CODE BEGIN PV */
volatile float TIM3CH1_Freq = 0.0; // 频率
volatile float TIM3CH1_Duty = 0.0; // 占空比
volatile int capture_end_flag = 0; // 

volatile uint32_t high_val = 0;
volatile uint32_t low_val = 0;
/* USER CODE END PV */

初始化

/* USER CODE BEGIN 2 */
OLED_Init();
OLED_Clear();
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1); // 开启定时器

OLED_Refresh_Gram();
/* USER CODE END 2 */

主循环

注意,HAL_Delay()放在循环里可能会造成问题。

/* USER CODE BEGIN WHILE */
while (1)
{
//		HAL_Delay(3000);
    if(capture_end_flag == 1)
    {
        OLED_Refresh_Gram();
        OLED_ShowNum(0, 0, TIM3CH1_Freq, 6, 16); // 显示频率

        OLED_ShowString(50, 0, str1, 16);

        OLED_ShowNum(0, 16, (uint16_t)(TIM3CH1_Duty * 100) % 100, 2, 16); // 显示占空比的整数
        OLED_ShowChar(16, 16, '.', 16, 1);
        OLED_ShowChar(38, 16, '%', 16, 1);
        if ((uint16_t)(TIM3CH1_Duty * 10000) % 100 < 10 && 0 < (uint16_t)(TIM3CH1_Duty * 10000) % 100){ // 显示占空比的小数
            OLED_ShowChar(21, 16, '0', 16, 1);
        }else if ((uint16_t)(TIM3CH1_Duty * 10000) % 100 == 0){
            OLED_ShowChar(21, 16, '0', 16, 1);
            OLED_ShowChar(28, 16, '0', 16, 1);
        }
        else{
            OLED_ShowNum(21, 16, (uint16_t)(TIM3CH1_Duty * 10000) % 100, 2, 16);
        }
        capture_end_flag = 0;
    }	
    /* USER CODE END WHILE */

TIM 捕捉回调函数

/* USER CODE BEGIN 0 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) // TIM 捕捉回调函数 
{
    static uint8_t capture_cnt = 1;    //电平捕捉计数

    if(htim->Instance == TIM3)        //判断是否由 定时器3 产生
    {
            if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)    //TIM3 通道 1
            {    
                    if(capture_end_flag == 0)
                    {
                            if(capture_cnt == 1)        // 第一次进入回调,捕获第一个上升沿
                            {
                                    capture_cnt = 2; // 下一次要捕获第二个沿事件
                                    __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); //设置成下降沿触发
                                    __HAL_TIM_SetCounter(htim, 0);    //清空定时器计数值,为了从当前沿开始重新计时
                                    high_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);    //由第一个上升沿设为起始位置
                                    
                            }else if(capture_cnt == 2)    // 第二次进入回调,捕获第一个下降沿
                            {
                                    capture_cnt = 3; // 下一次要捕获第三个沿事件
                                    low_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);    //低电平起始位置
                                    __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); //设置成上升沿触发
                                    
                                    
                            }else if(capture_cnt == 3)    // 第三次进入回调,第二个上升沿
                            {
                                    capture_cnt = 1; // 准备下一轮测量
                                    high_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
                                        
                                    //计算频率
                                    TIM3CH1_Freq = (float)72000000 / 72 / (high_val+1);
                                    //计算占空比
                                    TIM3CH1_Duty = (float)(low_val+1) / (high_val+1);
                                    capture_end_flag = 1;
                            }
                    }
            }
    }
}	

五、注意

  • 中断处理器中,数字越小,优先级越高
  • 检查引脚是不是插错了, 还真插错了
  • 调示波器的输入电压,要输入 High Level 3V, Low Level 0V
  • 有的时候 OLED 会短暂误码。等一会,多按几次 reset,再烧录几次
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号