STM32-HAL库(快速入门)-3-UART-不定长收发简便版

代码文件:

链接:https://pan.baidu.com/s/1ZjbgVoDO5RGnTeN7z6pC_Q?pwd=91c7 
提取码:91c7 

目录

 

一、UART基本原理

二、cubemx配置

1.基本(阻塞方式)发送/接收

2.中断模式发送/接收

三、代码实现

1.基本(阻塞方式)发送/接收

​编辑​编辑

2.printf重定向

3.中断模式发送/接收

发送:

 接收:

不定长代码收发逻辑:

第一步:定义接收字符缓冲区

第二步:打开串口接收中断

 第三步:不定长收发

 


 

一、UART基本原理

UART:通用异步通信                USART:通用同步异步通信

异步通信:通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。

同步通信:通信要确保双方时钟完全相同

由于一般我们只用异步模式,所以本章为UART,也只介绍异步通信的使用

串口部分电路图

发送阶段:先将要发送的舒服放入TDR中,再由TDR转入移位寄存器,最后再一位一位通过TX引脚发出。

接收阶段:RX引脚一位一位存入移位寄存器,再一次性转入RDR寄存器。

重点标志位:

        TXE:TDR寄存器中的数据已经被转移到移位寄存器(1)

          TC:移位寄存器中的数据发送完成(1)

     RXNE:接收完数据(1)


二、cubemx配置

1.基本(阻塞方式)发送/接收

阻塞模式:发送和接收函数会一直等待,直到数据发送或接收完成,因此会影响效率。

第一步:选择串口

第二部:选择异步模式

第三步:设置参数

baud rate:波特率                可以理解为发送数据的速度

word length:字长                可以理解为一次性发送多少位的二进制码

parity:奇偶校验                   

stop bits:停止位

data direction:数据放心       选择收发模式

over sampling:过采样          用串口发送的n倍速率来采样,可以滤除干扰信号

阻塞模式配置只需要配置这些就可以用了

2.中断模式发送/接收

中断模式:发送和接收函数是非阻塞的,中断后立即返回,程序在等待数据传输的同时执行其他任务

cubemx中打开串口中断即可


三、代码实现

1.基本(阻塞方式)发送/接收

 

定义数据数组

 定时发送数据、接收到数据后立刻返回

总代码:

  uint8_t message[] = "hello world";
  uint8_t receiveData;

  HAL_UART_Transmit(&huart1,message,12,200);
  HAL_Delay(500);
      
//参数1:串口结构体;参数2:数据数组地址;参数3:数据长度;参数4:超时时间  
  HAL_UART_Receive(&huart1,&receiveData,2,HAL_MAX_DELAY);
//参数1:串口结构体;参数2:发送数据;参数3:数据长度;参数4:超时时间  
  HAL_UART_Transmit(&huart1,&receiveData,2,200);

连接好串口线之后,确认参数选择无误打开串口,即可看到发送的数据了!

注意:

1.连接串口线的时候,要注意单片机的TX连接到电脑的RX,单片机的RX连接到电脑的TX

2.串口助手使用时,要取消RTS,否则,串口助手会让单片机始终保持复位状态,直接卡住什么现象也没有(困扰我1小时。。。。。)

2.printf重定向

printf重定向会让我们的代码调试、日志输出、人机交互等更加便捷

第一步:包含stdio文件

#include "stdio.h"

第二步: 重定向fputc

//printf重定向
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

第三步:勾选Use MicroLIB

这一步很重要!!!也要注意,cubemx重新生成程序后会给这个勾选取消,如果没有重新勾选,工程可能会直接卡死,debug里需要点击三次run才能进入main,如要使用printf,时刻检查!!!

测试代码: 

      HAL_Delay(500);
      printf("ZTL\r\n");

 

效果:

 

3.中断模式发送/接收

发送:

直接调用函数即可,无需设置停止时间

      参数1:串口号;参数2:发送信息的地址;参数3:字节数,直接用sizeof获取
      HAL_UART_Transmit_IT(&huart1,message,sizeof(message));//中断方式发送数据
      HAL_Delay(500);

 接收:

中断接收函数:

参数1:串口号;参数2:接收到的数据缓冲区地址;参数3:接收多少数据
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

HAL_UART_RECEIVE_IT执行过程可以理解为:打开串口中断,返回主函数,后台自动接收Size个数据,当接收满Size个数据后触发中断!如果你设置Size=10,然而只发了123456不能触发中断,还得再发7890才能触发中断,触发中断后调用一系列函数,调用过程中,“关闭了接收中断”,然后跳转到回调函数(用户编写的处理数据函数),所以,我们需要在while前先调用一次来打开接收中断,再在回调函数重新调用一次,用来重新打开串口接收中断。

不定长代码收发逻辑:

由上面可知,HAL库的串口中断需要接收size个数据才能进入callback回调函数,那我们可以直接设置size=1,那么每收到1位数据就可以进入这个中断,来对这1位数据操作,比如存入一个数组中。如发送了12345,收到1后,进入中断

那么现在我们就要想办法怎么一位一位的存起来再拿出来。解决方法就是设置一个数组,并规定数组最大值为100,再设置一个下标索引,来不断指示当前的数据应该存在数组的哪一个位置,再设置一个停止字符,当最后一位是该字符,则可以开始处理整个字符串了。

第一步:定义接收字符缓冲区

第二步:打开串口接收中断

while前调用一次receive_it,这时,下标为0,数据存在buffer【0】

由于HAL库封装的原因,当我们开启串口中断后,其具体的中断还没有被打开,比如你想使用串口接收中断,它还没有被激活,我们需要调用接收中断函数手动激活。

 第三步:不定长收发

先判断引起中断引脚号是不是串口1,再判断当前缓存区有没有空间了,如果有,则从寄存器取出来数据,存入缓冲区,第一次执行的话,则存入了buffer【0】,然后下标加1,接着判断这个字符是不是结束字符,如果不是,则重新开启中断,再往后接收,直到这个字符是结束字符,那我们仍然把它存入buffer,然后对数据进行处理,处理结束后清空缓冲区,防止对下一次传输的数据进行干扰。最后,如果缓冲区不足,比如定义最多存100个字符,结果从0发到了200个,那么存到第101个的时候,就不够用了,那么我们需要报错,并且清空缓冲区,让对方重新发。

 

由于赶工可能写的不是很好,如果有bug或者其他问题,可以直接发到评论区

 

<think>好的,我现在需要回答用户关于HAL_UART_Receive和HAL_UART_Receive_IT的区别及用法的问题。首先,我得确认自己对这些函数的工作原理和HAL的结构有足够的了解。根据用户提供的引用资料,我需要整理出两者的区别,并给出正确的用法步骤。 首先,用户提到的引用[2]和引用[4]提到了HAL_UART_Receive_IT的使用方法,包括初始化和回调函数。而引用[3]则提到了使用HAL_UART_Receive时可能遇到的问题,比如读取不到数据。引用[4]特别指出,使用中断接收需要在主循环前开启接收中断,并且不能在中断中直接读取寄存器,这说明HAL_UART_Receive_IT是中断驱动的。 接下来,我需要区分这两个函数的工作模式。HAL_UART_Receive是阻塞式的,也就是说,当调用这个函数时,程序会一直等待直到接收到指定数量的数据或超时。这可能会影响其他任务的执行,尤其是在实时系统中。而HAL_UART_Receive_IT是非阻塞的,启动后立即返回,数据接收在后台进行,通过中断处理,接收完成后会触发回调函数。 然后,我需要检查这两个函数的用法步骤。根据引用[4],使用HAL_UART_Receive_IT需要先初始化并使能中断,然后在主循环前启动接收。而HAL_UART_Receive则直接调用,并指定超时时间。需要注意的是,HAL_UART_Receive如果在主循环中不恰当使用,可能会导致程序卡住,尤其是在没有超时的情况下。 另外,用户提到的引用[3]中的问题,可能是因为没有正确配置超时时间,或者在调用HAL_UART_Receive时没有处理可能的错误情况。比如,如果超时时间设置过短,可能在数据未完全接收时就返回了,导致数据不完整。 还需要考虑DMA相关的函数,比如HAL_UART_Receive_DMA,但用户的问题主要围绕Receive和Receive_IT,所以可能不需要深入讨论DMA,但可以简要提及作为扩展。 最后,总结两者的区别,包括阻塞与非阻塞、使用场景、配置步骤以及回调函数的使用。同时,根据用户提供的引用资料,确保引用正确,比如在讨论中断配置时引用[4],在提到函数位置时引用[2]。 可能的相关问题包括如何选择这两种函数,如何处理接收完成后的数据,以及如何调试接收失败的情况。这些问题可以帮助用户进一步理解实际应用中的注意事项。</think>### HAL_UART_Receive与HAL_UART_Receive_IT的区别及用法 #### 1. **核心区别** - **`HAL_UART_Receive`**:是**阻塞式接收**函数,调用后会占用CPU时间,直到接收到指定长度的数据或超时才会返回[^3][^4]。 - **`HAL_UART_Receive_IT`**:是**非阻塞中断接收**函数,调用后立即返回,数据接收在后台通过中断完成,需配合回调函数处理接收完成事件[^2][^4]。 #### 2. **使用场景** - **阻塞式场景**:适用于简单任务或需要严格同步的场合(如单次接收固定长度数据且无实时性要求)。 - **中断驱动场景**:适用于实时系统或多任务环境,避免阻塞主循环(如持续接收不定长数据)[^4]。 --- #### 3. **用法详解** ##### (1) `HAL_UART_Receive`(阻塞式) ```c // 示例:接收128字节数据,超时时间100ms char buffer[128] = {0}; HAL_StatusTypeDef status = HAL_UART_Receive(&huart2, (uint8_t*)buffer, 128, 100); if (status == HAL_OK) { // 处理接收到的数据 } ``` - **步骤**: 1. 直接调用函数并指定超时时间。 2. 检查返回值`HAL_OK`确认接收成功。 ##### (2) `HAL_UART_Receive_IT`(中断驱动) ```c // 初始化时使能中断 MX_USART2_UART_Init(); HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); // 主循环前启动接收(单字节示例) uint8_t rx_byte; HAL_UART_Receive_IT(&huart2, &rx_byte, 1); // 接收完成回调函数(需用户实现) void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart2) { // 处理接收到的单字节数据 // 重新启动接收以持续监听 HAL_UART_Receive_IT(&huart2, &rx_byte, 1); } } ``` - **步骤**: 1. 初始化UART并配置中断优先级。 2. 调用`HAL_UART_Receive_IT`启动接收。 3. 在回调函数`HAL_UART_RxCpltCallback`中处理数据并重启接收[^4]。 --- #### 4. **关键注意事项** - **中断配置**:使用`HAL_UART_Receive_IT`前必须使能NVIC中断,否则无法触发回调。 - **超时处理**:`HAL_UART_Receive`若超时时间过短,可能导致接收不完整(需根据波特率调整)[^3]。 - **数据长度**:中断接收通常逐字节处理,需在回调中重新启动接收以持续监听[^4]。 --- #### 5. **性能对比** | 特性 | `HAL_UART_Receive` | `HAL_UART_Receive_IT` | |---------------------|-------------------------|-------------------------| | CPU占用 | 高(阻塞) | 低(后台中断) | | 实时性 | 差 | 高 | | 适用场景 | 单次固定长度数据 | 持续/不定长数据 | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值