暑期一起练-2-基于STM32F072的简易信号发生器和可编程脉冲发生器
本项目是基于STM32F072的简易信号发生器和可编程脉冲发生器,利用stm32cubeide一站式编程,实现多种可调波形和PWM波的可视化生成。
标签
嵌入式系统
STM32
信号发生器
唉可悲
更新2021-09-05
1937

   1.项目需求

   本项目制作的是暑期一起练中基于STM32F072的多功能掌中仪器的项目2,项目要求如下:

  1. 通过STM32F072的DAC产生正弦波、三角波等常用波形,输出到Wav管脚;
  2. 通过STM32F072的内部定时器产生可调周期、可调占空比的PWM信号,输出到PWM管脚;
  3. 可以通过按键改变Wav信号的波形、频率、幅度、直流偏移,改变PWM信号的频率和占空比;
  4. 在LCD上显示波形信息以及当前的参数、控制菜单。

  2.完成的功能及性能

  1. 能够产生正弦波,锯齿波,三角波,方波四种基本波形,波形可调频率,最大值和最小值;
  2. 能够产生可调周期,占空比的PWM波;
  3. 基本波形根据产生精度不同,生成波形最大频率最高可以达到12Khz,PWM波最大频率可以达到60KHz;
  4. 生成波形最大值和最小值范围在-3.6V-3.6V之间;
  5. 能够通过屏幕和按键修改参数。

  3.未实现功能或计划实现功能

  1. 利用USB HID进行上位机通信,实现上位机控制。

  4.主要实现思路

   stm32f072内部自带有经过校准的晶振,可以用作时钟源,频率为48Mhz,实际误差在5%左右,有可能会影响定时器计数稳定性,从而导致生成频率出现误差。内部集成DAC和PWM生成器,能够直接生成PWM波和绘制波形。绘制波形目前查阅的资料来看,只有描点方法,描点方式的精度取决于描点数量,根据试验,在256个点的情况下,DAC能够输出较为理想的波形,虽然还存在一些毛刺,但相对而言可以忽略,增加更多的点也能继续提高精度,但是根据STM32官方文档显示DAC最大转换效率为1Mhz(实际可能会大于这个值,这个值是保守值),因此过多点会导致最高频率有所降低。最终决定根据精度不同需求设定多种不同点,满足不同频率需求。

   DAC转换需要不停往寄存器送入值,这个过程占用CPU很大,stm32f072内部集成DMA通道,DMA(Direct Memory Access,直接储存器访问) 允许不同速度的硬件装置来沟通,而不需要依赖于CPU的大量中断负载,通过DMA将值给DAC,实现无缝转换,转换周期有定时器作为触发任务,通过修改定时器实现对频率的修改。PWM生成采用内部定时器生成PWM,通过修改定时器调整频率和占空比。屏幕和按键作为人机交互。

   5.主要实现步骤说明

   1.STM32Cube配置引脚和功能

   在stm32cubeide中新建项目,创建后进入引脚和功能配置界面,如下图

FryTvMh2C7anI2549LNXWxK7dLlw

   主要配置DAC、SPI、定时器,I2C为储存器引脚,由于本硬件暂时没用可以不进行配置。SPI也可以采用软件模拟SPI,移植性更高,但是性能弱,为了驱动屏幕,建议采用硬件SPI,DAC需要配置DMA通道,如下图:

Fkcy3HnvsSsgKq9CNAVN11heaXqV

   主要注意memory的值为half word,因为DAC为12位,实际数组使用是16位int类型,half word一次可以发送一个数字。DAC配置如下:

FluDzWSyAj4KwN0AHPBmiYtTS2ER

   需要开启Output buffer,开启后副作用是电压不能到0v,最小输出理论值为0.2v左右,但是开启后输出能力会增加,在本项目硬件中不开启的话,经过运算放大器输出只有800mv左右,排查了很久才发现这个问题,推断是不开启无法推动运放。

   其他按键引脚配置成为输入,根据电路图配置下拉即可,时钟配置如下图:

   FnQi-3LBAZbowYV9hOdXTdQ9K26j

   接着生成代码即可,代码框架如下图

   Fs_hC7Aa0qZgQTP34y8O5XCWlrBr

   其中core为用户程序,功能部分需要自己编写

   2.功能实现-波形生成

   波形生成首先定义了有个结构体存储波形的相关数据

typedef struct WaveData{
    uint16_t codenum; //描点数量
    uint8_t codenumLevel;//精度等级,高中低分别对应描点数量256 128 60
    uint16_t Codetable12bit[256];           //描点表
    uint16_t frequency;     //频率
    uint8_t frequencyLevel; //频率等级,实际频率=frequency*10^frequencyLevel
    uint8_t maxValue;   //最大值
    uint8_t minValue;   //最小值
} _WaveData;

   其中最大值和最小值理论上为4和-4,但是为了方便储存和为后期AT24C02储存做准备,这里存储采用0-80值进行储存,在程序里进行换算。为了实现修改频率,需要修改定时器值,定时器频率为48Mhz,定时器值计算公式如下,x为所需频率

(uint32_t)(48000000/sizeof(Sine12bit)/x) -1

   生成波形较为简单,正弦波采用sin函数生成即可,其他采用直线函数生成,需要将最大值和最小值进行换算,stm32 DAC最大值为3.3v,精度为12位,为了实现更高的输出范围,本项目硬件使用了运算放大器,但是运算放大器的接法没能查到类似的,不知道怎么计算(模电数电学的不好),因此只能利用下电路仿真软件看下输入输出的关系了,本来准备采用电子森林的电路仿真软件,但是操作有点复杂,有些地方不知道怎么用,最终还是使用了multisim在线版,注册NI账户就能用,仿真电路图如下图所示:

Fic4VytRd8yXoR3az9CSlYfsPesE

   V4为阶跃信号,从0-3.3v,仿真结果如图

FqVFXdHQ77sC44NDyD3Vuf0UkAxz

   能够看到随着电压输入增加,输出电压降低,理论上0v输入4v输出,3.3v输入-4v输出,且呈线性关系,因此可以使用函数进行换算。换算方法首先将最大值最小值换算到0-3.3,再进行反比例换算,最后乘以4096/3.3的值即可。

   3.功能实现-按键

   由于按键抖动存在,需要对按键进行消抖,常用有延时消抖,但是会占用cpu,不合适,本文参考其他大佬文章,采用状态机方式进行消抖,还可以判断长按,首先建立一个结构体

typedef struct
{
    uint8_t KeyLogic;
    uint8_t KeyPhysic;
    uint16_t KeyONCounts;
    uint8_t KeyOFFCounts;
    uint8_t KeyIsDeal;
}KEY_TypeDef;

#define     KEY_OFF         0
#define     KEY_ON          1
#define     KEY_HOLD        2
#define     KEY_IDLE        3
#define     KEY_ERROR       10

 来源https://blog.csdn.net/m0_46704668/article/details/113360878

   之后在中断里进行按键扫描,更像Physic也就是物理状态,物理状态累加到一定值后改变Logic也就是逻辑状态,相比原文章增加了Isdeal即按键是否处理,避免扫描太快,而按键对应函数还没有处理。程序根据Logic状态进行处理。按键1用于切换主界面,按键2用于切换次级选择,拨码按键用于改变数据。

   4.功能实现-菜单

   菜单也采用状态机方式实现,然后在主循环中调用,更新界面,创建结构体如下:

typedef struct MenuSwitch{
    uint8_t menuchangeFlag;  //菜单是否需要切换
    uint8_t mainSwitchNum;   //主菜单选择号
    uint8_t secondarySwitchNum;  //次级菜单选择号
}_MenuSwitch;

   之后根据按键和菜单选择进行不同功能响应,改变值之后再更新界面,界面和按键处理分开,方便后期进行添加。

   6.遇到的问题

   在制作过程中,遇到很多问题,有些令人摸不着头脑,有些现在也悬而未决。

  1. LCD屏幕移植的是中景园的程序,最开始移植是微雪程序,但是微雪程序屏幕反向不对,且显示有点不正常,不知道为什么。移植后能正常显示,也可以实现功能,但是,但是!屏幕在下载程序后一段时间可以用,放置一段时间后就不能用了,最开始我以为程序有问题,但是实际上能看到波形,证明程序是运行了,但是频率没有反应,只能在下载程序的那段时间能正常运行,最开始怀疑是程序初始化问题,但是修改了5 6种网上找的初始化方式都是同样问题,但是官方程序没有问题,到时候参考下;
  2. 中景园和微雪程序显示中文都是采用获取中文GBK编码,但是,但是,和keil5不同,STM32cubeide默认为utf8编码,gbk直接乱码,改了默认编码后屏幕能显示中文,但是导致很多注释全部乱码且不能恢复,因此源文件可能会有些乱码注释,不过大部分变量函数取名我尽量按用途和规范来取,看懂问题应该不大,实在太多地方不想修改了;
  3. 还有不开启output buffer无法正常输出电压问题也困扰了很久,一直以为程序错了,看了官方的也是开了buffer,一改程序果然就正常了。

   7.总结

   这次活动拓展了我的知识储备,全方面锻炼了我的能力。很感谢硬禾学堂提供的这个平台和机会,只有实践才能促进进步,只有实践才能发现问题并解决问题!

   8.实物图片

Fu67FZgtF7O6GKylZagVtoP5ir_MFrmj16e_zpexzv8cXhs5i5ZsDI2tFpYB5IWRirms-Gnn1jIhgDt0dwQi

附件下载
Arbitrary_waveform_generator.7z
程序,可以使用stm32cubeide导入
Arbitrary_waveform_generator.hex
hex文件,可以直接下载进去
团队介绍
中国民用航空飞行学院
团队成员
唉可悲
电子爱好者
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号