STM32CubeIDE(CUBE-MX hal库)----串口通信

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文讲述了利用HAL库进行串口数据的发送和接收


提示:以下是本篇文章正文内容,下面案例可供参考

一、CUBE-MX可视化配置

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、发送数据和接收数据

1.HAL库串口的阻塞模式和非阻塞模式

阻塞模式:
在阻塞模式下,发送和接收函数会一直等待直到数据发送或接收完成。在HAL库中,一些典型的阻塞模式的串口操作函数有:
发送数据:HAL_UART_Transmit 或 HAL_UART_Transmit_DMA。
接收数据:HAL_UART_Receive 或 HAL_UART_Receive_DMA。
这些函数会一直阻塞程序的执行,直到数据完全发送或接收
非阻塞模式:
在非阻塞模式下,发送和接收函数是非阻塞的,它们会立即返回,允许程序在等待数据传输的同时执行其他任务。在HAL库中,使用的是带有IT(中断)或DMA(直接存储器访问)的函数。
发送数据:HAL_UART_Transmit_IT、HAL_UART_Transmit_DMA等。
接收数据:HAL_UART_Receive_IT、HAL_UART_Receive_DMA等。
两种方式的优缺点:
阻塞模式简单直观,但可能导致程序在等待数据时无法执行其他任务。非阻塞模式可以提高系统的响应性,但需要更复杂的程序设计,以处理异步的数据传输。

HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);//非阻塞方式发送数据
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

2.HAL库串口阻塞模式数据发送函数

实现了每隔500ms向串口发送一个字符串hello world
在这里插入图片描述
HAL_UART_Transmit函数解析

函数:HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
入口参数:UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1,注意的是传入的是地址例如:&huart1
*pData 需要发送的数据
Size 发送的字节数
Timeout 最大发送时间,发送数据超过该时间退出发送
返回值: HAL_OK = 0x00U,
HAL_ERROR = 0x01U,
HAL_BUSY = 0x02U,
HAL_TIMEOUT = 0x03U
功能:发送一字节数据

3.HAL库串口阻塞模式数据接收函数

实现了将串口发送的数据进行接收,存放到receiveData中,并利用HAL_UART_Transmit()将接收到的数据发送到串口
在这里插入图片描述
HAL_UART_Receive函数解析

函数:HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
参数:同HAL_UART_Transmit()函数一样,这个函数也有四个参数
第一个参数是要使用的串口句柄地址,比如要使用U(S)ART1,参数就设置为U(S)ART1的句柄地址&huart1
第二个参数是接受数据的缓冲区首地址
第三个参数是接受的数据长度,这里可以直接用sizeof()函数获取接受缓冲区的长度
第四个参数是超时时间,单位是ms,如果超过设置的时间,则函数返回HAL_TIMEOUT,如果设置为HAL_MAX_DELAY,处理器就会一直等到接受到设置好的数据数量再执行下一条语句。
返回值: HAL_OK = 0x00U,
HAL_ERROR = 0x01U,
HAL_BUSY = 0x02U,
HAL_TIMEOUT = 0x03U
功能:接收数据

4.HAL库串口非阻塞模式数据发送函数

首先要使能中断
在这里插入图片描述

函数:HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数:前三个参数和阻塞方式完全一致,为什么没有超时时间了呢?因为中断(IT)方式配置完成寄存器之后不需要再占用CPU,会在接受完成后触发中断。

5.HAL库串口非阻塞模式数据接收函数

在这里插入图片描述
重写HAL_UART_RxCpltCallback回调函数,接收数据完成后将数据以非阻塞方式进行发送
在这里插入图片描述
实现效果,注意再发送数据后想要再次接收数据要再次使用HAL_UART_Receive_IT(&huart1, receiveData, 2);
在这里插入图片描述

6.HAL库串口处理流程和标准库函数的处理流程对比

MX_USART1_UART_Init(); 对应 USART_Config();NVIC_Configuration();
HAL_UART_Init(&huart1) 对应 USART_Init(DEBUG_USARTx, &USART_InitStructure)
HAL_UART_Receive_IT(&huart1, (uint8_t *)Buffer, 1); 对应 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);

在看HAL库代码时疑问点是在开启HAL_UART_Receive_IT()非阻塞接收数据,具体实现的源代码在哪里?
首先在使用标准库时,一般直接在某个串口的中断服务函数中利用USART_ReceiveData整个库函数来接收数据。

void USART1_IRQHandler(void)   
{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		Res =USART_ReceiveData(USART1);
	}
}

而在HAL库中开发者不用再写f(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)判断寄存器的状态了,因为HAL_UART_IRQHandler(&huart1);这个函数已经帮你写好了。在这里插入图片描述
点进HAL_UART_IRQHandler(&huart1);这里面HAL库已经帮你写了判断寄存器值的函数这里相当于if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
在这里插入图片描述
点进去UART_Receive_IT这里面实现的功能和标准库函数中的USART_ReceiveData实现功能是一样的
在这里插入图片描述
这里是标准库函数中的USART_ReceiveData(),经过比较可以看出HAL库将底层对寄存器的操作进行了封装因此用户可以更加方便的使用HAL库函数

uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  
  /* Receive Data */
  return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
}

在这里插入图片描述

三、接收不定长数据以及DMA数据的发送和接收

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  /* Prevent unused argument(s) compilation warning */
	if(huart==&huart1)
	{
//		HAL_UART_Transmit_DMA(&huart1, receiveData, Size);
//		HAL_UARTEx_ReceiveToIdle_DMA(&huart1, receiveData, sizeof(receiveData));
		HAL_UART_Transmit_IT(&huart1, receiveData, Size);
		HAL_UARTEx_ReceiveToIdle_IT(&huart1, receiveData, sizeof(receiveData));
	}


  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UARTEx_RxEventCallback can be implemented in the user file.
   */
}

在这里插入图片描述
利用DMA进行数据的传输

在这里插入图片描述

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  /* Prevent unused argument(s) compilation warning */
	if(huart==&huart1)
	{
		HAL_UART_Transmit_DMA(&huart1, receiveData, Size);
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1, receiveData, sizeof(receiveData));
		//HAL_UART_Transmit_IT(&huart1, receiveData, Size);
		//HAL_UARTEx_ReceiveToIdle_IT(&huart1, receiveData, sizeof(receiveData));
	}


  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UARTEx_RxEventCallback can be implemented in the user file.
   */
}

四、printf重定向

1.在main函数前面加上以下代码

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
//STM32cubeIDE下
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1,0xFFFF);
    return ch;
}

//keil下 //没在keil下尝试过 一直使用软件stm32cubeIDE没有取keil验证
//UART_HandleTypeDef huart1; //UART句柄
int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,0xffff);
	return ch;
}

2.在CUBEIDE中按照图中所示修改
在这里插入图片描述在这里插入图片描述
实现效果
在这里插入图片描述

  • 35
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值