1、說明
1.1、注意事項:
- HAL庫的DMA底層基本都會默認開啟中斷使能,如果在STM32CubeMx禁用了中斷相關(guān)的功能,程序可能會進入空中斷回調(diào)出不來。
- 切記使用STM32-HAL庫的DMA發(fā)送時需要開啟USART中斷和DMA中斷。
- 在一般時間要求不是很高很高的場合,使用HAL庫自帶的函數(shù)就可以,并不會很頻繁的觸發(fā)中斷占用資源。
1.2、接收部分
- 接收DMA初始化成循環(huán)傳輸模式。開啟對應DMA通道中斷和串口全局中斷
- 之前擔心開啟串口中斷會在接收數(shù)據(jù)時連續(xù)觸發(fā)中斷、導致消耗CPU資源,實際HAL底層未開啟接收中斷,不會觸發(fā)中斷。
1.3、發(fā)送部分
- 發(fā)送時如果要使用DAM功能,必須開啟DMA中斷和串口中斷。HAL的全局狀態(tài)需要在中斷中得到更新,否則會發(fā)送完一次狀態(tài)一直處于被占用中。
- HAL底層開啟了串口數(shù)據(jù)發(fā)送完成中斷TC。該中斷只有在DMA沒有新的數(shù)據(jù)傳入后,并且移位寄存器為空時才會觸發(fā)一次,不會每發(fā)送一個字節(jié)就會觸發(fā)中斷。
2、代碼
2.1、初始化
初始化接收即可,發(fā)送會在有數(shù)據(jù)時才會去操作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;
2.2、緩沖接收
循環(huán)接收、需要開啟DMA和UART中斷文章來源:http://www.zghlxwxcb.cn/news/detail-801703.html
void dma_uart_init()
{
HAL_UART_Receive_DMA(&huart1, rxbuff, RX_FIFO_SIZE);
}
///查詢讀取一個字節(jié)數(shù)據(jù)
int dma_uart_read_char()
{
static int rx_tail = 0;
int rx_head = (RX_FIFO_SIZE)-huart1.hdmarx->Instance->CNDTR; // 接收到的數(shù)據(jù)偏移量
if (rx_head != rx_tail)
{
int ch = rxbuff[rx_tail++];
if (rx_tail >= RX_FIFO_SIZE)
{
rx_tail = 0;
}
return ch;
}
return -1;
}
2.3、緩沖發(fā)送
單次DMA發(fā)送,需要開啟DMA和UART中斷文章來源地址http://www.zghlxwxcb.cn/news/detail-801703.html
///查詢狀態(tài)并觸發(fā)一次發(fā)送
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緩沖發(fā)送多個字節(jié)數(shù)據(jù)
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 // 丟棄新的數(shù)據(jù)
if (tmp == tx_tail) // 數(shù)據(jù)溢出 發(fā)送慢于寫入
{
break;
}
#else // 等待舊數(shù)據(jù)發(fā)送完
if (tmp == tx_tail)
{
while (tmp == tx_tail)
{
}
}
#endif
txbuff[tx_head] = data[i];
tx_head = tmp;
}
dma_uart_write_trig();
}
///中斷回掉函數(shù),該函數(shù)由串口發(fā)送完成中斷TC觸發(fā)
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
dma_uart_write_trig();
}
2.4、格式化打印
#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);
}
}
到了這里,關(guān)于STM32-UART-DMA HAL庫緩沖收發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!