STM32H7串口向外不停发送数据,容易造成接收无法进入中断,求解
如题做的STM32H7 是一个屏幕,需要时刻和 主板进行串口通讯(发送和接收)
如果发送不频繁, 比方说安下按键发送一次数据,那接收没出现过问题(也可能是出现的概率极低,没被察觉)
但是如果改成 发送 每几十ms 发送一个字节,然后循环发送的情况(这样不怕干扰丢数据,因为会重复发送)
也就是发送一直进行的时候, 容易工作很久后, 接收就卡住了,debug后发现是无法进入接收中断HAL_UART_RxCpltCallback
HAL_UART_Transmit_IT和HAL_UART_Transmit 两种发送 都测试过 ,都会造成问题复现
现在中断优先级串口是改成0 0的。 网上说很可能是发送的过程中被接收打断,但是接收发现串口正忙,就没触发中断,导致HAL_UART_Receive_IT这句没执行,不再进入接收中断了
大家有好的解决思路吗? 有人提出 在发送结束后都加一句 HAL_UART_Receive_IT开启接收中断(还没测试)但是感觉不靠谱
都H7了,为啥串口不用DMA mypear 发表于 2023-4-19 14:28
都H7了,为啥串口不用DMA
(引用自2楼)
{:dizzy:}因为 同样的情况下 , STC竟然 可以一直发一直收,但是性能更强的STM32竟然死掉了不可思议
而且我这应用应该也不算复杂情况了
为了减少传输的数据量太大,我一个帧的数据都是拆分 一个数据一次的发送了 ,发送完后等待很一段时间再发送下一个字节 mypear 发表于 2023-4-19 14:28
都H7了,为啥串口不用DMA
(引用自2楼)
如果用DMA就不会有这个问题了吗? 接收是怎么写的?HAL_UART_Receive_IT(&huart, , 1);这样写的吗?如果是,改成其他方式,接收数量不要写1。 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=READ_DATA;
READ_DATA=READ_DATA;
READ_DATA=READ_DATA;
READ_DATA=READ_DATA;
READ_DATA=READ_DATA;
READ_DATA=READ_DATA;
READ_DATA=READ_DATA;
READ_DATA=RxBuffer;
uart_receice_flag=1;
HAL_UART_Receive_IT(&huart5,RxBuffer,1); // Enable the USART5 Interrupt
}
}
DMA+FIFO,可以考虑一下 jbpan852 发表于 2023-4-19 14:39
DMA+FIFO,可以考虑一下
(引用自7楼)
谢谢,我先研究下 如果解决不了 就只能上DMA了 看看芯片手册,理解下UART硬件,写个寄存器不到10行的事情。
ST的HAL完全是垃圾。 MasterPhi 发表于 2023-4-19 14:47
看看芯片手册,理解下UART硬件,写个寄存器不到10行的事情。
ST的HAL完全是垃圾。 ...
(引用自9楼)
我有点不太理解 STC 这样的 串口 是开启中断后, 一直都会接收数据
但是 STM32 竟然接收进入中断后,要手动开启下一次接收才行 (如果能像STC这样,永远中断工作, 那我这个问题也不用纠结了,现在是 打断一次 永远 不再开启下次接收了)
我不确定这个坑是否是 HAL 带来的
本帖最后由 Doding 于 2023-4-19 14:52 编辑
ackyee 发表于 2023-4-19 14:38
是的 接收也是1 这样进来的数据就不用对位了
有什么讲究吗? 放1 会出现什么样的问题呢
(引用自6楼)
接收数据长度为1,串口每收到一个字节后会关中断,清标志位,在Rxcplt里再调用Receive_IT,会再把中断打开,每收一字节都要开关一次中断。
如果数据长度已知,直接写数据长度,如果数据长度未知但数据连续,用空闲中断+DMA接收,如果长度未知且不连续,用LL库吧。 Doding 发表于 2023-4-19 14:50
接收数据长度为1,串口每收到一个字节后会关中断,清标志位,在Rxcplt里再调用Receive_IT,会再把中断打 ...
(引用自11楼)
感觉这个问题应该是 cubemx 的库引起的
接收到数据后 ,即使判断串口忙,不能进入中断, 那也应该帮我使能下一次接收对吧{:dizzy:}
现在这个库 直接帮我给干罢工了{:lol:} 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里处理收到的数据就可以了。 串口空闲中断/超时中断+DMA很爽的,数据量特别大的可以再加一个环形缓冲,这是标准用法了,跟用什么库没关系 ackyee 发表于 2023-4-19 14:31
如果用DMA就不会有这个问题了吗?
(引用自4楼)
DMA不占CPU 看下UART的状态寄存器,持掉的时候是不是有异常状态产生? 你是不是复制的例程上的代码, 3318156 发表于 2023-4-21 00:27
你是不是复制的例程上的代码,
(引用自17楼)
关键说清楚了{:tongue:} 串口接收用DMA+idle中断,很流行,idle中断后把DMA接到的数据复制出来解析;
如果配置了freertos,串口接收是一个任务,发送是一个任务,就更妥了{:lol:} H7串口我用了很久,建议用DMA发送。 IT发送要规避HAL的锁,也就是发送前强制释放锁:__HAL_UNLOCK(huart); 是被HAL库调戏了吧 3318156 发表于 2023-4-21 00:27
你是不是复制的例程上的代码,
(引用自17楼)
哈哈,cubemx 的hal库, 然后初始化这些都自动设置好了 ,自己只是增加了个回调函数,流程应该没问题了
估计就是互相 关中断锁外设的问题了 qwe2231695 发表于 2023-4-21 14:55
H7串口我用了很久,建议用DMA发送。 IT发送要规避HAL的锁,也就是发送前强制释放锁:__HAL_UNLOCK(huart); ...
(引用自20楼)
感觉你的方向比较接近了
我待会查查看代码框架里是否有锁 串口的地方 本帖最后由 qwe2231695 于 2023-4-21 17:08 编辑
ackyee 发表于 2023-4-21 16:13
感觉你的方向比较接近了
(引用自23楼)
HAL在接收中断时会自动锁上,导致你发送的时候没有获得锁,导致失败。
关于DMA 和 IDEL接收可以看我写的笔记https://blog.csdn.net/cqy1028/article/details/117408683 qwe2231695 发表于 2023-4-21 17:06
HAL在接收中断时会自动锁上,导致你发送的时候没有获得锁,导致失败。
关于DMA 和 IDEL接收可以看我写的 ...
(引用自24楼)
但是发送的数据一直都有 , 接收被打断一次后 永远不再进入了
我也怀疑 接收中断进入了 但是还没进入回调函数的时候 被发送打断了,然后回调函数没有正确进入就无法 使能下一次接收了
是的,就是”接收被打断一次后 永远不再进入了“。 只要在再次开启接收前__HAL_UNLOCK(huart);
并且实现
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
在里面再
__HAL_UNLOCK(huart);
__HAL_UART_CLEAR_OREFLAG(huart); 啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说,无非就是初始化的时候开启好接收中断,然后在中断函数里面把接收的内容搬运到外部循环的缓冲中去吗?要是这么高的速度的芯片,我估计大部分运算啊判断啊一类的处理即使放在串口中断处理函数里面进行又何妨嘛,
不知道为啥要弄那么复杂,复杂到自己都不知道哪里有问题
还有就是,好多地方的思路是,中断进去后要关中断使能,这点我是到现在都没有明白,为啥要关呢?如果是说害怕中断函数进行过程中来了新的自己的中断,这不本身就矛盾的吗?这已经说明中断处理时间太长了,设计不合理。 1a2b3c 发表于 2023-4-22 16:56
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说, ...
(引用自27楼)
你是饱汉子不知饿汉子饥,现在好多编程者就搞不懂中断,更用不好中断,只能靠HAL软件去做这些工作,至于效率,不行就换性能更强的芯片,反正现在芯片也便宜 1a2b3c 发表于 2023-4-22 16:56
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说, ...
(引用自27楼)
hal库是怎么麻烦怎么来 很频繁就不要用中断了,dma解忧愁。一定要用中断就要确保在中断里尽量简单处理,例如仅通过环形缓冲期存取收发的数据。 ackyee 发表于 2023-4-21 16:13
哈哈,cubemx 的hal库, 然后初始化这些都自动设置好了 ,自己只是增加了个回调函数,流程应该没问题了 ...
(引用自22楼)
用中断进行循环接收,每次接收完有个中断标志要清掉,不然后面会进不了中断接收程序,以前用官方例程就有这个坑,只能收几次,后面就收不到了,估计cube也是没有清的,文档里写的是会自动复位,实际没有复位 1a2b3c 发表于 2023-4-22 16:56
啥子回调函数,啥子锁这里锁那里的,对我毫无用处?。些软件的人依赖这些东西太那个啥了,,,
对我来说, ...
(引用自27楼)
哈哈如果 不调用库的话,每一颗芯片都要去从头研究寄存器 对于简单的单片机来说还行 ,对于H7这种复杂的,不调用库的话学习上花费的时间太大了
锁来锁去 不是我的本意 是 库里自带的而且还很难找到问题点{:dizzy:} vtte 发表于 2023-4-22 22:19
很频繁就不要用中断了,dma解忧愁。一定要用中断就要确保在中断里尽量简单处理,例如仅通过环形缓冲期存取 ...
(引用自30楼)
原来如此 今天就把中断给干了 换DMA方式
另外HAL库碰到问题的时候找问题 太不容易了 3318156 发表于 2023-4-23 06:08
用中断进行循环接收,每次接收完有个中断标志要清掉,不然后面会进不了中断接收程序,以前用官方例程就有 ...
(引用自31楼)
是的 和你一样的情况
你后来怎么解决的 也是换DMA了吗 qwe2231695 发表于 2023-4-21 14:55
H7串口我用了很久,建议用DMA发送。 IT发送要规避HAL的锁,也就是发送前强制释放锁:__HAL_UNLOCK(huart); ...
(引用自20楼)
网上他们也遇到这个问题了 都在怀疑是 lock的问题
页:
[1]