初始化接收即可,发送会在有数据时才会去操作DMA
开启中断
#include "SEGGER_RTT.h"
#define TX_FIFO_SIZE 36
#define RX_FIFO_SIZE 128
static uint8_t rxbuff[RX_FIFO_SIZE];
static uint8_t txbuff[TX_FIFO_SIZE];
static uint16_t tx_tail = 0;
static uint16_t tx_head = 0;
循环接收、需要开启DMA和UART中断
void dma_uart_init()
{
HAL_UART_Receive_DMA(&huart1, rxbuff, RX_FIFO_SIZE);
}
///查询读取一个字节数据
int dma_uart_read_char()
{
static int rx_tail = 0;
int rx_head = (RX_FIFO_SIZE)-huart1.hdmarx->Instance->CNDTR; // 接收到的数据偏移量
if (rx_head != rx_tail)
{
int ch = rxbuff[rx_tail++];
if (rx_tail >= RX_FIFO_SIZE)
{
rx_tail = 0;
}
return ch;
}
return -1;
}
单次DMA发送,需要开启DMA和UART中断
///查询状态并触发一次发送
static void dma_uart_write_trig()
{
static int lock = 0;
if (lock)//中断重入锁
return;
lock = 1;
if (huart1.gState == HAL_UART_STATE_READY)
{
static uint8_t dma_tx_fifo[128];
for (size_t n = 0; n < 128; n++)
{
if (tx_head != tx_tail)
{
dma_tx_fifo[n] = txbuff[tx_tail++];
if (tx_tail >= TX_FIFO_SIZE)
tx_tail = 0;
}
else
{
if (n > 0)
{
HAL_UART_Transmit_DMA(&huart1, dma_tx_fifo, n);
}
break;
}
}
}
lock = 0;
}
///DMA缓冲发送多个字节数据
void dma_uart_writes(const uint8_t *data, int size)
{
for (size_t i = 0; i < size; i++)
{
uint16_t tmp = tx_head + 1;
if (tmp >= TX_FIFO_SIZE)
{
tmp = 0;
}
#if 0 // 丢弃新的数据
if (tmp == tx_tail) // 数据溢出 发送慢于写入
{
break;
}
#else // 等待旧数据发送完
if (tmp == tx_tail)
{
while (tmp == tx_tail)
{
}
}
#endif
txbuff[tx_head] = data[i];
tx_head = tmp;
}
dma_uart_write_trig();
}
///中断回掉函数,该函数由串口发送完成中断TC触发
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
dma_uart_write_trig();
}
#include "stdarg.h"
#include "stdio.h"
#define PRINT_BUFF_SIZE 500
static char print_buff[PRINT_BUFF_SIZE];
void print_x(void *format, ...)
{
va_list ap;
va_start(ap, format);
int n = vsnprintf(print_buff, PRINT_BUFF_SIZE, format, ap);
va_end(ap);
if (n > 0)
{
dma_uart_writes((uint8_t *)print_buff, n);
}
}