0%

Design an Arbitrary Waveform Generator Using the RP2040 MCU and a Digital-to-Analog Converter

    标题是AI写的,本来我想写的是用RP2040实现AWG ,AI说我这个标题不够专业,给我改了一大串,我感觉确实挺🐂🍺,就直接贴上来了。

为什么要写这个

网上有一堆RP2040实现的AWG的设计,其中有一个传播比较广泛的是一个用python写的配合一个10bit R2R DAC实现的AWG设计。然而,我认为它有错误:基本上所有的帖子认为连续的DMA传输直接使用例程中给出的控制传输的方法就可以了,然而这种传输方法会损失一个时钟周期用来搬运DMA配置。这意味着信号周期没有被严格控制。对于主频轻轻松松就可以达到270MHz的RP2040来说这个Bug很难看出来,但是如果生成信号波形周期较短就可以看到。B站有一个对于原开源项目的复刻,在输出高频的时候就能看出来了。

这个复刻的视频不够详细,后面我会给出具体测试结果。

不知道为什么RP2040作为树莓派一个很不错的产品,有相当多的讨论和开源环境,但是有些教程却始终是抄来抄去,甚至英文环境也是,可能确实是没啥人用这个做产品就是这样吧。。。包括下载配置,有更好的方法,但是容易找到的教程都是最开始手册上给出的方法。

一个原因是手册上没有直接给出DMA乒乓传输的例子和说明,而是通过一个称作“控制传输(2.5.6.2. DMA Control Blocks .RP2040-Datasheet)” 来说明如何连续传输数据到外设或者指定地址。我在反复怀疑自己了几天之后,决定直接写代码验证一下。

Talk is cheap. Show me the code

    我最开始不甚了解乒乓传输这个概念,说来惭愧,写了几年单片机,就用过一次DMA, 最后还因为操作逻辑不好处理舍弃了,其他时候要么是用垃圾单片机压根没有DMA,要么是没这需求。这里还是第一次正儿八经看看DMA怎么做。

代码验证想法是正确的,分别验证了原来的控制传输确实会出错,测试了信号波形,以及验证了使用PingPong传输能得到想要的结果。

手册中给出的例子确实实现了连续传输不需要CPU介入,但是它从来没说过时序是严格的,单独为DMA循环传输做了功能的有STM32,配置循环就会自动从地址段环回取数据。RP2040的DMA IP核似乎是买的公版IP,不过用下来还是比较好用的。

下面正文里面详细说设计和测试。

RP2040 DMA

DMA,顾名思义,直接内存访问,无需使用CPU搬运数据。

有一个触发其他通道的概念比较有意思,可以配置为每个通道传输结束后会自动触发另外一个DMA通道启动,很明显,这样就可以实现一个PingPong传输了,甚至可以多个通道接力最后转回来。遗憾的是它并不能自己触发自己,所以实现连续传输至少需要两个DMA通道.

由于没有自动的循环模式,想要严格控制传输时序,就需要DMA通道在下一次传输前准备好,

由于DMA通道配置的传输地址并不会自己回到最初的地址,因此每次传输结束后至少要重新配置传输起始地址才能在下一次传输中传输正确的数据。因此,这种方法保证了时间间隔的严格,但是作为牺牲是CPU必然要耗费一定时间参与传输任务。这可能对于其他任务是有影响的。

然而RP2040是双核的,实在优化不出来完全可以扔到另一个核心跑(

R2R DAC

为什么使用这个DAC? 由于是电阻结构所以很容易做而且能达到不错的输出速度。当然了很多成品并行DAC也是使用的R2R结构,而且拆机件也不贵,这里首选选用手工使用电阻搭建这个DAC,为了好玩,其后再测试成品集成芯片。

关于DAC,可以看我这篇博客:(36条消息) 关于DAC的原理_dac工作原理_你要写卓的博客-CSDN博客(TODO:改天找到原文迁移到自己的博客上)

硬件设计

其实最开始的测试版本充其量只能叫做硬件连接不能叫做硬件设计,因为测试过程中只是用到了一个开发板连接了一堆电阻而已。