CubeMX配置01a12c3aff844035b0a8085be62f4d95.png

 4ab8c6e988a842d1b373b360af1f081c.png

1ff7c2723a654e1f829b8af883579349.png

ce1889c009f04e1bb9fb8631ac8c1b94.png

TxRX选择正常Normal模式:

f58428c4665c4f70897f8e7a572e1a48.png8cf08675669b4e0fb55cc911fed4104d.png 3cdd79f64dea4223a26000979fcb7ecc.png

e6af663cd2c64755aefa29424403c710.png

9a90b67abf6649aca1500cdd804ed3ae.png

配置完毕 

程序部分

main.h 

1f22a2454064433eab569c34ecad6673.png

#include "stdio.h"
#include "string.h"
#include <stdarg.h>
#include "usart.h"
#include "dma.h"

DMA发送

 1、进行一些参数定义和自定义函数26eb2d8e3a0d4832bb24777843f98de5.png

//usart.h文件,变量外部声明
#define USART_DMA_TX_BUFFER_MAXIMUM			256    // DMA缓冲区大小
#define USART_DMA_RX_BUFFER_MAXIMUM			256    // DMA缓冲区大小
extern uint8_t usart1_rx_buffer[USART_DMA_RX_BUFFER_MAXIMUM]; //串口1的DMA接收缓冲区
extern uint8_t usart1_tx_buffer[USART_DMA_TX_BUFFER_MAXIMUM]; //串口1的DMA发送缓冲区
extern uint8_t usart1_rx_flag; //DMA接收成功标志 0,未接收到/1,接收到等待处理
extern uint16_t usart1_rx_len; //DMA一次空闲中断接收到的数据长度
extern uint8_t receive_u1_data[USART_DMA_RX_BUFFER_MAXIMUM];	  //DMA接收数据缓存区

注意:要放到有注释begin和end的中间,不然下次重新配置生成会被擦除。

usart.c文件中:

55711e56c58742d592aaa3f07d06e067.png

//变量外部声明
uint8_t usart1_rx_buffer[USART_DMA_RX_BUFFER_MAXIMUM]; //串口1的DMA接收缓冲区
uint8_t usart1_tx_buffer[USART_DMA_TX_BUFFER_MAXIMUM]; //串口1的DMA发送缓冲区
uint8_t usart1_rx_flag = 0; //DMA接收成功标志 0,未接收到/1,,接收到等待处理
uint16_t usart1_rx_len = 0; //DMA一次空闲中断接收到的数据长度
uint8_t receive_u1_data[USART_DMA_RX_BUFFER_MAXIMUM];	  //DMA接收数据缓存区

26a6492cd5894b89a6d286430c9536c8.png

//串口1的DMA发送
void UART1_TX_DMA_Send(uint8_t *buffer, uint16_t length)
{
    //等待上一次的数据发送完毕
	while(HAL_DMA_GetState(&hdma_usart1_tx) != HAL_DMA_STATE_READY);
    //while(__HAL_DMA_GET_COUNTER(&hdma_usart1_tx));
	
    //关闭DMA
    __HAL_DMA_DISABLE(&hdma_usart1_tx);

    //开始发送数据
    HAL_UART_Transmit_DMA(&huart1, buffer, length);
}

//串口1的DMA发送printf
void printf1(const char *format, ...)
{
	uint32_t length = 0;
	va_list args;
	
	__va_start(args, format);
	
	length = vsnprintf((char*)usart1_tx_buffer, sizeof(usart1_tx_buffer), (char*)format, args);
	
	UART1_TX_DMA_Send(usart1_tx_buffer, length);
}

然后记得在usart.h文件中声明

60f30de0f945458f9b184fb867aedd20.png

发送测试:(main.c)

 8a05b77f9d3d46aeb39cdffe72f4efd8.png

 53a0299e6b1f42c791cc04afa107b173.png

 DMA接收

使能DMA接收,并于接收完后进入空闲中断函数

HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

函数作用:在DMA模式下接收一定数量的数据,直到接收到预期数量的数据或发生空闲事件。

参数Size:接收数据的长度,一般大于不定长数据长度,避免遗漏数据空闲中断回调函数

__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)

使能DMA接收

主函数:

28958ba1befb42e4a916ee3f460ee024.png

HAL_UARTEx_ReceiveToIdle_DMA(&huart1,usart1_rx_buffer,USART_DMA_RX_BUFFER_MAXIMUM);

中断:

b00afb014f39436fbfd2a7565756ae92.png

中断回调函数,放usart.c

939a1f22636b4e49ba2a2a98f97431d2.png

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART1) //如果是串口1
	{
		memset(receive_u1_data, 0, usart1_rx_len);//清除上次缓存的数据
		usart1_rx_len = USART_DMA_RX_BUFFER_MAXIMUM - (__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)); //接收个数等于接收缓冲区总大小减剩余计数
			
		/* 搬移数据进行其他处理 */
		memcpy(receive_u1_data, usart1_rx_buffer, usart1_rx_len); 
		usart1_rx_flag = 1; //标志已经成功接收到一包等待处理
	}
}

代码改善(2023/12/30):

/*串口中断回调函数*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if (huart->Instance == USART1) //如果是串口1
	{
		usart1_rx_len = USART_DMA_RX_BUFFER_MAXIMUM - (__HAL_DMA_GET_COUNTER(&hdma_usart1_rx)); //接收个数等于接收缓冲区总大小减剩余计数
		usart1_rx_buffer[usart1_rx_len]	='\0'; //清除上次缓存的数据
		usart1_rx_flag = 1; //标志已经成功接收到一包等待处理
	}

}

改进了上次缓存数据的清除,直接赋予数组一个结束符,就不用再弄个新的数组来存放了,功能函数使用时,直接读取usart1_rx_buffer数组里面的数据就好了。 

测试(main.c)

7b12f4205eb84e0dbf5a4c0d2b306629.png

if (usart1_rx_flag)
		{
			count++;
			printf1("接收数据次数: %d\r\n接收数据长度: %d\r\n接收数据内容:%s",count,usart1_rx_len,receive_u1_data);
			//delay_ms(10);
			//Debug_printf("连续传送\r\n");
			usart1_rx_flag = 0;
			//usart1_rx_len = 0;
		}

如果上面的回调函数用了第二种方法的话就:

if (usart1_rx_flag)
		{
			count++;
			printf1("接收数据次数: %d\r\n接收数据长度: %d\r\n接收数据内容:%s",count,usart1_rx_len,usart1_rx_buffer);
			usart1_rx_flag = 0;
		}

烧入进去要复位一下,可以在这里设置就不用复位了

75fdb09129e448b58aeb4400cd00e8b0.png

109cda0326a046e49e90f783c9e7d266.png

结果:

9571a63772974f08b033825acd54e8c5.png

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐