找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

465

积分

0

好友

57

主题
发表于 9 小时前 | 查看: 1| 回复: 0

本项目基于开发板上的PWM模块和低通滤波(LPF)电路实现信号发生功能,能够生成频率0-100KHz、偏置1.5V、幅度0-1.5V的正弦波、三角波和方波信号。

实现的功能

系统可输出正弦波、方波和三角波,频率调节范围为0至100kHz,步进为1kHz;幅度调节范围为0至1500mV,步进为150mV。所有参数可通过按键交互调整并在屏幕上实时显示。

设计思路

由于开发板未集成数模转换器(DAC),因此选择PWM配合滤波电路来实现模拟电压的输出。受限于低通滤波器的特性,PWM的基础频率不能过低。本设计采用查表法来生成三种波形,并通过DMA循环地将波形数据数组传输给PWM比较寄存器。

频率的调节是通过在查表时“跳跃式”读取数据点来实现的,而幅度的调节则是对整个数据表乘以一个比例系数。

硬件介绍与流程图

硬件部分主要利用了板载的二阶低通滤波电路(附带一个电压跟随器)、几个功能按键以及OLED屏幕。读者可以根据电路参数自行计算该滤波器的截止频率。

STM32G031开发板二阶低通滤波电路原理图

整个系统的工作流程如下图所示,从上电初始化开始,通过按键操作循环调整波形参数并刷新显示。

基于PWM的信号发生器系统工作流程图

代码

以下是处理按键输入并更新波形参数的核心代码片段(输入捕获逻辑):

HAL_TIM_Base_Start_IT(&htim2);
    b_last=HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15);
while(flag_tim2<=20){
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)!=b_last){
    HAL_TIM_Base_Stop_IT(&htim2);
            flag_tim2=0;
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)==1){
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_14);
                          HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_3);
switch(pat){
case 0:
                                    fv=fv+1;
if(fv==10)fv=0;
break;
case 1:
                                  fre=fre+1;
                                  if(fre==101)fre=1;
break;
case 2:
                                mode=mode+1;
if(mode==3)mode=0;
break;
                            }
    OLED_Clear();
switch(mode){
                                case 0:
    OLED_ShowString(10, 0, "Square    ", 8, 1);
break;
case 1:
    OLED_ShowString(10, 0, "sine      ", 8, 1);
break;
case 2:
    OLED_ShowString(10, 0, "Triangular", 8, 1);
break;
                                }
    sprintf((char*)Vpp,"%d  ",1500-fv*150);
                            OLED_ShowString(42, 10, Vpp, 8, 1);
    sprintf((char*)FV,"%d    ",fre);
    OLED_ShowString(30, 20, FV, 8, 1);
    OLED_Menu();
    OLED_Refresh();
                         buff_try();
                         HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_3, (uint32_t*)buff_value, j);
break;
            }
else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)==0){
break;
            }
break;
        }
    }
    HAL_TIM_Base_Stop_IT(&htim2);
    flag_tim2=0;

效果展示

下图展示了系统实际运行时的效果,使用STM32G031开发板产生信号,并通过示波器观测生成的波形。

STM32信号发生器实物运行与示波器波形显示

遇到的困难

在项目实现过程中遇到了不少挑战。由于相关知识储备不足,大部分问题都依赖于网络搜索解决。

  1. 基础环境搭建:第一个难关是点亮LED,花费了两天时间,最终在社区交流中发现是编译器版本兼容性问题。
  2. 波形生成算法:最初尝试通过定时器动态改变PWM占空比来生成正弦波,但这种方法只能产生极低频率的波形。随后转向了解DDS(直接数字频率合成)原理,但关于用PWM模拟DDS的资料较少。主要思路是查表法(也可实时计算,精度更高,但因不熟悉SPWM公式而放弃),通过改变查表步进来调节频率。然而,当目标频率较高且不能被基准频率整除时,会出现精度问题。后续改进为不改变DMA传输数组大小,通过循环读表来填满缓冲区,结合定时器调整理论上可实现更低频率的输出。
  3. 幅度调节精度:通过乘以一个系数来调节幅度,将小数转换为整数时精度损失较大。曾考虑实时计算,但受限于公式理解,最终选择用SPWM软件预生成10个不同幅度的波形表。三角波表为手动生成,直接使用了乘系数的方法,牺牲了一定的精度。
  4. 编码器读数:采用下降沿捕获A相变化并判断B相电平的方式判断方向,但正反转经常误判,最终简化为只支持单向调节。
  5. 屏幕驱动:OLED屏幕的驱动是耗时最长的部分,相关教学资源相对较少,仅点亮屏幕就花费了一天时间,反复观看教学直播才勉强攻克。

心得体会

这次项目对我个人而言是一个不小的挑战,相当于在相关知识几乎为零的基础上起步。从最初的无从下手,到通过听课、搜索资料、选择性学习,最终拼凑完成了这个设计。非常感谢技术交流群里朋友们的答疑以及平台提供的支持。

经过这次实践,我不仅学习了STM32、PWM、DMA等嵌入式开发的相关知识,更重要的是养成了持续学习和解决问题的习惯。如果你也打算开始动手做项目,很多时候阻碍你的可能不是代码本身,而是手边没有合适的板卡和模块来反复验证想法

我本次项目使用的硬件平台是“基于STM32的简易信号发生器与示波器”学习套件,这让我少走了很多弯路。如果你想系统地跟随项目实践,打好硬件基础至关重要。同时,在探索信号与系统、电路设计等更深层的原理时,有一个可以随时交流讨论的社区环境会事半功倍。欢迎到云栈社区与更多开发者一起学习成长。




上一篇:JWT安全与API认证避坑指南:双Token策略与纵深防御详解
下一篇:AI服务器vs通用服务器:架构设计差异全解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-18 18:14 , Processed in 0.454454 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表