STM32CubeMX_配置UART_+DMA实现不定长数据发送和接收
本文写作写时使用的平台:
STM32CubeMX 版本:6.6.1
MCU:STM32F103CBT6
在STM32CubeMX生成工程
1.先设置串口配置,波特率
2.把DMA接收设置成为循环模式。
3.打开uart中断,同时设置好对应的优先级
然后生成代码。
修改工程代码
1.修改void MX_USART1_UART_Init(void)函数中的代码,加入如下代码打开空闲中断
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
2.定义缓存区和dma发送标志
#define USART1_BUFFER_SIZE 32
uint8_t usart1_tx_buffer[USART1_BUFFER_SIZE] ={0};
uint8_t usart1_rx_buffer[USART1_BUFFER_SIZE] ={0};
volatile uint8_t usart1_tx_dma_status = 0;
volatile uint8_t usart1_rx_dma_status = 0;
3.添加初始化函数
lp_err_t bsp_st32_uart1_init(void)
{
lp_err_t ret = LP_OK;
if(HAL_UART_Receive_DMA(&huart1,usart1_rx_buffer,USART1_BUFFER_SIZE) != HAL_OK) //这个函数最要是设置接收缓存区
{
//error
LOG_OUT("bsp_st32_uart1_init Fail\r\n");
ret = LP_FAIL;
}
return ret;
}
4.新增两个函数一个是发送完成回调,一个接收完成回调。
extern
lp_err_t lp_sys_os_serial_rev_data_complete_hook(lp_u8_t serial_register,lp_u8_t* data,lp_u16_t len);
void UART_RxIdleCallback(UART_HandleTypeDef *huart,DMA_HandleTypeDef *hdma_usart_rx)
{
uint8_t dma_recv_len;
if(huart->Instance == USART1){
if(__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE)){
__HAL_UART_CLEAR_IDLEFLAG(huart);
HAL_UART_DMAStop(huart);
dma_recv_len = USART1_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(hdma_usart_rx);//这个是本次接收到的长度
//这个是我自己封装好的接收的数据放入队列
lp_sys_os_serial_rev_data_complete_hook(LP_UART1_E,&usart1_rx_buffer[0],dma_recv_len);
//再次打开DMA
HAL_UART_Receive_DMA(huart,usart1_rx_buffer,USART1_BUFFER_SIZE);
}
}
}
extern
lp_err_t lp_sys_os_serial_tx_data_complete_hook(lp_u8_t serial_register);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
usart1_tx_dma_status = 0; //发送完成标志设置为空闲
//发送完成回调可以用来做一些清理的工作,比如485ctl 设置为接收。
lp_sys_os_serial_tx_data_complete_hook(LP_UART1_E);
}
}
5.把函数void UART_RxIdleCallback(UART_HandleTypeDef *huart,DMA_HandleTypeDef *hdma_usart_rx)在空闲中断中调用
void UART_RxIdleCallback(UART_HandleTypeDef *huart,DMA_HandleTypeDef *hdma_usart_rx);
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
UART_RxIdleCallback(&huart1,&hdma_usart1_rx);
/* USER CODE END USART1_IRQn 1 */
}
6.封装发送函数
lp_err_t bsp_st32_uart1_send(lp_u8_t *data,lp_u16_t len)
{
if(usart1_tx_dma_status != 0)
{
return LP_FAIL;
}
usart1_tx_dma_status = 1;
if(HAL_UART_Transmit_DMA(&huart1,data,len) != HAL_OK)
{
//error
LOG_OUT("HAL_UART_Transmit_DMA Fail\r\n");
}
return LP_OK;
}
lp_err_t bsp_st32_uart1_send_is_busy(void)
{
if(usart1_tx_dma_status == 0)
{
return LP_OK;
}
return LP_FAIL;
}
```c
lp_err_t bsp_st32_uart1_send_is_busy(void)
{
if(usart1_tx_dma_status == 0)
{
return LP_OK;
}
return LP_FAIL;
}
完成编译