stm32f103 标准库-UCOSIII-uart串口 dma 空闲接收中断 以及 实际APP应用场景

STM32F103 UCOSIII UART串口空闲DMA接收

以及 实际产品中的应用方式(标准库3.5版本)

1. 修订记录

日期修订版本描述修订人
2021-5-4v1原理和产品应用讲解微信: pingdanv3314

有完整的产品上用的代码,会上传到CSDN下载中,请朋友们自己下载,这里主要是从框架整体上做讲解,

不会挨个讲代码,没啥意义;

2. 实际产品中应用的交互协议-JSON格式

2.1、协议举例-其中一个命令

大部分情况下,1个数据包的长度都小于1024字节,在本地局域网中都可以直接1次性发送完成

比如常用的有人的 以太网,WIFI等模组–这个时候使用DMA空闲中断接收串口数据包优势就非常明显了

不用做断帧判断,只需要做数据包的格式 和 完整性判断,这个非常方便写代码,不容易出错;

命令协议距离:

主轴运动 绝对脉冲数

请求参数
参数类型描述
cmdInt命令代码
action_idInt唯一序号
plusCntXInt
plusCntYInt
应答
参数类型描述
action_idInt唯一序号
statusString“0”=成功,或其他错误描述信息
示例

请求:

{
   "cmd":5,
   "action_id ":1234,
   
   "plusCntX":300,
   "plusCntY":400
}

应答:

{
 	"action_id ":1234,
    "status":"0"
}

3、DMA串口空闲接收原理

原理讲解:

当串口初始化完成后,串口就保持为接收状态,之后有数据来就开始接收数据,一旦没有数据停止发送的时间超过了固定的时间

(这个时间一般是 一个字节的传输时间,所以不同的比特率对应不同的时间,如果实际应用中,中途间隔比较大,就需要使用硬件定时器的方式,来加大这个时间:在空闲中断中启动定时器,并且将已经接收的字节搬运到缓冲区中)

,就会触发串口的空闲中断,注意不是DMA的,此时DMA还是正常接收的,然后再空闲中断中 赶紧把 DMA停止,搬运接收到的数据 到 自定义的缓冲区中,此时就完成了一次一包数据的接收;

所以:串口的空闲中断 和 DMA 是同时分开执行的,并不是空闲中断发生了DMA就停止了,所以之后应用层要赶紧把数据取出来,不然数据就可能被 新的数据覆盖;

DMA通道的选择: 请看STM32中文参考手册的DMA章节
在这里插入图片描述

在这里插入图片描述

根据上面的指示,在初始化代码中选择就行;

粘贴部分代码:

串口3配置初始化,串口空闲中断 和 对应DMA通道初始化:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对应的串口空闲中断代码:
在这里插入图片描述

这里一旦触发了中断,就重启了DMA接收,此时一旦立即有新数据发送过来的化,之前接收的数据肯定被覆盖了,所有需要根究自己的产品的交互速度 设计是否是共享内存,还是消息队列的,因为STM32F103的内存毕竟就这么点;

如果对端连续发送数据命令过来,那么中途的指令肯定会被丢掉很多,要注意整个系统的设计结构;

APP中的主程序就一直等待信号量的通知,然后将数据拷贝出来:
在这里插入图片描述

4、DMA启动的通道太多也会出问题,会阻塞卡顿

STM32F103的我没有使用到很多个DMA都启动的场景,,但是在STM32H743上就使用了很多的DMA通道,而且数据的收发非常快,且频繁,此时就可能出现DMA频繁仲裁,就可能导致卡顿

因为DMA都是要和内存SRAM打交道的,如果DMA非常频繁,就可能出现总线冲突,就需要冲裁了,这个时候就可能导致卡顿阻塞;所以DMA也不是万能的,也不可能完全解放CPU

在这里插入图片描述

这个系统由 14个DMA通道

主串口-和FPAG交互的串口 是 200字节,921600,2.5MS一次400HZ的速度接收的 ,速度非常快,光发送时间就占用了1.7MS左右

然后需要根据设置的 转发参数,同步的将接收的这个高频数据,转发到其他串口 和 SD卡保存;

此时对于内存的操作就非常繁忙了,哪怕CPU是空闲的,也可能导致处理速度跟不上节奏;

5、下载代码地址:

请搜索:

stm32f103 标准库-uart串口 dma 空闲接收中断 以及 实际APP应用场景

或者
加wv :pingdanv3314 索取

6、欢迎联系沟通交流

                                       weixin :  pingdanv3314

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对STM32G4HAL串口空闲中断接收不定长数据的问题,可以按照以下步骤进行解决: 1. 开启串口空闲中断,即在初始化串口时,将USART_CR1_REG中的USART_CR1_IDLEIE位设置为1。 2. 在串口空闲中断中,通过读取USART_ISR_REG寄存器中的位USART_ISR_RXNE和USART_ISR_IDLE来判断是接收到数据还是空闲中断。 3. 如果是接收到数据,则读取USART_RDR_REG寄存器中的数据,并将其存储到缓冲区中。 4. 如果是空闲中断,则通过计算接收到的数据长度来确定数据的长度,并将其存储到缓冲区中。 5. 在数据长度达到预定长度时,可以通过回调函数或者其他方式来通知数据接收已经完成。 下面是一个示例代码: ```c uint8_t rx_buffer[100]; uint8_t rx_counter = 0; uint8_t rx_length = 0; uint8_t rx_flag = 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USARTx) { if(rx_flag == 0) { //接收到数据 if((__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) == RESET)) { rx_buffer[rx_counter++] = (uint8_t)(huart->Instance->RDR & 0x00FF); } //空闲中断 else if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET) { rx_length = rx_counter; rx_counter = 0; rx_flag = 1; } } } } ``` 在上面的代码中,当接收到数据时,将数据存储到缓冲区中,并将计数器rx_counter加1。当空闲中断发生时,计算接收到的数据长度,并将其存储到rx_length中。在接收完成后,将rx_flag设置为1,表示数据接收已经完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值