在STM32中编写串口通信数据收发有三种方式:轮询模式(阻塞方式),中断模式(非阻塞方式)以及DMA模式。
一. 串口通信(DMA模式)
打开STM32CubeMX,前部分配置流程如串口数据收发基础(三)节里一样。配置好USART1的基本参数,开启定时器中断后,接下来就要开启USART1的DMA。
设置好之后,设置存储路径,选择所用IDE,然后点击GENERATE CODE创建工程,open project打开工程进行全局编译。
二. HAL库中串口收发的重要函数(DMA模式)
1. DMA模式下发送数据函数:HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
@简介 以DMA模式发送一定数量的数据。
@参数 huart,指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数 pData,待发送数据缓冲区的指针。
@参数 Size,待发送数据的字节数。
@返回值 函数执行状态。
2. DMA模式下接收数据函数: HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
@简介 在DMA模式下接收一定数量的数据
@参数 huart,指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数 pData,待接收接收数据缓冲区的指针。
@参数 Size,待接收数据的字节数。
@注意 当UART奇偶校验使能(PCE = 1)时,接收的数据包含奇偶校验位。
@返回值 函数执行状态。
3. DMA模式下接收不定长数据函数: HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
@简介 在DMA模式下接收一定数量的数据,直到接收到预期数量的数据或发生IDLE事件。
@注意 接收数据由这个函数调用发起。DMA服务实现了接收数据的进一步进展,在用户接收缓冲区中自动传输接收到的数据元素,并在接收传输过半/完成时调用回
调函数。UART IDLE事件也用于将接收阶段视为结束。在所有情况下,回调执行将指示接收到的数据元素的数量。
@参数 huart 指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数 pData 待接收接收数据缓冲区的指针。
@参数 Size 待接收数据的字节数。
@返回值 函数执行状态。
4. DMA模式数据传输完成回调函数:HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size);
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
UNUSED(huart);
UNUSED(Size);
}
@简介 接收事件回调(使用高级接收服务后调用的Rx事件通知)。
@参数 huart UART handle
@参数 Size,应用程序接收缓冲区中可用数据的数量(表示接收缓冲区中数据可用的位置)
@返回值 空
5.禁用指定的DMA通道中断函数:__HAL_DMA_DISABLE_IT(HANDLE, INTERRUPT) (CLEAR_BIT((HANDLE)->Instance->CCR , (INTERRUPT)));
#define __HAL_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) (CLEAR_BIT((__HANDLE__)->Instance->CCR , (__INTERRUPT__)))
@简介 禁用指定的DMA通道中断。
@参数 __HANDLE__: DMA处理
@参数 __INTERRUPT__: 指明要启用或者禁用的DMA中断源
该参数可以是下列值的任意组合:
@arg DMA_IT_TC: 传输完成中断屏蔽
@arg DMA_IT_HT: 过半传输完成中断屏蔽
@arg DMA_IT_TE: 传输错误中断屏蔽
@返回值 空
以上提及的函数可在stm32f1xx_hal_uart.c 和 stm32f1xx_hal_dma.h中,在这些文件中找到
三. 实现串口定长收发通信(DMA模式)
在main.c文件中的Private variables下的USER CODE BEGIN PV注释对中写入以下代码
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
unsigned char String_1[] = "hello world!!!\r\n";
unsigned char rx[16];
/* USER CODE END PV */
在main.c文件中的Private function prototypes下的USER CODE BEGIN PFP注释对中写入以下代码
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// dma模式
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart == &huart1){ // 将上位机发来的数据完整的返回回去
HAL_UART_Transmit_DMA(&huart1,rx,sizeof(rx));
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_4);
HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
}
}
/* USER CODE END PFP */
在main.c文件中的main函数下USER CODE BEGIN 2 注释对写入以下代码
/* USER CODE BEGIN 2 */
HAL_UART_Transmit_IT(&huart1,String_1,sizeof(String_1));
HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
/* USER CODE END 2 */
实现的效果是在当开发板通过USB转TTL模块与电脑上的串口调试助手相连后,上位机向开发板发送的数据。开发板接收到上位机发来的数据后,翻转PB4引脚上的LED灯亮灭,随后将接收到的数据原封不动的再返回给上位机。
四. 实现串口不定长收发数据通信(DMA模式)
在main.c文件中的Private function prototypes下的USER CODE BEGIN PFP注释对中写入以下代码
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// dma模式
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
if(huart == &huart1){ // 将上位机发来的数据完整的返回回去
HAL_UART_Transmit_DMA(&huart1,rx,Size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
}
}
/* USER CODE END PFP */
在main.c文件中的main函数下USER CODE BEGIN 2 注释对写入以下代码文章来源:https://www.toymoban.com/news/detail-769249.html
/* USER CODE BEGIN 2 */
HAL_UART_Transmit_IT(&huart1,String_1,sizeof(String_1));
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
/* USER CODE END 2 */
实现的效果是在当开发板通过USB转TTL模块与电脑上的串口调试助手相连后,上位机向开发板发送的数据。开发板接收到上位机发来的数据后,随后将接收到的数据原封不动的再返回给上位机。
如下图可以发现依次发送不定长的数据给开发板后,开发板都完整的返回了。
但是当我们一次发送过多的数据后,返回的数据竟然不完整了。
这是因为在发送数据的时候,当我们接收的数据量达到设置的最大值的一半的时候
也就是这个
,就会触发HAL_UARTEx_RxEventCallback回调函数。
为了解决这个问题,我们可以使用关闭“DMA传输过半中断”的函数,也就是__HAL_DMA_DISABLE_IT()函数。将其写入到HAL_UARTEx_RxEventCallback回调函数中
注意:如果编译出错为 **error: #20: identifier “hdma_usart1_rx” is undefined **时,说明标识符“hdma_usart1_rx”未定义。可以证明解决。
在usart.h中的USER CODE BEGIN Private defines注释对中添加extern DMA_HandleTypeDef hdma_usart1_rx;
编译,运行,串口调试助手,启动!!!
这个时候可以发现数据终于实现了正常的不定长收发了(只要不要写过我们的先前设定的rx数组长度就好了)
文章来源地址https://www.toymoban.com/news/detail-769249.html
到了这里,关于【STM32笔记】STM32的串口数据收发基础(四)(USART DMA模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!