有人想使用定时器事件触发DMA读取SPI数据,希望每一次更新事件仅触发一轮DMA传输,借助DMA实现N字节的SPI数据收发。
要完成这个功能,这里推荐两种做法供参考。
第一种,先做好SPI的DMA收发配置,配置每轮DMA传输个数为N的Normal模式,在每次的定时器更新事件的中断里调用相关SPI的收发函数即可。
第二种,如果说我们所使用的STM32芯片内置DMAMUX模块,我们可以使用DMAMUX的DMA同步功能来实现该需求。这里基于STM32G4系列芯片重点介绍第二种做法的实现过程。
DMAMUX有个DMA事件同步机制,具体到这里,即使我们开启SPI的DMA的收发功能,但相应DMA通道的请求数及开启可以受制于其它事件,即与其它事件建立起同步关系。作为同步事件的可以是外部中断事件、定时器事件甚至其它DMA事件。只有同步事件出现时,相应的DMA才能启动传输。
我们这里使用STM32G431的Nucleo开发板进行验证测试。使用SPI1,全双工模式,硬件上将数据线互联并开启RX/TX的DMA功能进行自发自收。同时,使用低功耗定时器LPTIM1,其周期性输出事件作为SPI TX/RX的DMA的同步事件,每个事件并为其申请5个DMA请求。LPTIM1每个输出事件触发SPI的DMA传输,SPI通过DMA访问5个数据,这里的数据是“STM32”五个字符。
现在看看基于CubeMx的主要配置。
先对LPTIM1进行配置。我这里开启了其PWM波形输出,只是为了方便后面借助波形观察时序,并非必须的。
对于SPI的配置,主要看看它的DMA配置。开启其RX/TX的DMA的同步功能。这里采用LPTIM的输出事件作为其同步事件。每次同步事件为其申请5个DMA请求。有关SPI的其它基本配置就没必要贴图了。
完成各种配置后生成初始化代码,然后在代码里添加些用户代码即可验证结果了。
#define PeriodValue (6)
#define PulseValue (1)
#define Size (5)
uint8_t pTxData[Size]={'S','T','M','3','2'};
uint8_t pRxData[Size]={0};
HAL_SPI_TransmitReceive_DMA(&hspi1, pTxData, pRxData,Size);
HAL_LPTIM_PWM_Start(&hlptim1, PeriodValue,PulseValue);
借助于IDE调试工具我们可以看到SPI通过DMA收到的数据。
另外,我们借助示波器可以看到相应的输出波形。下面截图中黄色波形为LPTIM的PWM输出,蓝色为SPI的数据信号,紫色为SPI时钟信号。第二副图是放大了的局部波形。
从上面波形图可以看出,每个定时器输出事件即触发DMA完成SPI的5个数据收发,然后等待下次触发。
=====================
往期话题阅读链接【点击即可阅读】:
版权声明:本文为CSDN博主「茶话MCU」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38106263/article/details/121896831
暂无评论