STM32
直播中

李皓圳

7年用户 1056经验值
私信 关注
[问答]

如何去实现UART阻塞方式收发数据呢

如何去实现UART阻塞方式收发数据呢?
如何去实现UART中断方式收发数据呢?

回帖(1)

陈桂平

2021-12-8 14:03:40
0x01 UART阻塞方式收发

CubeMX or CubeIDE配置
1.开启debug





2.使用外部晶振
    如果你的板子上没有晶振的话,就不要开了,不然stm32跑不起来





时钟配置(根据自己板子上的晶振频率酌情设置)





注: HSE:外部高速晶振        LSE:外部低速晶振
3.设置USART1为异步模式,无硬件流控





4.设置参数





5.生成代码
    快捷键:Alt+K 或者 点图中的小齿轮





我们已经完成了基本配置并生成了初始化代码
UART阻塞方式收发

接下来学习UART阻塞方式发送数据
1.编写代码
    打开main.c





添加要发送的字符串





先看一下要用到的函数





    可以看到,这个函数一共有四个参数,
    第一个参数是要使用的串口句柄地址,比如要使用U(S)ART1,参数就设置为U(S)ART1的句柄地址&huart1
    第二个参数是要发送的数据缓冲区首地址
    第三个参数是发送的数据长度,这里可以直接用sizeof()函数获取发送缓冲区的长度
    第四个参数是超时时间,单位是ms,如果超过设置的时间,则函数返回HAL_TIMEOUT,如果设置为HAL_MAX_DELAY,处理器就会一直等到数据发送完成再执行下一条语句。
2.使用函数
在main.c的while循环中添加代码





3.烧录运行
   连接stlink/jlink到板子
   连接USB/TTL到板子上,rx,tx分别接stm32板子上tx,rx
   然后点图中的绿色三角 或者 按下快捷键R+R





如果一切正常的话,就会看到





然后用串口助手打开TTL的端口就可以看到





我们已经完成了UART阻塞方式发送数据
再尝试一下UART阻塞方式接受数据
1.需要学习的函数





    同HAL_UART_Transmit()函数一样,这个函数也有四个参数
    第一个参数是要使用的串口句柄地址,比如要使用U(S)ART1,参数就设置为U(S)ART1的句柄地址&huart1
    第二个参数是接受数据的缓冲区首地址
    第三个参数是接受的数据长度,这里可以直接用sizeof()函数获取接受缓冲区的长度
    第四个参数是超时时间,单位是ms,如果超过设置的时间,则函数返回HAL_TIMEOUT,如果设置为HAL_MAX_DELAY,处理器就会一直等到接受到设置好的数据数量再执行下一条语句。
目标:将接受到的数据发送回主机
2.编写代码
    设置好接收缓冲区
    Tip:接受缓冲区长度可以大于要接受数据的长度,但是不能小于要接受的数据长度。





在while()编写业务代码





3.烧录测试
    连接好TTL和stlink
    快捷键R+R下载
一位16进制数正好是4bit,所以两位16进制正好是1byte(8bit)
我设置的缓冲区类型是uint8_t(8bit),长度是4
所以我要发送8位16进制数正好填满缓冲区
ps:串口助手要打开HEX发送和HEX接收





效果





串口printf()重定向

使用HAL_UART_Transmit发送字符串很不方便
可以重定向printf()函数使printf通过串口打印字符串
上代码

#include "stdio.h"

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



编写业务代码





效果





UART中断方式收发

1.CubeMX/CubeIDE 图形化配置
使能USART1 全局中断





2.需要学习的函数
中断方式发送函数





中断方式接受函数





中断方式的收发函数只有三个参数
第一个参数时要使用的串口句柄地址
第二个参数是发送/接受缓冲区的首地址,用于存放要发送/接收的数据
第三个参数是发送/接受缓冲区长度
前三个参数和阻塞方式完全一致,为什么没有超时时间了呢?
因为中断(IT)方式配置完成寄存器之后不需要再占用CPU,会在接受完成后触发中断。

      阻塞方式就好比你要拿快递,就一遍遍都前台询问快递到没到,在这期间你不能干别的,
中断方式是你告诉前台快递到了给你打电话,在这期间你是可以腾出身子来干别的事情。
由此可见,中断方式效率大于阻塞方式,极端情况下,中断方式的安全性也高于阻塞方式
接收中断回调函数





顾名思义,该函数是当中断方式串口接收触发中断(接收完成)所调用的函数
    该函数的返回值为__weak,表示这个函数需要用户自己去编写,最终会执行用户所自行编写的回调函数(如果用户不编写,也会执行自带的回调函数,只不过自带的HAL_UART_RxCpltCallback()函数是空函数,所以等同于什么也没有做)
注意:用户自行编写的回调函数返回值不能为__weak。
会有同学问,有没有发送中断回调函数呢?
答案是,有的,但是直接把发送完要执行的语句写到发送语句的后面不就好了吗T^T
3.代码编写
目标:


  • 使用HAL_UART_Receive_IT()函数接受指定数量的数据存到指定缓冲区;
  • 编写接受回调函数,回调函数作用是当回调函数被执行后判断是否是usart1所触发的中断,如果是,就使用HAL_UART_Transmit_IT()函数给主机发送指定内容的应答数据。

动手操作:
声明一个接受缓冲区(Rxbuf)和应答数据(ACKbuf)





main()中编写业务代码





重写回调函数





4.烧录测试
    快捷键R+R或者点绿色小三角烧录
效果:





DMA方式串口收发

1.什么是DMA
知识拓展链接:百度-DMA

      前文说过中断方式就好比你告诉前台,等快递到了给你打电话,让你亲自来取,假设你正在做着一些重要的事情,正好来了电话让你取快递,这样一来就会耽误事。
     这怎么办呢?雇个保姆不就好了吗,DMA就好比这个保姆,你告诉她在哪里取快递,她就会等快递到了之后自己帮你把快递拿回家。
2.软件配置(一定要看图啊)





3.需要学习的函数
    DMA方式串口发送函数





该函数一共有三个参数
参数类型和中断类型串口发送函数一样,不再赘述
    DMA方式串口接收函数





该函数一共有三个参数
参数类型和中断类型串口发送 函数一样,不再赘述
3.代码编写
任务:
    使用DMA方式串口收发方式进行回环测试
声明一个缓冲区





编写业务代码





编写中断回调函数:
    注意:UART一旦开启DMA之后,DMA收发中断都是强制开启的,所以DMA收发函数也可以编写回调函数。





4.烧录测试
    快捷键R+R或者点绿色小三角烧录
效果:





拒绝白嫖,点个赞吧
举报

更多回帖

发帖
×
20
完善资料,
赚取积分