在学习HAL库开发的时候,发现了一些我难以理解的问题😢。主要都是关于DMA和UART外设,SPI外设的问题,本人才疏学浅,查阅了几天的资料也没有找到能理解的解答,特发帖求助。
DMA和UART外设
在使用HAL库+CubeIDE开发,重定向printf时查看教程和资料发现主流代码都如下
#include <stdio.h>
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int _io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__*/
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart4, (uint8_t *)&ch,1,0xFFFF);
return ch;
}
基本都是对putchar函数的重定义来重定向printf到uart串口输出,核心代码就是一句
HAL_UART_Transmit(&huart4, (uint8_t *)&ch,1,0xFFFF);
于是我想着把阻塞式发送改为DMA发送可以加快速度节约资源,就把句代码改成了
HAL_UART_Transmit_DMA(&huart4, (uint8_t *)&ch,1,0xFFFF);
但结果就是串口无法发送。我不太懂printf这个函数的底层实现是怎么样的,网上也没有找到特别合适的解答,但找到了另一种重定向方式
uint8_t UART4_TXBuff[UART_TXBuffSize];
void uart4_printf(const char *format,...)
{
uint32_t length;
va_list args;
va_start(args, format);
length = vsnprintf((char*)UART4_TXBuff, sizeof(UART4_TXBuff)+1, (char*)format, args);
va_end(args);
HAL_UART_Transmit_DMA(&huart4,UART4_TXBuff,length);
}
大概方式就是把要发送的内容全部加载到缓冲数组中,再一次性全部由DMA发送给UART外设,结果能成功发送,上位机也能完整的接收信息。但我还是不太懂为什么直接把阻塞式的UART发送改为DMA发送程序就无法达到效果。望各位大佬解答qwq
DMA和SPI外设
在写LCD屏幕(st7789)的驱动时,我发现大部分的现成的驱动代码发送一字节的指令时都是使用阻塞式SPI发送的
uint8_t SPI6_WriteData(uint8_t *data,uint16_t size)
{
return HAL_SPI_Transmit(&hspi6,data,size,1000);
}
static void LCD_SPI_Send(uint8_t *data, uint16_t size)
{
SPI6_WriteData(data, size);
}
static void LCD_Write_Cmd(uint8_t cmd)
{
LCD_DC(0);
LCD_SPI_Send(&cmd, 1);
}
发送一字节数据也是同理,最底层都是一句
HAL_SPI_Transmit(&hspi6,data,size,1000);
于是和当时串口一样,我就想着把它改成DMA发送
HAL_SPI_Transmit_DMA(&hspi6,data,size);
不出意外的,屏幕没有反应。但改回阻塞式就一点问题没有。虽然只是一字节的数据发送,就算改成DMA发送也意义不大,但我还是想知道为什么DMA不行阻塞式就可以。
总结问题
在上述的两种场景下,都是阻塞式的发送就没有问题,但改成DMA发送就不行。真心求教为什么会这样orz