相信大家很多初学者都会遇到串口接收不定长数据的情况。
对于初学者可能看着有点难理解,多看几遍就好,亲测能用。
话不多说上菜上菜!!!!
此代码是本人在具体工程应用,实测稳定。
有不足之处还请发现问题的小伙伴指出,大家共同进步。
此处省略stm32CubeIDE 配置过程*********************************
串口配置过程如下:
其他几个串口也是如下进行配置(正常使用的话只使能DMA接收即可)
波特率设置
NVIC中断配置
DMA配置
新建usr_uart_rec.h头文件,内容如下:
#ifndef USR_UART_REC_USR_UART_REC_H_
#define USR_UART_REC_USR_UART_REC_H_
#include "main.h"
#define MAX_REC_COUNT 36
typedef struct
{
uint8_t ReciveBuff[MAX_REC_COUNT];
uint8_t uartRecCount;
uint8_t RecFlag:1;
}DMAuartReciveBuff;
typedef struct
{
DMAuartReciveBuff userUart1;
DMAuartReciveBuff userUart2;
DMAuartReciveBuff userUart3;
DMAuartReciveBuff userUart4;
DMAuartReciveBuff userUart5;
DMAuartReciveBuff userUart6;
}UART_REC;
typedef struct
{
uint8_t DMAbuff[MAX_REC_COUNT];
}uBbuffer;
typedef struct
{
uBbuffer usr_uart1;
uBbuffer usr_uart2;
uBbuffer usr_uart3;
uBbuffer usr_uart4;
uBbuffer usr_uart5;
uBbuffer usr_uart6;
}UART_MEMCPY_BUFF;
extern UART_MEMCPY_BUFF usr_dma_Data;
extern UART_REC userUart;
void USR_UART_Init();
void UART1_IRQ_DataGet();
void UART2_IRQ_DataGet();
void UART3_IRQ_DataGet();
void UART4_IRQ_DataGet();
void UART5_IRQ_DataGet();
void UART6_IRQ_DataGet();
#endif
新建usr_uart_rec.c头文件,内容如下:
#include "main.h"
#include "usart.h"
#include "usr_uart_rec.h"
#include "string.h"
UART_REC userUart;
UART_MEMCPY_BUFF usr_dma_Data;
void USR_UART_Init()
{
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart4,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart5,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart6,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
userUart.userUart1.uartRecCount = 0;
HAL_UART_Receive_DMA(&huart1, (uint8_t *)&userUart.userUart1.ReciveBuff, sizeof(userUart.userUart1.ReciveBuff));
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&userUart.userUart2.ReciveBuff, sizeof(userUart.userUart2.ReciveBuff));
HAL_UART_Receive_DMA(&huart3, (uint8_t *)&userUart.userUart3.ReciveBuff, sizeof(userUart.userUart3.ReciveBuff));
HAL_UART_Receive_DMA(&huart4, (uint8_t *)&userUart.userUart4.ReciveBuff, sizeof(userUart.userUart4.ReciveBuff));
HAL_UART_Receive_DMA(&huart5, (uint8_t *)&userUart.userUart5.ReciveBuff, sizeof(userUart.userUart5.ReciveBuff));
HAL_UART_Receive_DMA(&huart6, (uint8_t *)&userUart.userUart6.ReciveBuff, sizeof(userUart.userUart6.ReciveBuff));
}
void UART1_IRQ_DataGet()
{
if(USART1 == huart1.Instance)
{
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))
{
HAL_UART_DMAStop(&huart1);
userUart.userUart1.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
userUart.userUart1.RecFlag = true;
HAL_UART_Receive_DMA(&huart1, (uint8_t *)&userUart.userUart1.ReciveBuff, sizeof(userUart.userUart1.ReciveBuff));
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
}
}
}
void UART2_IRQ_DataGet()
{
if(USART2 == huart2.Instance)
{
if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))
{
HAL_UART_DMAStop(&huart2);
userUart.userUart2.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
userUart.userUart2.RecFlag = true;
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&userUart.userUart2.ReciveBuff, sizeof(userUart.userUart2.ReciveBuff));
__HAL_UART_CLEAR_IDLEFLAG(&huart2);
}
}
}
void UART3_IRQ_DataGet()
{
if(USART3 == huart3.Instance)
{
if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
{
HAL_UART_DMAStop(&huart3);
userUart.userUart3.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
userUart.userUart3.RecFlag = true;
HAL_UART_Receive_DMA(&huart3, (uint8_t *)&userUart.userUart3.ReciveBuff, sizeof(userUart.userUart3.ReciveBuff));
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
}
}
}
void UART4_IRQ_DataGet()
{
if(UART4 == huart4.Instance)
{
if(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE))
{
HAL_UART_DMAStop(&huart4);
userUart.userUart4.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);
userUart.userUart4.RecFlag = true;
HAL_UART_Receive_DMA(&huart4, (uint8_t *)&userUart.userUart4.ReciveBuff, sizeof(userUart.userUart4.ReciveBuff));
__HAL_UART_CLEAR_IDLEFLAG(&huart4);
}
}
}
void UART5_IRQ_DataGet()
{
if(UART5 == huart5.Instance)
{
if(__HAL_UART_GET_FLAG(&huart5,UART_FLAG_IDLE))
{
HAL_UART_DMAStop(&huart5);
userUart.userUart5.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_uart5_rx);
userUart.userUart5.RecFlag = true;
HAL_UART_Receive_DMA(&huart5, (uint8_t *)&userUart.userUart5.ReciveBuff, sizeof(userUart.userUart5.ReciveBuff));
__HAL_UART_CLEAR_IDLEFLAG(&huart5);
}
}
}
void UART6_IRQ_DataGet()
{
if(USART6 == huart6.Instance)
{
if(__HAL_UART_GET_FLAG(&huart6,UART_FLAG_IDLE))
{
HAL_UART_DMAStop(&huart6);
userUart.userUart6.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_usart6_rx);
userUart.userUart6.RecFlag = true;
HAL_UART_Receive_DMA(&huart6, (uint8_t *)&userUart.userUart6.ReciveBuff, sizeof(userUart.userUart6.ReciveBuff));
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
}
}
}
注释掉的部分可用于调试,本人不建议在中断中处理大量数据,因为容易死机哦。
在使用串口DMA的时候需要注意以下问题:
在使用 stm32CubeIDE生成代码之后,按照官方的初始化流程有点点问题,会导致串口接收不到数据,所以要稍作修改,改变初始化流程:如下所示(最主要的是先初始化DMA 再初始化相关串口)这是一位博主针对DMA串口接收数据失败写的文章
MX_DMA_Init();
MX_USART1_UART_Init();
MX_UART4_Init();
MX_UART5_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_USART6_UART_Init();
最后在stm32f4xx_it.c 如下,将自定义的函数加到中断服务函数中即可 例如:
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
UART1_IRQ_DataGet();
}
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
UART2_IRQ_DataGet();
}
void USART3_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart3);
UART3_IRQ_DataGet();
}
void UART4_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart4);
UART4_IRQ_DataGet();
}
void UART5_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart5);
UART5_IRQ_DataGet();
}
void USART6_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart6);
UART6_IRQ_DataGet();
}
需要注意的是 此代码在接收完成后会有一个软件标志位被置1,使用完数据之后需要用户手动清零。
userUart.userUart1.RecFlag = true;
userUart.userUart1.uartRecCount = MAX_REC_COUNT - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
具体如何使用呢,举个例子(串口1):
uint8_t PowerRecBuff[23];
void PowerDataAnalyze()
{
if(userUart.userUart1.RecFlag )
{
userUart.userUart1.RecFlag = false;
memcpy((uint8_t *)&PowerRecBuff,(uint8_t *)&userUart.userUart1.ReciveBuff, userUart.userUart1.uartRecCount);
RSOC = PowerRecBuff[23];
userUart.userUart1.uartRecCount = 0;
memset((uint8_t *)&userUart.userUart1.ReciveBuff,0, sizeof(userUart.userUart1.ReciveBuff));
}
}
自此完结。此代码亲测可用,对于初学者可能有点难理解。学习哪有不难的,就因为难所以才要学呀
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)