是否可以在 STM32F3 上使用 DMA 通过 SPI 传输无限数据?
Posted
技术标签:
【中文标题】是否可以在 STM32F3 上使用 DMA 通过 SPI 传输无限数据?【英文标题】:Is there possible to stream infinte data over SPI using DMA on STM32F3? 【发布时间】:2020-04-11 07:37:54 【问题描述】:我正在开发一种基于新协议的 RF 调制解调器,该协议具有在一帧中流式传输 96 字节的功能 - 但它们会在通信结束之前不断发送。我计划在 STM32 中使用两个 96 字节缓冲区 - 在接下来的几行中,我将解释原因。
我想通过 USB-CDC 将前 96 字节帧发送到 STM32 - 然后外部调制解调器芯片将生成“9600bps”时钟,STM 将不得不在指定的输出引脚上逐位写入有效负载(在每个时钟脉冲)。 当 STM32 注意到它已经发送了一半的 96 字节帧 - 它向 PC 发送通知以发送更多数据时 - PC 将立即通过 USB-CDC 重新填充第二个 96 字节缓冲区。当 STM32 将结束发送第一个缓冲区时 - 立即开始发送第二个缓冲区内容。当它将发送第二个缓冲区的一半时 - 如前所述,它将向 PC 请求另一个 96Byte 帧。 一直这样,在 PC 发送命令停止 tx 之前。
这种传输模式 - 串行,使用“触发时钟”。 这是否可以使用 DMA,我该如何设置? 我想使用 DMA 来使用 USB,同时已经将数据流式传输到无线电调制解调器芯片。这是正确的方法吗?
我正在构建一个具有数据包和流功能以及数字语音的开源无线电通信系统项目。我正在为 PC 无线电调制解调器设计和电子产品。项目名为 M17,由 Wojtek SP5WWP 维护。
【问题讨论】:
【参考方案1】:回复。一般架构。 USB ACM 上的串行通信不必使用相同大小的缓冲区,也不必与 SPI 上的下游通信同步。您可以使用尽可能大的缓冲区,以便 PC 可以提前发送数据。如果 PC 提供数据的速度不够快,这将减少缓冲区下溢的机会。使用循环缓冲区并在数据包从 USB 到达时填充它。
DMA 是正确的方法。尽管人们常说 DMA 仅用于高带宽操作,但实际上使用 DMA 可能比处理每个字节的中断更容易,即使您每秒只处理 9600 位。
STM32F3 中的 DMA 控制器有一个半传输完成(DMA_ISR 中的 HTIF)位,您可以轮询或使其生成和中断。结合传输完成状态 (TCIF) 和循环位(DMA_CCR 中的 CIRC),您可以组织双缓冲数据管道,以便传输可以与 MCU 正在执行的任何其他操作重叠。应用程序将在 HTIF 事件上重新加载 DMA 缓冲区的前半部分。当 TCIF 事件发生时,它会重新加载后半部分。它必须尽快完成,在另一半完成之前。但是,只有当您需要持续传输数据时才需要双缓冲管道,即总量大于 DMA 缓冲区的大小。 停止循环 DMA 可能很棘手。我想 STM32 和外部芯片都知道要发送多少字节。在这种情况下,在收到此金额后,禁用 DMA。
看来STM32需要一个slave SPI,因为外部芯片会产生SPI时钟。
DMA 设置起来并不难,但是,它需要多个东西才能正常工作。我假设寄存器级编程,如果您使用某种框架,您需要了解它是如何实现这些功能的。启用 SPI 时钟、SPI 引脚的 GPIO 端口和 DMA,将引脚配置为 AF。为 SPI 外设找到正确的 DMA 通道。在 SPI DMA 的情况下,您通常需要两个通道:TX 和 RX,但对于从 SPI,您可能只需要一个。配置 SPI,注意时钟极性和相位,设置为每个 TX 和/或 RX 产生一个 DMA 请求。将 DMA CPAR 通道寄存器设置为指向通道中的 SPI DR 寄存器,并对所有其他 DMA 通道寄存器进行适当的编程。启用 DMA 通道。在从机模式下启用 SPI。当 SPI 主机在 MOSI/SCK 引脚上计时数据时,DMA 控制器会将它们放入内存中。当缓冲区半满和满时,通道将设置 HTIF 和 TCIF 位并生成和中断,如果你告诉它。使用这些事件来实现流控制。
【讨论】:
非常感谢您的回答!我可以在我的 STM32 中设置 SPI 从机,并在没有 CS 信号的情况下使用它吗?无线电调制解调器芯片不提供它。 STM32 不需要 CS 信号。其实我不知道怎么处理从机模式下的CS信号呢。使用 SPI 可能很棘手,首先尝试在从机模式下接收 DR 中的单个字节,没有 DMA 等。您只需要一个切换 SCK 即可。然后,添加其他东西并组织管道。考虑流量控制和错误条件。 "当缓冲区半满和满时,如果你告诉它,通道将设置 HTIF 和 TCIF 位并生成和中断。使用这些事件来实现流控制。" - 所以在通过SPI从buffer1发送所有内容(标志TCIF打开)之后,我是否必须停止DMA,用buffer2覆盖buffer1,然后将其转回?你觉得它够快吗? 使用 DMA 是一个可以解决的技术问题。但是,您需要首先考虑流量控制。如果调制解调器预先知道字节数并期望所有这些字节都可用,那么在您将所有内容缓冲到 RAM 之前,您不能告诉它开始传输,因为您无法期望 PC 及时发送所有内容。如果在传输过程中,您可以向调制解调器发出没有更多数据可用的信号,因此它可以暂停,然后循环 DMA 可以工作。以上是关于是否可以在 STM32F3 上使用 DMA 通过 SPI 传输无限数据?的主要内容,如果未能解决你的问题,请参考以下文章
stm32f412 SPI dma接收和UART dma发送问题解决
如何将 stm32f3discovery API 传递给函数?