STM32利用DMA发送无法正确发送数据的问题

一、现象:

在子函数中,定义了一个局部变量sendbuf[8] ={1,2,3,4,5,6,7,8},然后分别利用普通串口发送函数发送可以正常发送和利用DMA发送,并利用串口调试助手查看,发现助手可以正确接收普通串口发送函数所发出的数据,而对于DMA发送的数据,接收到的是一堆乱码。

二、原因:

1、 普通串口发送函数是阻塞型的,比如将上述sendbuf[8]每一个字节发送出去,低层代码逻辑是将1移位到串口的TX寄存器里,硬件检测到后在适当的时间发送出去。在未发送出去前,需要判断TX寄存器是否为空,即判断标志位USART_FLAG_TXE或者USART_FLAG_TC,如果没有发送成功就while阻塞(hal库中升级了,hal库设定超时机制,如果等待时间过长,就直接返回超时错误),一直阻塞到1发送出去后,再将2放到TX的寄存器里,一直将sendbuf[8]里的数发完为止。因此只要没有发送完,子函数就无法返回,在发送期间局部变量数组sendbuf是一直存在的。直到发送完成后子函数返回。

2、 DMA发送是非阻塞的。在子函数中调用DMA发送一个数组时,实际上是将数组的地址给DMA,告诉单片机,从这个地址开始的N位数是需要发的,你有空的时候发出去就行。因此当你调用DMA发送函数的时候,你只是下达了一个需要发送的命令,但是数据并没有即时发送出去,程序也不会阻塞在DMA发送函数,子函数直接返回了。返回以后局部变量sendbuf将失去意义。sendbuf所指向的地址里的数据是啥你根本无法知晓。当单片机闲下来了觉得自己可以去按照地址去寻这些数的时候,这些数早就物是人非了。发出去的数也就是乱码的

一些BUG现象:

对于不清楚DMA是非阻塞机制的朋友,有的会尝试打断点一行一行往下顺,发现一行一行顺的时候,发出来的数据是对的;但是全速运行的时候就是错的。错的原因上面已经解释了,对于一行一行顺的时候为什么成功,因为你人工形成了程序阻塞,逼着单片机在子函数返回之前去读地址里的数,不发出去你不返回,单片机没办法只能照办。但一全速就飞了。

三、解决方案:

如果了解了DMA非阻塞机制,怎么解决其实很简单,切入点就是,寻址数要在。当单片机闲下来,去寻找地址里的数时,那个地址要还是那个数。不能因为子函数返回就没了。
所以解决方案很简单,发送数组设置成全局变量数组就行。 当子函数返回时,你不用催着单片机发送,数组里的数也不会飞。等到单片机想发送的时候,去寻数也能找到。

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值