当前位置:   article > 正文

STM32CubeMx+HAL库:USART串口收发数据的三种方式_单片机串口接收方式

单片机串口接收方式

目录

1.阻塞模式 

1.1 阻塞模式发送函数

1.2 阻塞模式接收函数

1.3 STM32CubeMX配置

1.4 代码编写

测试阻塞模式发送函数

测试阻塞模式接收函数

2.中断模式

2.1 中断模式发送函数

2.2 中断模式接收函数

2.3 STM32CubeMX配置

2.4 代码编写

3.DMA模式

3.1 什么是DMA

3.2 DMA模式发送函数

3.3 DMA模式接收函数

3.4 STM32CubeMX配置

3.5 代码编写 

总结


上篇我们讲解了利用HAL库串口中断模式收发数据的教程,包括STM32CubeMx中串口的配置等,不清楚的小伙伴可以跳转链接学习查看。

STM32CubeMx+HAL库实现串口中断收发数据(STM32F103RCT6)新手小白必看的保姆级教程icon-default.png?t=N7T8https://blog.csdn.net/weixin_54015326/article/details/135683705?spm=1001.2014.3001.5501


本篇我们主要总结下串口收发数据的三种方式,分别是:阻塞模式(也叫轮询)、中断模式、DMA模式,以下是HAL库中串口发送和接收数据时所调用的函数。

汇总:

1.阻塞模式收发数据

        HAL_UART_Transmit():串口发送数据,使用超时管理机制
        HAL_UART_Receive(): 串口接收数据,使用超时管理机制

2.中断模式收发数据
        HAL_UART_Transmit_IT():串口中断模式发送
        HAL_UART_Receive_IT(): 串口中断模式接收

3.DMA模式收发数据
        HAL_UART_Transmit_DMA():串口DMA模式发送
        HAL_UART_Transmit_DMA():串口DMA模式接收

1.阻塞模式 

1.1 阻塞模式发送函数

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

该函数的作用是将数据通过UART发送到外部设备或其他设备。

参数说明:

  • huart: UART句柄,表示要使用的UART外设。
  • pData: 要发送的数据的指针,即数据的起始地址。
  • Size: 要发送的数据的大小,以字节为单位。用sizeof()函数获取发送缓冲区的长度
  • Timeout: 发送的超时时间,单位为毫秒。如果在指定的时间内发送完成,则函数返回 HAL_OK;否则,返回 HAL_TIMEOUT如果设置为HAL_MAX_DELAY,处理器就会一直等到数据发送完成再执行下一条语句。

1.2 阻塞模式接收函数

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

它的作用是从UART接收数据,并将接收到的数据存储到指定的缓冲区中。

参数说明:

  第一个参数是要使用的串口句柄地址
  第二个参数是要接收的数据缓冲区首地址
  第三个参数是接收的数据长度,这里可以直接用sizeof()函数获取接收缓冲区的长度
  第四个参数是超时时间,单位是ms,如果超过设置的时间,则函数返回HAL_TIMEOUT,如果设置为HAL_MAX_DELAY,处理器就会一直等到数据发送完成再执行下一条语句。

1.3 STM32CubeMX配置

 第一步:选择SYS的Debug-Serial Wire,开启SWD调试;

第二步: 时钟配置,选择RCC的 HSE -> Crystal/Ceramic Resonator(外部晶振)

紧接着配置时钟树  ⬇  ⬇  ⬇  ⬇ 

第三步:配置USART,设置参数

配置完成,生成初始化代码(Project和Code Generator里的配置请参考之前那篇串口中断的贴子,熟悉之后就可以直接嘎嘎点)

1.4 代码编写

测试阻塞模式发送函数

在main.c里,定义一个发送数组缓冲区TxBuf数组;

在while(1)循环里添加阻塞发送函数和1s的延时,实现效果是每隔1s串口发送一次TxBuf数组里的“Hello World!!我爱单片机!!” 并在串口助手上显示;

  1. HAL_Delay(1000);
  2. HAL_UART_Transmit(&huart1, TxBuf, sizeof(TxBuf), 100);

最终显示效果如下图所示: 

测试阻塞模式接收函数

首先定义一个接收缓冲区数组RXBuf[4],1个16进制数是4bit,两个16进制数是1byte(8bit),设置的缓冲区类型是uint8_t(8bit),数组大小是4字节,所以要发送8个16进制数正好填满缓冲区。

注意:接收缓冲区长度可以大于要接收数据的长度,但是不能小于要接收的数据长度。

while循环里添加串口接收和串口发送函数代码: 

  1. //从RxBuf接收缓冲区中接收数据,如果在1秒内没有接收完数据,函数将返回超时错误,接收完返回HAL_OK
  2. if(HAL_UART_Receive(&huart1, RxBuf, sizeof(RxBuf), 1000) == HAL_OK)
  3. { // 如果成功接收到数据
  4. // 将接收到的数据原样发送回UART1,如果在1秒内没有发送完数据,函数将返回超时错误。
  5. HAL_UART_Transmit(&huart1, RxBuf, sizeof(RxBuf), 1000);
  6. }

串口助手显示:

HEX模式是十六进制模式,当我们用电脑以HEX模式给单片机发送数据时,发的是十六进制,单片机接收的也是十六进制; 

注意:串口助手要打开HEX发送和HEX接收 

2.中断模式

2.1 中断模式发送函数

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

这个函数的目的是启动UART传输并以非阻塞的方式发送一定数量的数据。

参数说明:中断方式的收发函数只有三个参数
      第一个参数是要使用的串口句柄地址
      第二个参数是发送缓冲区的首地址,用于存放要发送的数据
      第三个参数是发送缓冲区长度

2.2 中断模式接收函数

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

参数说明与发送函数类似,只是把第二个和第三个参数变为了接收缓冲区

        中断模式的前三个参数和阻塞方式完全一致,只是没有了超时时间管理,因为中断(IT)方式配置完成寄存器之后不需要再占用CPU,会在接收/发送数据完成后触发中断,因此不需要超时时间管理机制。

2.3 STM32CubeMX配置

在之间的基础上再选择 NVIC Settings,勾选Enable,再次生成代码

2.4 代码编写

在开始的时候我们需要先启动一次异步接收 HAL_UART_Receive_IT();  

 之后添加串口回调函数,当串口接收到sizeof(RxBuf)大小的数据时,会产生串口接收中断,然后进入到中断服务函数中,执行对应的串口接收回调函数里面的代码。

 这段代码的意思是:判断串口是否为串口1,如果是的话,串口发送ACKBuf数组里面的数据,显示在串口助手的界面上。

  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  2. {
  3. if(huart == &huart1) // 判断串口号是否为 huart1
  4. {
  5. // 发送 ACKBuf 的缓冲区的数据到 UART1,使用中断模式发送
  6. HAL_UART_Transmit_IT(&huart1, ACKBuf, sizeof(ACKBuf));
  7. }
  8. // 重新启动 UART1 的中断接收,将接收到的数据存放到 RxBuf 的缓冲区中
  9. HAL_UART_Receive_IT(&huart1, RxBuf, sizeof(RxBuf));
  10. }

 串口显示:

3.DMA模式

3.1 什么是DMA

DMA(Direct Memory Access,直接内存访问)是一种计算机系统中用于数据传输的机制。它允许数据在外设和内存之间直接传输,而不需要CPU的介入,从而减轻了CPU的负担,提高了数据传输的效率。

举个栗子:

        想象一下我们搬家的场景:你要把家里的一些东西从旧房子搬到新房子。在传统的情况下,你可能要亲自搬每一箱东西,把它们从旧房子搬到新房子。这就相当于CPU传统地处理数据传输的方式。

        现在,有一支搬家队,他们专门负责搬家。你只需要告诉他们从哪里搬,搬到哪里,然后他们就会自己完成这项任务。而你可以利用这段时间去做其他事情,不需要亲自动手。这就有点类似于DMA的工作原理。

        在计算机中,CPU通常会处理数据的传输工作,就像你亲自搬家一样。但有了DMA,就好比有了一支专门负责数据传输的队伍。CPU只需要告诉DMA从哪里搬,搬到哪里,然后就可以去处理其他任务了。DMA负责在外设和内存之间直接传输数据,而不需要CPU一直参与。

简而言之,DMA就像是一支搬家队伍,负责在不需要CPU亲自操劳的情况下完成数据传输任务,从而提高了系统的效率。

3.2 DMA模式发送函数

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

参数类型和中断模式发送函数相同

3.3 DMA模式接收函数

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

参数类型和中断模式接收函数相同 

3.4 STM32CubeMX配置

使用DMA时必须开启中断!!

优先级选择: 

 DMA配置:

3.5 代码编写 

同理也要先开启一次DMA接收;

  1. // 串口收到数据的回调函数
  2. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  3. { // 判断触发回调的 UART 句柄是否为 huart1
  4. if(huart == &huart1) // 如果串口是 UART1
  5. { // 使用 DMA 模式将 RxBuf 的缓冲区的数据原样发送回 UART1
  6. HAL_UART_Transmit_DMA(&huart1, RxBuf, sizeof(RxBuf));
  7. }
  8. // 使用 DMA 模式重新启动 UART1 的接收,将接收到的数据存放到 RxBuf 缓冲区中
  9. HAL_UART_Receive_DMA(&huart1, RxBuf, sizeof(RxBuf));
  10. }

 串口显示:

总结

串口助手接收区显示的数据,就是通过 HAL_UART_Transmit、HAL_UART_Transmit_IT、HAL_UART_Transmit_DMA这三个之一的发送函数,把发送缓冲区数组里的数据发送到外面。

发送区用户输入的数据,通过接收函数,存到接收缓冲区数组中,以便与发送函数发送。

中断模式和DMA(normal)模式下接收数据,都需要在初始化时开启一次中断/DMA接收,并且在接收回调函数中重启一次中断/DMA接收,才能实现循环发送。

以上就是初步探索HAL库实现串口接收和发送的三种方式,继续进步!!

完结!!!撒花!!      *★,°*:.☆( ̄▽ ̄)/$:*.°★*  


本篇完。

本人博客仅代表个人见解方便记录成长笔记。

若有不足,请指出,感谢您的阅读!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/855067
推荐阅读
相关标签
  

闽ICP备14008679号