2021暑假一起练——用STM32F072CBT6做了简易波形发生器
本项目完成的是本次暑期一起练项目的任务二,通过STM32F072实现简易的波形发生功能
标签
嵌入式系统
STM32
波形发生器
喻家山不相信野猪
更新2021-09-11
1914

内容介绍

FnDVRJ0aqJm9ajAraLRSOsYn9rtl

硬件介绍:基于STM32F072微控制器,支持双通道示波器、单通道波形发生器、单通道脉冲发生器、双路可调直流电压源,240*240 LCD显示,2个按键和一个拨轮开关

项目简介:本项目制作的是本次暑期一起练中基于STM32F072的多功能掌中仪器的任务二,以下是具体项目要求:

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

本次实现的功能:

  1. 通过DAC产生三角波,矩形波,正弦波,输出到Wav管脚
  2. 通过TIM2产生PWM信号,输出到PWM管脚
  3. 通过按键改变Wav信号的波形、频率、幅度、直流偏移,改变PWM信号的频率和占空比
  4. 在LCD上显示波形信息以及当前的参数、控制菜单

 

本来我打算完成任务一——制作一个简易的示波器,但是感觉波形的实时刷新不太好处理,于是转而选择了任务二——制作简易的波形发生器,项目基于ST官方提供的固件库进行开发,项目主体可分为以下几部分:

一:点亮屏幕

一开始,我通过几天的琢磨,还是没有成功把屏幕点亮。于是选择移植了中景园电子的屏幕驱动代码。但是由于它采用的是软件模拟的SPI并且没有使用DMA,这导致整个屏幕的刷新速度很慢,同时还会占用CPU,于是我配置了硬件SPI,并且通过使能DMA来改写了部分画图函数。通过观察电子森林提供的电路图并查阅STM32F072CB的数据手册,我发现在硬件上,本次选用的并不是默认的SPI引脚而是PB3和PB5,需要额外开启PB3和PB5的重映射功能。

GPIO_PinAFConfig(GPIOB,3,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,5,GPIO_AF_0);

根据本仪器的电路图,我们可以知道SPI需要配置成主设备单向传输模式,其他的配置都挺正常的。

部分SPI的配置如下:

SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4;
SPI_InitStruct.SPI_CPHA=SPI_CPHA_2Edge;
SPI_InitStruct.SPI_CPOL=SPI_CPOL_High;
SPI_InitStruct.SPI_CRCPolynomial=7;
SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b;
SPI_InitStruct.SPI_Direction=SPI_Direction_1Line_Tx;
SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;
SPI_InitStruct.SPI_Mode=SPI_Mode_Master;
SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;

 

二:波形输出

首先需要配置好DAC通道,根据电路图可知,Wav管脚连接的PA4引脚是DAC_Channel_1,接下来就是配置PA4和DAC,需要注意的就是PA4需要配置成模拟输入,一但使能 DACx通道之后,相应的 GPIO 引脚会自动与 DAC 的模拟输出相连,设置为输入,是为了避免额外的干扰。

在配置DAC的时候需要使能OutputBuffer,否则输出的波形不太正确,并且需要配置成定时器触发DAC,这样就可以通过修改定时器的参数来达到改变波形频率的目的,本次我采用的是TIM3。

DAC部分配置如下:

DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;
DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Enable;
DAC_InitStruct.DAC_Trigger=DAC_Trigger_T3_TRGO;
DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None;

配置完DAC之后就需要着手于波形的生成,我首先创建了三个长度为240的数组wav0[240],wav1[240],wav2[240]来分别存储三角波,矩形波,正弦波的基础波形,它们的幅值和直流偏移都是1.65V和1.65V,再创建一个数组wav_out[240]来存储真正需要输出的波形,将基础波形根据输出波形的幅值,直流偏移进行转化后存入wav_out[240]。

根据电路图可知输出到PWM_WAV管脚的电压U1和输出到WAV管脚的电压U2大致有如下关系:

U1 = 4V-3.3*U2,

通过以下公式转化后就可以输出符合要求的波形了:

wav_out[i]=wav0[i]*amp[amp_mode]/4.0+2048-512*DC[DC_mode]-512*amp[amp_mode];

其中,amp[amp_mode]和DC[DC_mode]分别表示需要输出波形的幅值和直流偏移。

在成功得到需要输出的波形后,就需要配置DAC+DMA,以此加快数据传输的速度,并且不占用CPU。

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&DAC->DHR12R1;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)wav_out;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 240;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

在DMA中需要注意的是SPI和DAC1都使用的是DMA1_Channel3,所以在每次使用完DMA+SPI后都要重新初始化DMA+DAC。

三:按键的功能

首先是配置按键的外部中断,在配置引脚的时候,需要注意PF0和PF1默认使用的是外部时钟,根据项目要求,需要调用以下代码来让他们使用内部时钟。

RCC->CR &= ~((uint32_t)RCC_CR_HSEON);

配置外部中断的时候需要让不同的外部中断有不同的中断优先级,以防中断产生冲突。

我定义了三个变量:mode,mode1_1,mode2_1。

mode=0表示处于波形发生模式,mode=1表示处于PWM波生成模式;

mode1_1 = 0表示处于波形选择状态,mode1_1 = 1表示处于幅值修改状态,mode1_1 = 2表示处于频率修改状态,mode1_1 = 3表示处于直流偏移修改状态。

mode2_1 = 0无法修改任何变量,mode2_1 = 1表示处于修改PWM波的频率状态,mode2_1 = 2表示处于修改PWM波占空比修改状态。

在中断回调函数中,首先延时10 ms,以此按键消抖,然后添加修改屏幕显示内容的代码,显示正在修改的内容。

对于波形的修改,我定义了一个变量wav_change = 0,如果我通过按键修改了波形的种类,幅值或直流偏移,就在中断中把wav_change置为1,在主函数的while循环中,如果发现wav_change == 1,就重新对wav_out[240]赋值,然后再将wav_change重新置为0,并且让wav_change 重新输出。

四:界面设计

根据官方所给的例程进行设计,大部分的按键功能和显示内容都与其保持一致。

在波形发生器界面,第一排显示三种可供选择的波形,第二排显示当前的幅值0~4V,第三排显示当前的频率1~10kHz,第四排显示当前的直流偏移-4~4V;在PWM波界面,第一排显示可视化的波形,第二排显示频率10~100kHz,第三排显示占空比10%~90%。

FgypF5N2Brsa0jgB9IsuLY6bk9Wn

Fs6SEvDr4hr2MAaLxFsF8MeulBio

五:PWM波的生成

根据所给的电路图可知,PWM波由PB10引脚输出,而PB10正好对应的是TIM2_CH3,在配置引脚的时候需要开启PB10的重映射功能,定时器输出比较需要配置成PWM模式一和极性为高,或者PWM模式二和极性为低。部分定时器的配置如下:

TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	
TIM_OC3Init(TIM2,&TIM_OCInitStruct);
	
TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);

通过调用

TIM_SetCompare3(TIM2,(duty_cycle/10));

来达到修改占空比的目的。

对于PWM波频率和占空比的修改都在中断回调函数中进行,前面已经写到了。

遇到的问题

在通过SPI+DMA向LCD屏发送数据时可能会出现数据不准确的情况

Wav管脚输出的电压最大只能达到3.6V

 

总结:

本次制作波形发生器的项目总体来说还是挺有意义的,不仅让我了解了STM32F072CBT6的DMA,SPI,DAC等功能,还让我学会如何进行这些功能的配置。一开始是跟着正点原子的视频学习STM32F1系列各种功能的基本配置,然后把它移植到STM32F0上面,如果有一些代码上的差异就会去看固件库中提供的例子或者上网查一下有没有STM32F0相关功能的例子。同时这也是我第一次做出一个有完整功能的仪器,很感谢硬禾学堂给我们提供了这次实践的机会,希望硬禾学堂能够越办越好!

 

附件下载

DAC.hex
可直接下载验证的.hex文件
DAC.zip
整个工程文件的压缩包

团队介绍

华中科技大学
团队成员
王世康
华中科技大学

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号