巧用STM32串口DMA的normal和circular模式,达到并行执行效果

  • 芯片型号:stm32f103rct6;SPI接口ADC;

  • 代码功能描述:有xyz3路数据,每路1个双通道adc采集,从x路依次数据并用串口发送出去,14字节,2250000bps;

  • 方案1:按照顺序执行,依次采集各路数据,然后uart发送。这样也行,但是我不喜欢,这样会影响数据更新的速率,就拿x路来说,要等yz路,串口发送都完成了,x路才开始下一次数据采集。我的目的是尽量提高各路数据更新的速率。方案1不满足。

  • 方案2:考虑用DMA发送,释放CPU。

  • DMA有normal和circular两种模式。
    circular用法:(STM32CubeMX配置串口DMA省略)

  • 在main函数中该初始化的都初始化完毕之后,紧接着一句:
    HAL_UART_Transmit_DMA(&huart1, (uint8_t*)Tx_frame, LENGTH_FRAME);

  • 就调用这个函数一次就可以了,DMA一直开启,一帧数据发送完毕之后里面发送下一帧,中间没有停顿。这样确实是快了,也释放了CPU,各路的数据采集因为缺少了等待串口发送的时间,所以就间接提高的了数据更新速率。但有个致命缺陷:数据采集和数据发送各玩各的,就是他俩时序对不上,数据采集到一半,一个完整帧数据只更新了一部分,就被DMA挪走了,这样就把新旧数据一块发送出去了,circular模式的DMA才不管数据有没有完整更新,只管发
    normal用法:

  • 为了解决circular带来的问题,采用normal模式,就是每发一次就开启一次DMA,这样就可以等一帧数据更新完毕之后,再开启DMA发送,同样不会占用CPU,在DMA发送数据的时间里CPU可以开启下一轮的数据采集。

  • 再HAL库配置好normal模式后,在数据采集的代码后面,比如采集数据代码是这样执行的:

CSX=0;
采集X_ADC_通道1;
采集X_ADC_通道2;
CSX=1;
CSY=0;
采集Y_ADC_通道1;
采集Y_ADC_通道2;
CSY=1;
CSZ=0;
采集Z_ADC_通道1;
采集Z_ADC_通道2;
CSZ=1;
HAL_UART_Transmit_DMA(&huart1, (uint8_t*)Tx_frame, LENGTH_FRAME);
  • 这样数据采集和数据发送几乎是并行执行的,可以大大提高各路数据更新的速率。

STM32的UART使用DMA操作不要入的坑

猜你喜欢

转载自blog.csdn.net/aqwtyyh/article/details/109118942