硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4694|回复: 6
收起左侧

[有问必答] 【太奇怪了】串口中断不停地进,主循环无法运行

[复制链接]

1

主题

7

回帖

30

积分

新手上路

积分
30
发表于 2017-8-8 10:01:18 | 显示全部楼层 |阅读模式
软件开了UART3 UART6,系统还用了systick,硬件spi,一个边沿触发的外部中断,中断优先级配置:NVIC_PriorityGroup_2,systick和外部中断均为PreemptionPriority=0,SubPriority=0,UART3的SubPriority=2,UART6的SubPriority=5,没有配置串口的PreemptionPriority。UART3每秒都有数据进来,数据量大约几百字节,UART6数据量较少,几十字节。串口驱动用的bsp_uart_fifo.c。
主循环运行一段时间后突然死掉,然后程序不停地在UART3中断服务子程序里进进出出,仿真调试发现进中断时并不是接收中断、发送中断、发送完毕中断(换句话说,再也不能进入串口接收中断了)。在中断服务子程序里打个断点,停下来后再全速运行,软件又恢复正常了。
这个问题困扰了我好久了,一开始怀疑串口中断被打断导致的故障,所以对串口中断做了关全局中断的保护,结果问题还是出现了。
还有我发现,在接收中断的ch=USART_ReceiveData(_pUart->uart);前面打个断点,就能出现该问题,让程序停下来,再全速运行,又恢复正常了。。。。
大神们帮帮忙啊!
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2017-8-8 10:14:35 | 显示全部楼层
所有其他功能都注释掉,仅测试USART3看看。我们V5板子一直用的USART3做的485 Modus,没发现问题。
回复

使用道具 举报

1

主题

7

回帖

30

积分

新手上路

积分
30
 楼主| 发表于 2017-8-8 11:08:55 | 显示全部楼层
不能直接回复版主,我在下面回复吧,一样版主能看到啊!
应该不是某个特定串口的问题,因为我即便关闭串口3,只用串口6,一样会出现问题。我正在一点儿一点儿屏蔽代码找原因,暂时还是没有进展。eric大神能不能按照我说的试一下,看看会不会也出现这个问题呢?就是在ch=USART_ReceiveData(_pUart->uart);前打个断点,再跑起来,主循环就死了。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2017-8-8 11:25:17 | 显示全部楼层

回 hansom_hu 的帖子

hansom_hu:不能直接回复版主,我在下面回复吧,一样版主能看到啊!
应该不是某个特定串口的问题,因为我即便关闭串口3,只用串口6,一样会出现问题。我正在一点儿一点儿屏蔽代码找原因,暂时还是没有进展。eric大神能不能按照我说的试一下,看看会不会也出现这个问题呢?就是在ch=USART_Rece .. (2017-08-08 11:08)
调试不能说明问题,特别是正在工作中的硬件外设设置断点。

建议新建一个USART3的工程,用串口线单独测试下,这样就很容易找到问题了。
回复

使用道具 举报

1

主题

7

回帖

30

积分

新手上路

积分
30
 楼主| 发表于 2017-8-9 12:37:54 | 显示全部楼层

回 eric2013 的帖子

eric2013:调试不能说明问题,特别是正在工作中的硬件外设设置断点。

建议新建一个USART3的工程,用串口线单独测试下,这样就很容易找到问题了。

....... (2017-08-08 11:25) 
问题解决了!
首先,串口不停地进中断是由ORE(overrun error溢出错误)中断引起的。ORE产生的官方描述如下:This bit is set by hardware when the word currently being received in the shift register is ready to be transferred into the RDR register while RXNE=1. An interrupt is generated if RXNEIE=1 in the USART_CR1 register. It is cleared by a software sequence (An read to the USART_SR register followed by a read to the USART_DR register).
大意为:该中断由硬件产生,当移位寄存器中有数据可以发送到RDR寄存器,且RDR寄存器里的数据未被读走时,ORE中断产生,并且ORE标志位置1(前提是USART_CR1中的RXNEIE使能,即使能接收中断)。该中断由软件序列清零(先读USART_SR,再读USART_DR)。
那么,串口溢出是怎么产生的呢?这个主要因为我的外部中断没设计好。。。
UART3有数据进来,产生RXNE中断,当准备读取RSART_RDR时,来了一个优先级更高的外部中断,软件立即跳到外部中断函数中处理中断,然而,这个过程是相当耗时的,大约需要50us。UART3的baudrate为115200,在此期间,串口又来了50/100000*115200/10=0.576个字节,随着时间的推移,总会出现一次处理外部中断时,UART3又来了一个新的字节的情况,从而产生了串中溢出。
串口溢出后,如果不将溢出中断清零,串口就无法再接收闲的数据!
按照STM32F407的datasheet所说,产生溢出后按照前面说的软件序列操作USART_SR和USART_DR就能清零溢出中断,然而,bsp_uart_fifo.c里串口中断函数是这样写的:
if(USART_GetITStatus(_pUart->uart, USART_IT_RXNE) != RESET)
{
    uint8_t ch;
    ch=USART_ReceiveData(_pUart->uart);
    ..........
}
可是,一旦出现 溢出中断,RXNE就再也不会置位了,也就无法读USART_RDR,导致无法清零ORE中断,从而产生了这个问题。
所以,只要在串口中断函数里加上ORE产生时,你分别读USART_SR和USART_RDR就可以了。
问题解决,安富莱的中断函数是不是应该考虑也加上我说的功能。
回复

使用道具 举报

1

主题

7

回帖

30

积分

新手上路

积分
30
 楼主| 发表于 2017-8-9 18:25:26 | 显示全部楼层
更正一下错误。。。前面我说的“随着时间的推移,总有一次外部中断处理中时,UART3又来了一个字节,从而产生了溢出中断 ”是不对的,按照前面的计算,中断处理过程只有0.576个字节进来,是不可能产生溢出中断的。
我现在也搞不清楚是什么引起的串口溢出了,总之,加上溢出中断处理后,问题确实解决了。[s:139]
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115490
QQ
发表于 2017-8-10 01:50:54 | 显示全部楼层

回 hansom_hu 的帖子

hansom_hu:更正一下错误。。。前面我说的“随着时间的推移,总有一次外部中断处理中时,UART3又来了一个字节,从而产生了溢出中断 ”是不对的,按照前面的计算,中断处理过程只有0.576个字节进来,是不可能产生溢出中断的。
我现在也搞不清楚是什么引起的串口溢出了,总之,加上溢出中断处理 .. (2017-08-09 18:25) 
[s:130]

估计是其它问题造成的吧,我们项目中485 Modbus 用的串口一直是这么用的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-29 06:36 , Processed in 0.232449 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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