蓝桥杯STM32 G431 hal库开发速成——UART

一、UART与USART的区别

UART(Universal Asynchronous Receiver/Transmitter,通用异步接收/发送器)和 USART(Universal Synchronous/Asynchronous Receiver/Transmitter,通用同步/异步接收/发送器)是两种常见的串行通信接口,它们在功能上有一些区别:

通信模式:

UART 仅支持异步通信。在异步通信中,数据以独立的字节形式传输,每个字节通常由起始位、数据位、可选的奇偶校验位和停止位组成。

USART 支持同步和异步两种通信模式。同步通信使用时钟信号同步发送和接收方,可以提高数据传输速度,但需要额外的线路用于时钟信号。

数据传输速率:

由于USART支持同步模式,它通常能够达到比UART更高的数据传输速率。

硬件复杂性:

USART由于其额外的同步功能,其硬件实现通常比纯异步的UART复杂。
应用场景:

UART常用于低速、简单的串行数据通信,如PC与微控制器之间的通信。
USART由于其高速和灵活性,常用于需要高速或同步数据传输的场景,如串行存储器访问、高速串行接口等。
兼容性:

多数USART设备能够向后兼容UART,即它们可以仅作为异步接收/发送器使用。
在选择UART或USART时,需要考虑具体的应用需求,包括通信速率、通信模式(同步或异步)、硬件成本和实现的复杂性。在许多应用场景中,UART的简单性和低成本使其成为首选,而在需要高速或同步通信的应用中,则可能会选择USART。

二、有关URAT的函数

串口发送/接收函数:

HAL_UART_Transmit();串口发送数据,使用超时管理机制 
HAL_UART_Receive();串口接收数据,使用超时管理机制
HAL_UART_Transmit_IT();串口中断模式发送  
HAL_UART_Receive_IT();串口中断模式接收
HAL_UART_Transmit_DMA();串口DMA模式发送
HAL_UART_Transmit_DMA();串口DMA模式接收

串口中断函数:

HAL_UART_IRQHandler(UART_HandleTypeDef *huart);  //串口中断处理函数
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
HAL_UART_ErrorCallback();//串口接收错误函数

中断发送函数:

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)

下面讲解常用的函数:

1.串口发送数据

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

功能:
串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。

参数:

huart: 指向uart _ handletypedef结构的huart指针,该结构包含指定uart模块的配置信息。

PData: 指向数据缓冲区的pData指针(U8或u16数据元素)。

Size: 要发送的数据元素( u8或U16 )的大小

Timeout: 超时持续时间,单位ms,0就是0ms超时,数据最大发送时间,超过则返回异常

2.中断接收函数

HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

功能: 串口中断接收,以中断方式接收指定长度数据。
过程: 设置数据存放位置、接收数据长度,然后使能串口接收中断。接收到数据时,会触发串口中断。串口中断函数处理,直到接收到指定长度数据,而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断)

3.接收中断回调函数

HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  

HAL库的中断进行完之后,并不会直接退出,而是会进入中断回调函数中,用户可以在其中设置代码,串口中断接收完成之后,会进入该函数,该函数为空函数,用户需自行修改。

函数作用:

HAL_UART_RxCpltCallback 是一个在 UART 接收数据完成时被调用的回调函数。
当使用 HAL 库的非阻塞接收函数(如 HAL_UART_Receive_IT)时,一旦预定数量的数据被接收完毕,该回调函数就会被触发。

参数:

UART_HandleTypeDef *huart:这是一个指向 UART 句柄的指针,它包含了 UART 模块的配置信息以及状态信息。
通过这个句柄,你可以访问有关当前 UART 通信的具体信息(例如,使用的 UART 实例)。

实现:

默认情况下,HAL_UART_RxCpltCallback 函数在 HAL 库中只有一个空的实现(即什么也不做)。
用户需要在自己的代码中提供这个函数的实现,以满足特定应用的需求。

注意事项:

在实现这个函数时,要确保代码的执行时间尽可能短,以避免阻塞其他中断服务程序。
此外,需要注意的是,这个函数运行在中断上下文中,因此应避免执行复杂或耗时的操作。

三、USART官方原理图

在这里插入图片描述

四、配置STM32cubeMX

1.根据官方原理图配置引脚,将PA9配置为TXD,将PA10配置为RXD,这样PA9与PA10
分别就与调试器的RXD和TXD相连接。
在这里插入图片描述

2.配置 USART1为的(Asynchronous)异步模式。
配置 USART1 中 “global interrupt” 和 “wake-up interrupt” 为 “ENABLE”

在这里插入图片描述
概念讲述:

1.异步通信相对于同步通信,异步通信不需要时钟信号。每个字节的数据以起始位、数据位、可选的奇偶校验位和停止位的形式发送,使得硬件和软件设计相对简单。

2.在 STM32CubeMX 中为 USART1 配置 “global interrupt” 和 “wake-up interrupt” 为 “ENABLE”(启用)意味着你在微控制器中启用了 USART1 相关的中断功能。这些设置允许 USART1 在特定事件发生时产生中断,从而通知 CPU 处理相关的通信任务。以下是这些设置的详细解释:

USART1 Global Interrupt(USART1 全局中断):

当你将这个选项设置为 “ENABLE” 时,它允许 USART1 在发生某些事件(如数据接收完成、发送完成、错误等)时生成中断信号。
这意味着当这些事件发生时,如果中断被允许(即在中断控制器中相应的中断使能位被置位),CPU 将暂停当前执行的任务,转而执行与 USART1 相关的中断服务程序(ISR)。
这对于实现非阻塞的串行通信非常有用,因为 CPU 不需要不断轮询 USART1 的状态。

USART1 Wake-up Interrupt(USART1 唤醒中断):

这个选项允许 USART1 通过中断信号从低功耗模式唤醒 CPU。
当 MCU 进入低功耗模式(如睡眠模式)时,如果启用了这个功能,USART1 接收到的数据可以生成中断,从而唤醒 MCU 执行相关的 ISR。
这对于节能应用非常有用,特别是在需要 MCU 在没有通信活动时进入低功耗状态的场景中。
启用这些中断功能要求你在程序中实现相应的中断服务例程,以处理 USART1 的接收、发送和错误事件。正确地使用这些中断可以提高程序的效率,减少 CPU 的轮询负担,同时实现更及时的响应。

五、定长UART

注:波特率为9600,开启接收中断,PA9/PA10
局限性:只能输入固定长度数据
效果:输入AT+1 串口助手显示1
AT+2 串口助手显示2
其他的 四位数显示3

1.在/* USER CODE BEGIN 0 /与/ USER CODE END 0 */之间增加如下代码

char rx[50];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)  //串口接收中断回调函数
{                                                        //接收到数据时单片机自动进入中断,进入这个回调函数,进行相关功能的设计即可
	if(rx[0]=='A'&&rx[1]=='T'&&rx[2]=='+'&&rx[3]=='1')
	{
		    HAL_UART_Transmit(&huart1,(unsigned char *)"1", 1, 50);	  
	}
	else if(rx[0]=='A'&&rx[1]=='T'&&rx[2]=='+'&&rx[3]=='2')
	{
	    HAL_UART_Transmit(&huart1,(unsigned char *)"2",1, 50);	  
	}
	else
	{ 
    HAL_UART_Transmit(&huart1,(unsigned char *)"3",1, 50);	  
	}
	  HAL_UART_Receive_IT(&huart1, (unsigned char *)rx, 4); // 再次开启接收中断,
//()第一个指串口1,第二个指存放接收到的数据的存放地址,第三个指接收到几个数据进入接收中断
}

2.在main.c中的int main(void)函数添加如下代码

HAL_UART_Receive_IT(&huart1, (unsigned char *)rx, 4);

3.在发送区分别输入发送:AT+1,AT+2,其他的四位数
串口助手分别接收显示:1 ,2 ,3
在这里插入图片描述
4.注意事项:

在 STM32 的 HAL 库中,当使用基于中断的串口接收 (HAL_UART_Receive_IT) 时,每次中断服务例程(ISR)执行完毕后,必须重新启用中断接收。即:代码的最后一行别忘了!

char rx[50];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)  //串口接收中断回调函数
{                                                        //接收到数据时单片机自动进入中断,进入这个回调函数,进行相关功能的设计即可
	if(rx[0]=='A'&&rx[1]=='T'&&rx[2]=='+'&&rx[3]=='1')
	{
		    HAL_UART_Transmit(&huart1,(unsigned char *)"1", 1, 50);	  
	}
	else if(rx[0]=='A'&&rx[1]=='T'&&rx[2]=='+'&&rx[3]=='2')
	{
	    HAL_UART_Transmit(&huart1,(unsigned char *)"2",1, 50);	  
	}
	else
	{ 
    HAL_UART_Transmit(&huart1,(unsigned char *)"3",1, 50);	  
	}
	  HAL_UART_Receive_IT(&huart1, (unsigned char *)rx, 4); // 再次开启接收中断,
//()第一个指串口1,第二个指存放接收到的数据的存放地址,第三个指接收到几个数据进入接收中断
}

如果出现不匹配的情况(例如:输入AT+1输出3),请重新烧录程序,很可能是因为空格引起的,前四个字符与后四个字符连接了,取了这八个字符的中间字符。

六、\r\n介绍

\r\n 是两个特殊的字符组合,用于表示换行和回车,在不同的文本环境中扮演重要角色:

\r(Carriage Return, CR):回车符,ASCII 码为 13。在早期打字机和计算机终端中,\r 用于将光标移回到一行的开头。

\n(Line Feed, LF):换行符,ASCII 码为 10。它用于将光标下移一行。

不同的操作系统有不同的文本文件换行表示方式:

Windows 系统通常使用 \r\n 组合来表示新的一行。在 Windows 文本文件中,每行的结束都标记为 \r\n。

Unix/Linux 系统使用 \n 来表示新的一行。

Mac 系统在较早的版本中使用 \r 作为行结束符,但现代的 macOS(基于 Unix)使用 \n。

在编程和网络通信中,这些字符经常用来标记文本的结束或分段。例如,在 HTTP 协议中,头部字段和正文之间就是用 \r\n 分隔的。在串行通信和某些文本处理场景中,\r\n 组合也被用作消息的结束符。

七、不定长数据接收UART

注:不定长数据接收UART(结束标志为\r\n版)
串口中断开启,波特率9600
效果:输入什么,输出就是什么

1.在/* USER CODE BEGIN 0 /与/ USER CODE END 0 */之间增加如下代码

char rx[100];
char data[100];
int data_length=0,first_flag=0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	data[data_length]=rx[0];
	data_length++;
	if(rx[0]=='\r')   //rx[0]是等于data[data_length--]
	{
	  first_flag=1;
	}
  if(first_flag==1&&rx[0]=='\n')   //rx[0]是等于data[data_length--]
		{	   
	//HAL_UART_Transmit(&huart1, (uint8_t *)data,data_length,1000),则输出的不转行
   	 HAL_UART_Transmit(&huart1, (uint8_t *)data,data_length,1000);
		 memset(data,0,data_length);data_length=0;first_flag=0;
//		 for(;i>0;i--)
//		 {
//		     a[i]=0;
//		 }
//		 i=0;k=0;
		}
	
	HAL_UART_Receive_IT(&huart1,  (uint8_t *)rx, 1);
}

2.在main.c中的int main(void)函数添加如下代码

HAL_UART_Receive_IT(&huart1,  (uint8_t *)rx, 1);

3.在发送区输入什么在接收区就输出什么
在这里插入图片描述
注意在发送区时,要把鼠标移到下一行,否则无法发送!因为在Windows 系统通常使用 \r\n 组合来表示新的一行。在 Windows 文本文件中,每行的结束都标记为 \r\n。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Comedy_宁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值