前面的系统配置不在赘述,直接从串口配置开,我这边使用到5组串口,具体使用按照实际需求,
1.这边需要打开DMA Settings,在Mode选择Normal,后生成代码。(注意要勾起来中断)
2.现在进入代码,创建一个.H 文件专门用于串口处理(名字按照喜欢的取就行)
#ifndef __UART_TOOL_H
#define __UART_TOOL_H
#include "usart.h"
#define RXTXBUF_SIZE 1024
/*串口环形缓冲串口接收*/
typedef struct
{
UART_HandleTypeDef dut_huart; //为串口 huart1
unsigned char *pRxBuf; //接收缓冲区
unsigned int usRxBufSize; //接收大小
unsigned int usRxWrite; //当前位置
unsigned int usRxRead; //读取位置
unsigned char rec_end_flag; //接收完成标志位
DMA_HandleTypeDef dut_dma; //接收DMA
unsigned char *dmaRxbuf; //DMA接收指针
volatile unsigned int dmaRxlen; //DMA 接收长度
}DUT_USART_FIFO;
unsigned char GetBuf(DUT_USART_FIFO *_pUart,unsigned char *p_ucBuf,unsigned int *_usBufLen);
void UartIRQ(DUT_USART_FIFO *_pUart);
void EnabledUart(DUT_USART_FIFO *_pUart);
#endif
3.在来到创建.c阶段(同样名字用自己喜欢就行)
#include "UART_tool.h"
unsigned char GetChar(DUT_USART_FIFO *_pUart, unsigned char *_pByte)
{
unsigned int usRxWrite=_pUart->usRxWrite;
if (_pUart->usRxRead == usRxWrite)
{
return 0;
}
else
{
*_pByte = _pUart->pRxBuf[_pUart->usRxRead];
if (++_pUart->usRxRead >= _pUart->usRxBufSize)
{
_pUart->usRxRead = 0;
}
return 1;
}
}
unsigned char GetBuf(DUT_USART_FIFO *_pUart,unsigned char *p_ucBuf,unsigned int *_usBufLen)
{
unsigned int i =0;
unsigned int usRxBufSize = _pUart->usRxBufSize;
unsigned int usDataRxNum;
unsigned int usRxWrite,usRxRead;
unsigned char aside;
if ( _pUart->usRxRead == _pUart->usRxWrite )
{
*_usBufLen = 0;
return 0;
}
usRxWrite = _pUart->usRxWrite; //usRxWrite为缓冲区下一次要写入的位置//
usRxRead = _pUart->usRxRead;
(usRxWrite > usRxRead) ? (usDataRxNum = usRxWrite - usRxRead)
: (usDataRxNum = usRxWrite + usRxBufSize - usRxRead);
*_usBufLen = usDataRxNum;
while ( _pUart->usRxRead != _pUart->usRxWrite )
{
if ( i++ < usDataRxNum )
{
GetChar( _pUart, p_ucBuf++ );
}
else
{
GetChar( _pUart, &aside );
}
}
return 1;
}
void UartIRQ(DUT_USART_FIFO *_pUart)
{
if((__HAL_UART_GET_FLAG(&_pUart->dut_huart,UART_FLAG_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&_pUart->dut_huart);//清除标志
HAL_UART_DMAStop(&_pUart->dut_huart); //停止接收,这边一定要要这条,不然会出现上一条和本次接收的一起回复回来的情况
_pUart->dmaRxlen = RXTXBUF_SIZE - __HAL_DMA_GET_COUNTER(&_pUart->dut_dma);
// printf("2._pUart->dmaRxlen %d\n",_pUart->dmaRxlen);
for (unsigned int i = 0; i < _pUart->dmaRxlen; i++)
{
_pUart->pRxBuf[_pUart->usRxWrite]=_pUart->dmaRxbuf[i];
if (++_pUart->usRxWrite>=_pUart->usRxBufSize)
{
_pUart->usRxWrite = 0;
}
}
memset(_pUart->dmaRxbuf,0x00,sizeof(_pUart->dmaRxbuf));
_pUart->dmaRxlen = 0;
_pUart->rec_end_flag = 1; // 接受完成标志位置1
HAL_UART_Receive_DMA(&_pUart->dut_huart,_pUart->dmaRxbuf,RXTXBUF_SIZE);//重新打开DMA接收
}
}
void EnabledUart(DUT_USART_FIFO *_pUart)
{
__HAL_UART_ENABLE_IT(&_pUart->dut_huart, UART_IT_IDLE);
HAL_UART_Receive_DMA(&_pUart->dut_huart,_pUart->dmaRxbuf,RXTXBUF_SIZE);
}
4.到 usart.c 初始化我们的结构体和打开中断
DUT_USART_FIFO g_tUART_1;
unsigned char g_tUART_1_RXBuf[RXTXBUF_SIZE]={0};
unsigned char g_DMA_1_Rxbuf[RXTXBUF_SIZE]={0}
void UART_init(void)
{
g_tUART_1.dut_huart = huart1;
g_tUART_1.pRxBuf = g_tUART_1_RXBuf;
g_tUART_1.usRxBufSize = ARRAY_SIZE(g_tUART_1_RXBuf);
g_tUART_1.usRxRead = 0;
g_tUART_1.usRxWrite = 0;
g_tUART_1.rec_end_flag = 0;
g_tUART_1.dut_dma = hdma_usart1_rx;
g_tUART_1.dmaRxbuf = g_DMA_1_Rxbuf;
g_tUART_1.dmaRxlen = 0;
EnabledUart(&g_tUART_1);
}
5.在中断文件下stm32f4xx_it.c 添加 UartIRQ(&g_tUART_1); 同步声明 extern DUT_USART_FIFO g_tUART_1
extern DUT_USART_FIFO g_tUART_1;
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 */
UartIRQ(&g_tUART_1);
/* USER CODE END USART1_IRQn 1 */
}
6.到main.C上初始化后,在死循环查询串口是否接收到信息,并且打印出来
6.看效果每隔50ms发送一次,发送S:6174,接收R:6174