历史上的今天
返回首页

历史上的今天

今天是:2024年10月15日(星期二)

正在发生

2018年10月15日 | STM32中USART接收中断问题使单片机死机

2018-10-15 来源:eefocus

问题描述:

在使用USART做串口通讯时,我只把接收中断打开,并设置抢占优先级为最低一个级别,而接收中断上一个优先级处理事情比较多,可能占用了2ms时间。当我使用9600波特率往下位机发送数据,速度非常快,就是一直按回车发送!问题就出来,不到1分钟时间,通讯没有反应了,死机了。USART配置代码如下:

void uart_config(void)

{

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = UART_GetBaud(BaudRate);

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx

USART_Mode_Tx;

USART_InitStructure.USART_Clock = USART_Clock_Disable;

USART_InitStructure.USART_CPOL = USART_CPOL_Low;

USART_InitStructure.USART_CPHA = USART_CPHA_2Edge;

USART_InitStructure.USART_LastBit = USART_LastBit_Enable;

USART_Init(USART1, &USART_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

USART_Cmd(USART1, ENABLE);

}

分析问题:

1.为什么没有通讯了?

通过仿真器仿真,发现程序一直进入接收中断中,由于我没有使用中断发送,于是程序就死在了接收中断,也就没有数据发送到电脑上来。接收中断代码如下:

void UART_Receive(void)

{

//正在处理上一条通讯,接收到数据不处理

if(bRecieveOK)

{

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

USART_ClearITPendingBit(USART1, USART_IT_RXNE);

return;//processing receive data,don't receive again

}

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

{

if(MoudBusExpir == 0)

{

ucRcePtr = 0;

MoudBusExpir = 20;//50ms

}

else

MoudBusExpir = 20;

ucRS485Buff[ucRcePtr++] = USART_ReceiveData(USART1);

USART_ClearITPendingBit(USART1, USART_IT_RXNE);

}

2.为什么会一直跑到接收中断?

断点之后发现(USART_GetITStatus(USART1, USART_IT_RXNE)==RESET的,也就是说没有数据接收到也进了中断,而且在USART配置中我也只打开了接收中断!没有数据送过来应该是不可能进入中断的!

3.响应了什么中断?

我想通过函数(USART_GetITStatus()把所有中断状态都读出来,但失败了,USART_IT_XXX所有中断状态都是RESET!也就是说没有中断也进入到这个中断服务程序来了!?

4.找资料

STM32F10x微控制器参考手册(2009年12月第10版)P541发现如下说明:

也就是说只要接收中断打开,即RXNEIE设置为1,那么ORE中断也自动打开了。

可是USART_GetITStatus(USART1, USART_IT_ORE )== RESET!!!!

找到USART_GetITStatus(USART1, USART_IT_RXNE)函数,发现只有当USART_IT_ERR中断使能时,才能读到ORE中断。

在这里要指出这个BUG:产生ORE中断了,但使用USART_GetITStatus()函数却无法读到这个中断被SET起来!

5.把ORE中断标志位清除

既然找到了是什么中断,那么把相应的中断标志位清除,就应该可以了吧?

USART_ClearITPendingBit(USART1, USART_IT_ORE);

但是,结果是没有任何效果!清除之后,马上读ORE中断状态,USART_GetITStatus(USART1, USART_IT_ORE)==RESET.程序仍然跑死在接收中断。再使用另一个函数USART_GetFlagStatus(USART1, USART_FLAG_ORE) = SET,原来ORE标志位还没有清除。

6.问题解决

为什么清除不掉?头疼了,再找找资料,有发现,在P523页如下图:

接收中断程序改为:

void UART_Receive(void)

{

if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)//注意!不能使用if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)来判断

{

USART_ReceiveData(USART1);

}

//正在处理上一条通讯,接收到数据不处理

if(bRecieveOK)

{

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

USART_ClearITPendingBit(USART1, USART_IT_RXNE);

return;//processing receive data,don't receive again

}

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

{

if(MoudBusExpir == 0)

{

ucRcePtr = 0;

MoudBusExpir = 20;//50ms

}

else

MoudBusExpir = 20;

ucRS485Buff[ucRcePtr++] = USART_ReceiveData(USART1);

USART_ClearITPendingBit(USART1, USART_IT_RXNE);

}

总结:

注意问题:1.USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);使能了接收中断,那么ORE中断也同时被开启了。

2.ORE中断只能使用USART_GetFlagStatus(USART1, USART_FLAG_ORE)读到(没有使能USART_IT_ERR中断时)

BUG建议:1.在STM32库中,能不能修改USART_GetITStatus()函数对USART_IT_ORE中断的处理?也就是我只要打开了接收中断,那么有ORE中断时,我也能使用USART_GetITStatus(USART1,USART_IT_ORE)读到.

以上来自http://blog.csdn.net/zyboy2000/article/details/8677256

本人对问题的解释是:

只要接收中断打开,即RXNEIE设置为1,那么ORE中断也会自动打开,ORE为溢出错误;当接收移位寄存器被传递到USART_RDR寄存器中将产生接收中断,RXNE会被硬件置1,当读取USART_RDR寄存器中的数据同时也会自动将RXNEIE清零。溢出中断的产生是当RXNE=1时(也就是上次数据还没被读取),串口接收寄存器又接收好了一个字节的数据并准备往USART_RDR寄存器去转移的时候,ORE标志位会被置1,而ORE标志位必须软件清零,由于代码代码中未对该标志位清零,所以单片机会在中断出死机。可适当添加相关函数清除标志位:

 if(USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET)
{
   USART_ClearFlag(USART2, USART_FLAG_ORE);
}
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}


推荐阅读

史海拾趣

Emerging Display Technolgies公司的发展小趣事

另一家新兴显示技术公司,专注于透明显示技术的研发。他们通过优化显示材料的透光性和显示效果,成功研发出了高透明度的显示屏。这种显示屏可以像玻璃一样透明,同时又能显示图像和文字。这一技术的创新,为商业广告、智能家居、公共交通等领域带来了全新的视觉体验。

远东福斯特公司的发展小趣事

随着虚拟现实(VR)、增强现实(AR)等技术的快速发展,微型显示技术的需求日益增加。一家新兴显示技术公司,凭借其在微纳加工和光学设计方面的技术优势,成功研发出了高性能的微型显示屏。这种显示屏具有体积小、分辨率高、功耗低等特点,为VR/AR设备提供了更加逼真的视觉体验。

ABL Heatsink公司的发展小趣事

在国内市场取得一定成绩后,ABL Heatsink公司开始将目光投向国际市场。公司首先在欧洲设立了分公司,随后又在美国、亚洲等地建立了销售网络。通过不断优化产品和服务,ABL Heatsink成功打入国际市场,实现了公司的全球化发展。

这些故事虽然基于虚构,但它们反映了电子行业中散热器公司可能经历的一些典型发展轨迹。当然,每个公司的实际发展情况都会有所不同,具体的故事还需要根据公司的实际情况来撰写。

创世(CS)公司的发展小趣事

作为一家有社会责任感的企业,创世公司始终关注环境保护和可持续发展。公司积极推广绿色生产技术和资源循环利用方案,减少生产过程中的能源消耗和废弃物排放。同时,创世公司还积极参与社会公益活动,为社会和环境贡献自己的力量。这种对社会责任的关注和担当使得创世公司在电子行业中树立了良好的形象。

Advanced Semiconductor, Inc.公司的发展小趣事

Advanced Semiconductor, Inc. (简称ASI) 成立于XXXX年,由一群热衷于半导体技术创新的工程师和科学家创立。在创立初期,ASI专注于研发高性能的半导体芯片,以满足当时市场对更快、更稳定电子产品的需求。公司凭借其独特的技术和创新的理念,很快在半导体行业中崭露头角,吸引了众多投资者的关注。

Elpress AB公司的发展小趣事

Elpress AB公司成立于1959年,由一群具有前瞻性和创新精神的工程师在瑞典的克拉姆福什市创立。公司从成立之初就专注于电气连接系统的研发和生产,致力于为电力行业提供高效、可靠的解决方案。在初期,Elpress AB凭借其专业的技术能力和对质量的严格把控,逐渐在市场上赢得了客户的信赖。

问答坊 | AI 解惑

232接口四路电压记录仪,超简单,带pc端软件!

该电压记录仪仅用了一只串口和廉价的运放就可实现四路电压记录,很适合用来记录多路电池电压状况. 500) {this.resized=true; this.width=500; this.alt=\'这是一张缩略图,点击可放大。\\n按住CTRL,滚动鼠标滚轮可自由缩放\';this.style.cursor=\'h ...…

查看全部问答>

最近做了一个lattice下载次数限制的VC程序.

最近做了一个lattice下载次数限制的VC程序. 有需要的可以联系我,QQ:289525317 只愿对技术人员开源,免费.…

查看全部问答>

嵌入式系统的学习

   我想往嵌入式系统发展,有哪位专家是在这方面发展的给我点建议,我想知道我得掌握哪些知识,嵌入式系统对c语言的要求高吗,应该掌握到哪一个程度?谢了~~…

查看全部问答>

退出系统后变量存储问题

我想要实现这样的功能:在单片机系统程序启动的时候,用键盘输入给一个变量赋值,在退出系统后这个值也保存下来,在下一次系统再次启动时该变量还是这个值,请问各位大侠C代码如何实现!…

查看全部问答>

ucos+lwip在lm3s8962上的以太网发送问题

最近一个项目,要求使用ucos+lwip在lm3s8962上的以太网发送、接收,我ucos-ii下建立了建立了一个任务(线程)用于处理以太网发送和接收任务,TCP和UDP接收和发送都正常,但是我在一个定时器中断中调用tcp_write和udp_write发送时,就不能成功发送, ...…

查看全部问答>

万利的技术支持太扯淡了

                                 开始电话咨询,我把问题细细说了一遍,某工说电话不方便,EMAIL把程序发给他(一提及EMAIl我就冒火,没有一次回的 ...…

查看全部问答>

如何判断MSP430F149的输入口是高或则低(急)

各位好: 我是一个新手,我想问如用C语言来判断,输入口的电平是高还是低! 是不是用这样的语句: if(P1IN==0x00)…

查看全部问答>

请教大侠数电知识

图一:3线-8线译码器    图二:COMS反相器     图三:TTL反相器 问题:为什么数电(阎石编的第五版)书上会说图一所画电路的输入电阻较低输出电阻较高?请高手授教,非常感谢    …

查看全部问答>

TLV2553

谁有TLV2553的C程序啊  急用  借鉴一下啊…

查看全部问答>