搜索
bottom↓
回复: 34

STM32H7串口向外不停发送数据,容易造成接收无法进入中断,求解

[复制链接]

出0入91汤圆

发表于 2023-4-19 14:25:23 | 显示全部楼层 |阅读模式
如题

做的STM32H7 是一个屏幕,需要时刻和 主板进行串口通讯(发送和接收)

如果发送不频繁, 比方说安下按键发送一次数据,  那接收没出现过问题(也可能是出现的概率极低,没被察觉)
但是如果改成 发送 每几十ms 发送一个字节,然后循环发送的情况(这样不怕干扰丢数据,因为会重复发送)

也就是发送一直进行的时候, 容易工作很久后, 接收就卡住了,debug后发现是无法进入接收中断  HAL_UART_RxCpltCallback

HAL_UART_Transmit_IT和  HAL_UART_Transmit     两种发送 都测试过 ,都会造成问题复现


现在中断优先级串口是改成0 0的。   网上说很可能是发送的过程中  被接收打断,但是接收发现串口正忙,就没触发中断,导致HAL_UART_Receive_IT  这句没执行,不再进入接收中断了


大家有好的解决思路吗? 有人提出 在发送结束后都加一句 HAL_UART_Receive_IT开启接收中断(还没测试)但是感觉不靠谱

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2023-4-19 14:28:02 | 显示全部楼层
都H7了,为啥串口不用DMA

出0入91汤圆

 楼主| 发表于 2023-4-19 14:30:22 | 显示全部楼层
mypear 发表于 2023-4-19 14:28
都H7了,为啥串口不用DMA
(引用自2楼)

  因为 同样的情况下 , STC  竟然 可以一直发一直收,  但是性能更强的STM32竟然死掉了  不可思议

而且  我这应用应该也不算复杂情况了


为了减少传输的数据量太大,  我一个帧的数据  都是拆分 一个数据  一次的发送了 ,  发送完后等待很一段时间再发送下一个字节

出0入91汤圆

 楼主| 发表于 2023-4-19 14:31:09 | 显示全部楼层
mypear 发表于 2023-4-19 14:28
都H7了,为啥串口不用DMA
(引用自2楼)

如果用DMA就不会有这个问题了吗?

出0入75汤圆

发表于 2023-4-19 14:36:25 | 显示全部楼层
接收是怎么写的?HAL_UART_Receive_IT(&huart, , 1);这样写的吗?如果是,改成其他方式,接收数量不要写1。

出0入91汤圆

 楼主| 发表于 2023-4-19 14:38:49 | 显示全部楼层
Doding 发表于 2023-4-19 14:36
接收是怎么写的?HAL_UART_Receive_IT(&huart, , 1);这样写的吗?如果是,改成其他方式,接收数量不要写1。 ...
(引用自5楼)

是的 接收也是1     这样进来的数据就不用对位了

有什么讲究吗?   放1 会出现什么样的问题呢

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
        if(huart->Instance == UART5)       
        {
                READ_DATA[0]=READ_DATA[1];
                READ_DATA[1]=READ_DATA[2];
                READ_DATA[2]=READ_DATA[3];
                READ_DATA[3]=READ_DATA[4];
                READ_DATA[4]=READ_DATA[5];
                READ_DATA[5]=READ_DATA[6];
                READ_DATA[6]=READ_DATA[7];
                READ_DATA[7]=RxBuffer[0];
               
                uart_receice_flag=1;
                       
                HAL_UART_Receive_IT(&huart5,RxBuffer,1);                        // Enable the USART5 Interrupt
        }
}

出0入0汤圆

发表于 2023-4-19 14:39:27 | 显示全部楼层
DMA+FIFO,可以考虑一下

出0入91汤圆

 楼主| 发表于 2023-4-19 14:40:54 | 显示全部楼层
jbpan852 发表于 2023-4-19 14:39
DMA+FIFO,可以考虑一下
(引用自7楼)

谢谢,我先研究下 如果解决不了 就只能上DMA了

出0入0汤圆

发表于 2023-4-19 14:47:19 来自手机 | 显示全部楼层
看看芯片手册,理解下UART硬件,写个寄存器不到10行的事情。

ST的HAL完全是垃圾。

出0入91汤圆

 楼主| 发表于 2023-4-19 14:50:04 | 显示全部楼层
MasterPhi 发表于 2023-4-19 14:47
看看芯片手册,理解下UART硬件,写个寄存器不到10行的事情。

ST的HAL完全是垃圾。 ...
(引用自9楼)


我有点不太理解     STC 这样的 串口 是  开启中断后, 一直都会接收数据

但是 STM32 竟然  接收进入中断后,  要手动开启下一次接收才行 (如果能像STC这样,永远中断工作, 那我这个问题也不用纠结了,现在是 打断一次 永远 不再开启下次接收了)

我不确定这个坑是否是 HAL 带来的  

出0入75汤圆

发表于 2023-4-19 14:50:39 | 显示全部楼层
本帖最后由 Doding 于 2023-4-19 14:52 编辑
ackyee 发表于 2023-4-19 14:38
是的 接收也是1     这样进来的数据就不用对位了

有什么讲究吗?   放1 会出现什么样的问题呢
(引用自6楼)


接收数据长度为1,串口每收到一个字节后会关中断,清标志位,在Rxcplt里再调用Receive_IT,会再把中断打开,每收一字节都要开关一次中断。
如果数据长度已知,直接写数据长度,如果数据长度未知但数据连续,用空闲中断+DMA接收,如果长度未知且不连续,用LL库吧。

出0入91汤圆

 楼主| 发表于 2023-4-19 14:54:20 | 显示全部楼层
Doding 发表于 2023-4-19 14:50
接收数据长度为1,串口每收到一个字节后会关中断,清标志位,在Rxcplt里再调用Receive_IT,会再把中断打 ...
(引用自11楼)


感觉这个问题应该是   cubemx 的库引起的

接收到数据后 ,即使判断串口忙,不能进入中断, 那也应该帮我使能下一次接收对吧

现在这个库 直接帮我给干罢工了

出0入75汤圆

发表于 2023-4-19 15:02:56 | 显示全部楼层
ackyee 发表于 2023-4-19 14:54
感觉这个问题应该是   cubemx 的库引起的

接收到数据后 ,即使判断串口忙,不能进入中断, 那也应该帮我 ...
(引用自12楼)

不是串口忙无法处理,是在频繁开关接收中断,丢数据就很正常了。
在调用HAL_UART_Receive_IT时,已经告诉库需要接收的数据长度是1字节,收完1字节后自然会关中断,如果需要收8个字节,在长度参数那直接写8就行了,在收到8个字节之前不会关中断。
不定长的数据,如果连续,配置好串口DMA,用HAL_UARTEx_ReceiveToIdle_IT,在HAL_UARTEx_RxEventCallback里处理收到的数据就可以了。

出0入1209汤圆

发表于 2023-4-19 15:04:59 | 显示全部楼层
串口空闲中断/超时中断+DMA很爽的,数据量特别大的可以再加一个环形缓冲,这是标准用法了,跟用什么库没关系

出0入0汤圆

发表于 2023-4-19 16:24:32 | 显示全部楼层
ackyee 发表于 2023-4-19 14:31
如果用DMA就不会有这个问题了吗?
(引用自4楼)

DMA不占CPU

出20入186汤圆

发表于 2023-4-19 16:50:37 | 显示全部楼层
看下UART的状态寄存器,持掉的时候是不是有异常状态产生?

出0入0汤圆

发表于 2023-4-21 00:27:54 来自手机 | 显示全部楼层
你是不是复制的例程上的代码,

出1310入193汤圆

发表于 2023-4-21 08:19:11 | 显示全部楼层
3318156 发表于 2023-4-21 00:27
你是不是复制的例程上的代码,
(引用自17楼)

关键说清楚了

出0入45汤圆

发表于 2023-4-21 13:47:34 | 显示全部楼层
串口接收用DMA+idle中断,很流行,idle中断后把DMA接到的数据复制出来解析;
如果配置了freertos,串口接收是一个任务,发送是一个任务,就更妥了

出105入79汤圆

发表于 2023-4-21 14:55:47 | 显示全部楼层
H7串口我用了很久,建议用DMA发送。 IT发送要规避HAL的锁,也就是发送前强制释放锁:__HAL_UNLOCK(huart);

出130入129汤圆

发表于 2023-4-21 15:15:31 | 显示全部楼层
是被HAL库调戏了吧

出0入91汤圆

 楼主| 发表于 2023-4-21 16:13:20 | 显示全部楼层
3318156 发表于 2023-4-21 00:27
你是不是复制的例程上的代码,
(引用自17楼)

哈哈,cubemx 的hal库, 然后初始化这些都自动设置好了 ,自己只是增加了个回调函数,  流程应该没问题了

估计就是互相 关中断  锁外设的问题了

出0入91汤圆

 楼主| 发表于 2023-4-21 16:13:53 | 显示全部楼层
qwe2231695 发表于 2023-4-21 14:55
H7串口我用了很久,建议用DMA发送。 IT发送要规避HAL的锁,也就是发送前强制释放锁:__HAL_UNLOCK(huart); ...
(引用自20楼)

感觉你的方向比较接近了


我待会查查看代码框架里是否有锁 串口的地方

出105入79汤圆

发表于 2023-4-21 17:06:45 | 显示全部楼层
本帖最后由 qwe2231695 于 2023-4-21 17:08 编辑
ackyee 发表于 2023-4-21 16:13
感觉你的方向比较接近了


(引用自23楼)


HAL在接收中断时会自动锁上,导致你发送的时候没有获得锁,导致失败。

关于DMA 和 IDEL接收可以看我写的笔记https://blog.csdn.net/cqy1028/article/details/117408683

出0入91汤圆

 楼主| 发表于 2023-4-22 10:06:03 | 显示全部楼层
qwe2231695 发表于 2023-4-21 17:06
HAL在接收中断时会自动锁上,导致你发送的时候没有获得锁,导致失败。

关于DMA 和 IDEL接收可以看我写的 ...
(引用自24楼)

但是发送的数据一直都有 ,   接收被打断一次后 永远不再进入了

我也怀疑 接收中断进入了 但是还没进入回调函数的时候 被发送打断了,  然后回调函数没有正确进入  就无法 使能下一次接收了

出105入79汤圆

发表于 2023-4-22 16:20:26 | 显示全部楼层
是的,就是”接收被打断一次后 永远不再进入了“。 只要在再次开启接收前__HAL_UNLOCK(huart);

并且实现
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)

在里面再
__HAL_UNLOCK(huart);
__HAL_UART_CLEAR_OREFLAG(huart);

出0入475汤圆

发表于 2023-4-22 16:56:16 来自手机 | 显示全部楼层
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说,无非就是初始化的时候开启好接收中断,然后在中断函数里面把接收的内容搬运到外部循环的缓冲中去吗?要是这么高的速度的芯片,我估计大部分运算啊判断啊一类的处理即使放在串口中断处理函数里面进行又何妨嘛,
不知道为啥要弄那么复杂,复杂到自己都不知道哪里有问题
还有就是,好多地方的思路是,中断进去后要关中断使能,这点我是到现在都没有明白,为啥要关呢?如果是说害怕中断函数进行过程中来了新的自己的中断,这不本身就矛盾的吗?这已经说明中断处理时间太长了,设计不合理。

出0入0汤圆

发表于 2023-4-22 19:21:03 | 显示全部楼层
1a2b3c 发表于 2023-4-22 16:56
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说, ...
(引用自27楼)

你是饱汉子不知饿汉子饥,现在好多编程者就搞不懂中断,更用不好中断,只能靠HAL软件去做这些工作,至于效率,不行就换性能更强的芯片,反正现在芯片也便宜

出130入129汤圆

发表于 2023-4-22 19:23:08 来自手机 | 显示全部楼层
1a2b3c 发表于 2023-4-22 16:56
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说, ...

(引用自27楼)

hal库是怎么麻烦怎么来

出0入33汤圆

发表于 2023-4-22 22:19:36 来自手机 | 显示全部楼层
很频繁就不要用中断了,dma解忧愁。一定要用中断就要确保在中断里尽量简单处理,例如仅通过环形缓冲期存取收发的数据。

出0入0汤圆

发表于 2023-4-23 06:08:33 来自手机 | 显示全部楼层
ackyee 发表于 2023-4-21 16:13
哈哈,cubemx 的hal库, 然后初始化这些都自动设置好了 ,自己只是增加了个回调函数,  流程应该没问题了 ...
(引用自22楼)

用中断进行循环接收,每次接收完有个中断标志要清掉,不然后面会进不了中断接收程序,以前用官方例程就有这个坑,只能收几次,后面就收不到了,估计cube也是没有清的,文档里写的是会自动复位,实际没有复位

出0入91汤圆

 楼主| 发表于 2023-4-23 08:47:53 | 显示全部楼层
1a2b3c 发表于 2023-4-22 16:56
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说, ...
(引用自27楼)

哈哈  如果 不调用库的话,每一颗芯片都要去从头研究寄存器   对于简单的单片机来说还行 ,对于  H7这种复杂的,不调用库的话  学习上花费的时间太大了

锁来锁去 不是我的本意 是 库里自带的  而且还很难找到问题点

出0入91汤圆

 楼主| 发表于 2023-4-23 08:49:18 | 显示全部楼层
vtte 发表于 2023-4-22 22:19
很频繁就不要用中断了,dma解忧愁。一定要用中断就要确保在中断里尽量简单处理,例如仅通过环形缓冲期存取 ...
(引用自30楼)

原来如此 今天就把中断给干了 换DMA方式   

另外  HAL库碰到问题的时候找问题 太不容易了

出0入91汤圆

 楼主| 发表于 2023-4-23 08:49:36 | 显示全部楼层
3318156 发表于 2023-4-23 06:08
用中断进行循环接收,每次接收完有个中断标志要清掉,不然后面会进不了中断接收程序,以前用官方例程就有 ...
(引用自31楼)

是的 和你一样的情况

你后来怎么解决的 也是换DMA了吗

出0入91汤圆

 楼主| 发表于 2023-4-25 14:06:11 | 显示全部楼层
qwe2231695 发表于 2023-4-21 14:55
H7串口我用了很久,建议用DMA发送。 IT发送要规避HAL的锁,也就是发送前强制释放锁:__HAL_UNLOCK(huart); ...
(引用自20楼)

网上他们也遇到这个问题了 都在怀疑是   lock的问题

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-21 00:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表