一、项目介绍
DDS任意波形发生器/本地控制
任务要求:
1、通过板上的高速DAC(10bits/最高125Msps)配合FPGA内部DDS的逻辑(最高48Msps),生成波形可调(正弦波、三角波、方波)、频率可调(DC-)、幅度可调的波形
2、生成模拟信号的频率范围为DC-5MHz,调节精度为1Hz
3、生成模拟信号的幅度为最大1Vpp,调节范围为0.1V-1V
4、在OLED上显示当前波形的形状、波形的频率以及幅度
5、利用板上旋转编码器和按键能够对波形进行切换、进行参数调节
二、设计思路:
1、先简单解释一下DDS的原理,DDS是一种全新的频率合成方法从相位概念出发直接合成所需波形的一种频率合成技术,通过控制相位的变化速度,直接产生各种不同频率、不同波形信号的一种频率合成方法。DDS系统主要由相位累加器、波形存储器、数模(D/A)转换器和低通滤波器等四个大的结构组成,然后在这个板子上面,主要是通过FPGA来做相位累计和波形存储,然后以后续的DAC模块来负责后两个结构。
2、然后解释一下本次项目中spi的部分,SPI主要是用于stm32对fpga和oled的数据传输,spi主要由四个部分组成,SS、SCK、MOSI、MISO,通过STM32的SPI外设,实现了数据传输,详细的SPI原理不过多赘述。
3、项目设计思路比较简单,主要是通过FPGA来操作,根据dds的原理,fpga需要做的其实只是将确定逻辑的高低电平以一定的频率进行输出即可。我们需要的只是一个存储这些高低信号的模块,以及确定读取他们的频率。在输出端,我们通过DAC电路,即可得到一个较为理想的输出模拟信号。
4、然后是控制端,控制端采用的是旋转编码器和按键来控制,然后使用的是SPI协议,让stm32控制oled,做一个ui交互,然后直接通过按键和旋转编码器控制,让stm32同时向fpga和oled传输数据。
三、系统框图和流程图:
1、fpga顶层文件,调用多个子文件,实现与stm32的互通,以及与高速DAC的模拟信号输出
2、stm32通过spi协议,实现与oled的显示和ui交互界面,以及与fpga的数据传输
3、通过编码器和按键,对stm32传输数据
四、简单的硬件介绍:
1、电赛训练板的扩展板
2、单通道10位的高速DAC模块
3、ssd1306的一个oled显示屏
4、基于stm32g301和ice40up5k的核心板主控
5、旋转编码器和两个按键用于控制
6、还有一个口袋仪器用于显示波形,以及实验室的示波器
五、实现的功能及图片展示:
1、100khz的1v正弦波
2、三种可调波形(在1khz时的图)
方波1khz,正弦波1khz,三角波1khz
3、频率范围为DC到5Mhz
图为2Mhz的和1Mhz的和200khz的以及20khz的(高频展示,因为口袋仪器性能有限)
200khz
1Mhz三角波
2Mhz三角波
20khz
4、幅值为0V到1V可调,且0.001v可调
(因为这个口袋仪器自带400-450mv的抬升,所以测试时实际电压都是基于这个值往上加的,但是实测数值都是正确的,下图分别为100mv,500mv和未输入)
5、频率精度可以为1hz
(如图,18967和18968hz的调节)
六、主要代码片段及说明
篇幅有限,详细内容见文件。
1、锁相环部分
pll_120M pll_120M_m1 (
.ref_clk_i(clk),
.RST_i(RST),
.outcore_o(dac_clk),
.outglobal_o()
);
2、SPI的一部分
SPI_TX SPI_TX_m1
(
.clk(clk),
.RST(RST),
.spi_cs(spi_cs),
.spi_sck(spi_sck),
.spi_miso(spi_miso),
.enable_TX(1'b1),
.data_TX(Freq[34:27]),
.signal_TX(signal_TX),
.CNT_TX(CNT_TX),
.state_TX(state_TX)
);
3、u8g2的UI交互代码
void SEL(uint8_t State,uint8_t Wave_st,uint8_t Fre_st,uint8_t V_st)
{
{
if(State == 0)
{
u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);
SEL_WAVE(Wave_st);
Draw_Fre(Fre_st);
Draw_Vpp(V_st);
Draw_On(On_st);
}
else if(State == 1)
{
u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);
Draw_Wave();
SEL_FRE(Fre_st);
Draw_Vpp(V_st);
Draw_On(On_st);
}
else
{
u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr);
Draw_Wave();
Draw_Fre(Fre_st);
SEL_VPP(V_st);
Draw_On(On_st);
}
}
}
七、遇到的主要难题及解决方法
1、本次项目的第一个难题即为u8g2库驱动oled的使用,本人平时是完全没接触过这个库的,平时也不会经常使用oled屏幕,对这个库的熟练度不够,导致了在调试的时候出现了很多问题,同时在参考了很多篇文章后,还是得到了解决办法,通过在显示部分添加延时的显示,来测试代码运行时,按键和编码器的交互是否与oled的显示同步。
2、第二个问题在于DDS的配置,在参考硬核官网的文献的时候,因为题目要求是5Mhz,所以在使用时需要一个外部120M的锁相环部分,然后因为调用的时候在频率的配置配错了(数字打错了,然后还一直没发现,大家不要学我),然后导致后续改代码的时候一直出现问题,最终去咨询大佬之后才发现了自己的问题。
3、第三个问题在于DDS的原理的不了解,使用FPGA来进行操作还是有一定难度的,这部分我参考了往届的很多栏目,以及官方中的那篇文档,根据文档一步一步调试,从输出一些简单的波形,到自己调整频率等参数,这是一个需要循序渐进不断测试的过程。
八、未来的计划或建议
该项目已经实现了基本上的DDS的输出波形功能,达到了预期指标,但是仍有很多细节部分可以提升
1、首先是oled的刷新率很低,本人对oled的使用并不熟练,所以使用这个的时候我没有去增加提高刷新率的功能,这会使得显示部分的效果较差,同时项目展示的时候效果也不是很好。
2、主控芯片资源比较有效,理论上来说可以更换更好的芯片,其实也不一定要用stm32来对oled和按键进行控制,但是因为板子的设计,所以还是使用了stm32来进行了一部分控制,我觉得可以只使用FPGA来进行设计,这样子资源利用也足够。
3、DAC模块的输出有限,只能单通道输出,当然实际情况下可以使用功能更加强大的DAC去实现更多的功能。
九、因为文件大,上传百度网盘链接
只提供了axf和rbt和hex文件,还有fpga代码,stm32因为内存大,放到网盘了
链接:https://pan.baidu.com/s/17gpD_vj1tTtN-CuMzoT2fA?pwd=6666
提取码:6666