写一段 STM32 使用HAL库 串口通信使用DMA 发送接受不定长数据的代码
时间: 2023-05-22 11:05:09 浏览: 272
以下是一段使用HAL库实现STM32串口通信使用DMA发送接收不定长数据的代码:
```c
#include "stm32f4xx_hal.h"
#define RX_BUFFER_SIZE 256
#define TX_BUFFER_SIZE 256
UART_HandleTypeDef huart;
DMA_HandleTypeDef hdma_tx;
DMA_HandleTypeDef hdma_rx;
uint8_t tx_buffer[TX_BUFFER_SIZE];
uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint16_t rx_rd_index = 0;
volatile uint16_t rx_wr_index = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// Increment the buffer write index
rx_wr_index++;
if (rx_wr_index >= RX_BUFFER_SIZE)
{
rx_wr_index = 0;
}
HAL_UART_Receive_DMA(huart, rx_buffer + rx_wr_index, 1);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
// Do nothing
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
// Do nothing
}
void init_uart_dma()
{
// Initialize the UART handle structure
huart.Instance = USART1;
huart.Init.BaudRate = 9600;
huart.Init.WordLength = UART_WORDLENGTH_8B;
huart.Init.StopBits = UART_STOPBITS_1;
huart.Init.Parity = UART_PARITY_NONE;
huart.Init.Mode = UART_MODE_TX_RX;
huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart.Init.OverSampling = UART_OVERSAMPLING_16;
if(HAL_UART_Init(&huart) != HAL_OK)
{
Error_Handler();
}
// Enable UART DMA transmission and reception
__HAL_RCC_DMA2_CLK_ENABLE();
hdma_tx.Instance = DMA2_Stream7;
hdma_tx.Init.Channel = DMA_CHANNEL_4;
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_tx.Init.Mode = DMA_NORMAL;
hdma_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_tx) != HAL_OK)
{
Error_Handler();
}
hdma_rx.Instance = DMA2_Stream2;
hdma_rx.Init.Channel = DMA_CHANNEL_4;
hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_rx.Init.Mode = DMA_CIRCULAR;
hdma_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&huart, hdmatx, hdma_tx);
__HAL_LINKDMA(&huart, hdmarx, hdma_rx);
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
HAL_UART_Receive_DMA(&huart, rx_buffer, 1);
}
void send_uart_packet(uint8_t *data, uint16_t length)
{
// Copy the data to the TX buffer
memcpy(tx_buffer, data, length);
// Enable UART transmission DMA
HAL_UART_Transmit_DMA(&huart, tx_buffer, length);
}
int read_uart_packet(uint8_t *buffer, uint16_t buffer_size)
{
int packet_size = 0;
// Get the buffer read index
uint16_t rd_index = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_rx);
// If the read index has changed
if (rd_index != rx_rd_index)
{
if (rd_index > rx_rd_index)
{
packet_size = rd_index - rx_rd_index;
}
else
{
packet_size = RX_BUFFER_SIZE - rx_rd_index + rd_index;
}
// Check that the buffer size is large enough
if (packet_size > buffer_size)
{
packet_size = buffer_size;
}
// Copy the data to the buffer
if (rx_rd_index + packet_size < RX_BUFFER_SIZE)
{
memcpy(buffer, rx_buffer + rx_rd_index, packet_size);
}
else
{
memcpy(buffer, rx_buffer + rx_rd_index, RX_BUFFER_SIZE - rx_rd_index);
memcpy(buffer + RX_BUFFER_SIZE - rx_rd_index, rx_buffer, packet_size - (RX_BUFFER_SIZE - rx_rd_index));
}
// Update the read index
rx_rd_index = rd_index;
}
return packet_size;
}
int main(void)
{
HAL_Init();
init_uart_dma();
while (1)
{
uint8_t buffer[32];
int packet_size = read_uart_packet(buffer, 32);
if (packet_size > 0)
{
// Do something with the received packet
}
}
}
void DMA2_Stream7_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_tx);
}
void DMA2_Stream2_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_rx);
}
```
阅读全文