使用LL库开发STM32:UART进阶使用(DMA循环接收 + UART空闲中断)

目的

在前面文章 《使用LL库开发STM32:UART基础使用》 中介绍了使用LL库开发UART的一些基本操作。实际使用中直接这么使用还是不太方便的,也会遇到很多问题,这篇文章就稍稍说一些更进一步的使用方法。

注1:在STM32开发时因为默认分配的堆内存不大,我个人比起使用malloc或是new方法申请内存,更多的喜欢把数据放在静态区域;(这样编译的时候也可以看到内存占用情况)
注2:本文中有些功能使用C++作为演示,实际使用中也可以自行改为纯C代码实现;

发送处理

STM32中UART发送数据最好用的方式就是通过DMA发送数据了,这种方式下只要指定要发送的数据的地址和数据长度,DMA就会依次自动将数据传输到UART上发送出去。但这个方式方便归方便,但稍稍还是会存在一点点问题的,所以需要进一步处理。相关内容可以参考 《使用HAL库开发STM32:UART进阶使用》 这篇文章中 《发送处理》 章节。

另外HAL库中UART通过DMA发送数据只需要一个函数就能搞定,但在LL库中每次重新发送数据就需要好几个函数同时操作了,主要步骤如下:

  • 清除DMA传输完成中断;
  • 失能DMA流或通道数据传输;
  • 设置要传输的数据地址与数据长度;
  • 使能DMA流或通道数据传输;

为了方便使用我对此进行了简单的封装,可以在本篇文章末尾的链接查看代码、例程、说明。(参考 lib_hal_uart 中 Lib_LL_UartTx 类

数据接收与解析

和发送相比UART接收到真正使用更加麻烦点,因为接收的时候会有更多不确定性,数据长度不定、数据传输出错等等各种问题。一般的串口通讯中会制定一些带有校验功能的协议,只有接收到符合协议的数据才进行响应。一般的来说数据接收可以按下面方式处理:
在这里插入图片描述

在STM32单片机中我一般使用 DMA循环接收 + UART空闲中断 的方式来处理这块业务:

  • 声明一个静态数组作为数据缓存,DMA循环将收到的数据放到该缓存中;
  • 然后启用UART的空闲中断,当每次进入空闲中断时对接到的数据进行解析处理;
  • 如果接收到符合需求的数据则调用相应的回调函数进行处理;

对于这块操作我也进行了简单的封装,下面是个演示(可以点击查看大图),该演示中数据解析部分处理了对 Modbus-Rtu 协议格式的数据解析:

  • 初始化配置
    在这里插入图片描述
  • 使用代码
    在这里插入图片描述
  • 使用演示
    在这里插入图片描述

上面演示中的代码、例程、说明都可以在本篇文章末尾的链接查看。

总结

串口是蛮常用的功能,为了使使用时更顺手花时间整点工具还是值得的。这篇文章主要是提供了一种思路。

上面的工具与例程在这里:
https://github.com/NaisuXu/STM32-tool-library-based-on-HAL-and-LL

S32K144是恩智浦(NXP)推出的一款32位汽车级微控制器(MCU),广泛应用于汽车和工业控制等领域。DMA(直接内存访问)是一种允许硬件子系统直接读写系统内存的技术,而无需CPU的介入,这可以大大提高数据传输的效率。UART(通用异步收发传输器)是一种常用的串行通信接口。 在S32K144中使用DMA进行UART空闲中断接收的例程,主要涉及到以下几个步骤: 1. 初始化UART模块,配置波特率、数据位、停止位和校验位等参数,确保UART通信正常工作。 2. 初始化DMA模块,设置传输数据的源地址、目标地址和传输大小等参数。源地址通常是UART接收缓冲区的地址,目标地址可以是用户自定义的RAM缓冲区地址。 3. 配置DMA触发源为UART空闲中断,当UART接收到数据并保持空闲状态一段时间后,触发DMA传输。 4. 配置DMA传输模式,根据需求选择合适的传输方向(从UART到内存)和传输类型(循环或单次传输)。 5. 开启DMA通道,并使能UART空闲中断。 6. 在DMA中断服务程序中添加适当的处理逻辑,比如处理接收到的数据,以及在数据处理完毕后重新启动DMA接收等。 下面是一个简化的代码示例框架,用于说明如何实现上述功能: ```c #include "S32K144.h" // UART初始化函数 void UART_Init(void) { // 这里填写初始化UART的代码,配置波特率等相关参数 } // DMA初始化函数 void DMA_Init(void) { // 这里填写初始化DMA的代码,配置源地址、目标地址和传输大小等参数 } // UART空闲中断处理函数 void UART1_RX_IDLE_ISR(void) { // 这里填写处理接收到的数据的代码 // 处理完毕后,可以停止当前DMA传输并重新启动新的DMA传输 } int main(void) { UART_Init(); // 初始化UART DMA_Init(); // 初始化DMA // 配置UART空闲中断,使能DMA接收 // 主循环 while(1) { // 用户代码 } } // 假设的DMA中断服务程序 void DMA채널中断服务程序(void) { // 中断处理代码,这里需要根据实际的DMA通道和中断向量填写 } ``` 注意:上述代码仅提供一个框架性的示例,实际编写时需要根据S32K144的具体寄存器配置和中断向量表来编写详细的初始化和中断处理函数。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Naisu Xu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值