-
芯片型号: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操作不要入的坑