单片机怎样才能不死机之串口Overrun

发布者:GoldenSerenity最新更新时间:2024-07-10 来源: elecfans关键字:单片机  死机 手机看文章 扫描二维码
随时随地手机看文章

闲言少叙,先上Code,大家看一下下面这段代码有没有问题?

// Note: USART demo code runs on STM32F030#include “main.h”


static __IO uint32_t TimingDelay;

RCC_ClocksTypeDef RCC_Clocks;

uint8_t uart_buffer[100];

// GPIO Configurationvoid GPIO_Configuration(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1); // Tx PA9 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); // Rx PA10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // USART1_TX | USART1_RX GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1; GPIO_Init(GPIOA, &GPIO_InitStructure); }

// USART Configurationvoid USART_Configuration(void){ USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; //USART_InitStructure.USART_BaudRate = 9600; 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_Tx | USART_Mode_Rx; USART_Init(USART1,&USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1,ENABLE); }

// Interrupt Configurationvoid NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; // USART1 interrupt Config NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}

// USART1 Interrupt Handlervoid USART1_IRQHandler (void){ static uint8_t i = 0;

if(USART_GetITStatus(USART1,USART_IT_RXNE)!= RESET) {// Clear Receive Data Register Not Empty Flag USART_ClearITPendingBit(USART1,USART_IT_RXNE); uart_buffer[i++] = USART_ReceiveData(USART1); if(i == 100) i = 0; }}

int main(void){ static uint8_t ch;

// Init a 1ms timer interrupt, for Delay function implementation. RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); // Enable USART1 and GPIOA clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); GPIO_Configuration(); USART_Configuration(); NVIC_Configuration(); ch = ‘A’; while(1) { Delay(50); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, ch); ch++; }

}

/*** @brief Inserts a delay time.* @param nTime: specifies the delay time length, in 1 ms.* @retval None*/void Delay(__IO uint32_t nTime){ TimingDelay = nTime; while(TimingDelay != 0);}

/*** @brief Decrements the TimingDelay variable.* @param None* @retval None*/void TimingDelay_Decrement(void){ if(TimingDelay != 0x00) { TimingDelay--; }}

它是可以在 STM32F030 上调试通过的串口收发测试程序,发送采用延时循环,接收采用中断,接收到的数据存入缓冲区。

有很多比较认真的实战派的同学估计会下载到板子上跑一跑,它确实能跑通,看起来也没什么问题。很多教程甚至官方的代码都是类似的处理方法。

但这确实有点儿像陷马坑,看似一马平川,跑着跑着突然连马带人 kucha 一声掉坑里了。这还真不是开玩笑,某知名楼宇自控公司的产品就在安装到客户现场后,经常莫名奇妙的死机。查来查去,查去查来,才发现问题。可是解决起来不容易啊,一个一个的去拆开,更新代码,想想都。。。

所以同学们不要轻视任何一段代码啊!

这段代码的问题是,如果接收数据之间间隔时间较长,可以正常收数据。但是如果对方发送数据非常快,或者偶尔在自己还没从串口接收寄存器取走数据的时候突然又来了数据,会导致 Overrun 标志位的置位。这个标志位一置,串口基本上就罢工了。所以,在程序中一定要有对异常情况的处理。甚至觉得不会发生的异常也不要置之不理。(想一想为什么要填充Flash的空白区域?在正常情况下代码永远不会跑到空白区域是吧。)

对串口异常的处理可以参考下面中断处理函数代码。当然也可以在主程序中定时处理,以便在中断失效的情况下还能恢复。

// USART1 Interrupt Handlervoid USART1_IRQHandler (void){ static uint8_t i = 0;

if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET) {// Clear Overrun Error Flag USART_ClearFlag(USART1, USART_FLAG_ORE); } else if(USART_GetFlagStatus(USART1, USART_FLAG_NE) != RESET) {// Clear Noise Error Flag USART_ClearFlag(USART1, USART_FLAG_NE); } else if(USART_GetFlagStatus(USART1, USART_FLAG_FE) != RESET) {// Clear Framing Error Flag USART_ClearFlag(USART1, USART_FLAG_FE); } else if(USART_GetFlagStatus(USART1, USART_FLAG_PE) != RESET) {// Clear Parity Error Flag USART_ClearFlag(USART1, USART_FLAG_PE); } else if(USART_GetITStatus(USART1,USART_IT_RXNE)!= RESET) {// Clear Receive Data Register Not Empty Flag USART_ClearITPendingBit(USART1,USART_IT_RXNE); uart_buffer[i++] = USART_ReceiveData(USART1); if(i == 100) i = 0; }}


关键字:单片机  死机 引用地址:单片机怎样才能不死机之串口Overrun

上一篇:do{...} while(0U) 这种代码的作用和意义
下一篇:探究用双定时器控制单片机输出固定的数量的PWM脉冲!

推荐阅读最新更新时间:2026-03-20 07:00

单片机程序死机跑飞查错指南
1. 意外中断。是否打开了某个中断,但是没有响应和清除中端标志,导致程序一直进入中断,造成死机假象; 2. 中断变量处理不妥。若定义某些会在中断中修改的全局变量,这时要注意两个问题:首先为了防止编译器优化中断变量,要在这些变量定义时前加volatile,其次在主循环中读取中断变量前应该首先关闭全局中断,防止读到一半被中断给修改了,读完之后再打开全局中断;否则出现造成数据乱套。 3. 地址溢出,常见错误为指针操作错误。我要着重说的是数组下标使用循环函数中循环变量,如果循环变量没控制好则会出现数组下标越界,意外修改系统的寄存器造成死机,这种情况下如果死机说明运气好,否则后面不知道发生什么头疼的事。 4. 无条件的死循环;比如使用whi
[单片机]
GD32F103系列SPI导致死机问题
提出问题 几年前的一个产品,一直用的STM32F103系列的MCU,2021年上半年意法半导体在市场上的MCU货源稀疏,高价都买不到,只能用国产芯片代替。国产芯片中,首选兆易创新,毕竟是上市公司,也是最早在国内与意法半导体竞争的公司。用GD32F103代替STM32F103。 发现问题 很幸运,STM32F103的程序是可以直接在GD32F103直接使用的。直接下载STM32F103的程序到GD32F103。没想到,好景不长,产品在用户运行一段时间后,客户发现“死机”现象。开门狗也没有起作用?但定时中断是可以运行的。 解决问题 既然中断可以运行(因为现实是数码管,用的定时扫描。显示是正常的,因此判断定时中断正常。),那么程序一定是
[单片机]
可编程控制器PLC运行时出现死机的原因
可编程控制器PLC运行时可能会出现死机的情况,这给工业生产造成不可预估的损失,因此,首先要了解PLC死机的原因,针对原因进行排查,软件或硬件错误都有可能导致PLC死机,下面分别进行介绍: 1、硬件方面 (1)I/O窜电,PLC自动侦测到I/O错误,进入STOP模式。 (2)I/O损坏,程序运行到需要该I/O的反馈信号,不能向下执行指令。 (3)扩展模块(功能型,如A/D)线路干扰或开路等。 (4)电源部分有干扰或故障。 (5)PLC的连接模块及地址分配模块出故障。 (6)电缆引起的故障。 2、软件方面 (1)触发了死循环。 (2)程序改写了系统参数区的内容,却没有初始化部分。 (3)保护程序启动:硬件保护、限制使用时间(针对货款收
[嵌入式]
STM32G0复位后死机
引言 有客户反映,STM32G071RBT6 在使用 STM32CubeProgrammer 烧录完程序后只能运行一次,复位后,程序无法运行,如果掉电后重新上电,程序恢复正常。 问题描述 根据客户描述,该问题可通过以下步骤复现: 2.1. 测试代码的功能流程图 准备测试代码 App1 和 App2: 2.2. 问题复现步骤 操作步骤 (1) 在 STM32CubeProgrammer 中下载 应用程序 App1(如图 3),并设置 RDP=1(如图 4);然后断开 STM32CubeProgrammer 的连接,板子断电后重新上电; (2) 根据 log 提示(如图 5),按下用户按键,板子会在 RDP 降级的过程
[单片机]
STM32G0复位后<font color='red'>死机</font>
工程师笔记|STM32G0 复位后死机
引言 有客户反映,STM32G071RBT6 在使用 STM32CubeProgrammer 烧录完程序后只能运行一次,复位后,程序无法运行,如果掉电后重新上电,程序恢复正常。 问题描述 根据客户描述,该问题可通过以下步骤复现: 2.1. 测试代码的功能流程图 准备测试代码 App1 和 App2: 2.2. 问题复现步骤 操作步骤 (1) 在 STM32CubeProgrammer 中下载 应用程序 App1(如图 3),并设置 RDP=1(如图 4);然后断开 STM32CubeProgrammer 的连接,板子断电后重新上电; (2) 根据 log 提示(如图 5
[单片机]
工控机死机的原因_工控机死机了怎么办
  1、灰尘过多引发死机故障   一台新工控机在国内的一般车站运转室使用一年左右后,其内部就会有很多灰尘了,如果进入到某个板卡的插槽中就可能引起该板卡接触不良而出现死机或其它故障,而且常是无故死机。   另外,机器内灰尘过多就会对某些重要工控机硬件设备的散热问题造成坏的影响,CPU和显卡等重要硬件如果散热不良自然就会引起蓝屏或花屏或定格或黑屏死机故障,此类死机现象虽然通常并没有什么规律可言,但使用时间越长其死机次数就越频繁。如果软驱磁头或光驱激光头上的灰尘过多的话,那么就会会导致读写盘困难,严重的就会引起工控机蓝屏死机。      对策:一定要交代录波器用户一年对工控机进行一次彻底除尘,当然,如果对工控机结构不
[嵌入式]
工控机<font color='red'>死机</font>的原因_工控机<font color='red'>死机</font>了怎么办
STM32开发笔记76: 初始化RTC后死机的原因
单片机型号:STM32L053R8T6 项目开发中只要初始化RTC,则系统死机。其初始化步骤可参考日志:STM32开发笔记44:RTC驱动程序的移植。按照日志STM32开发笔记75: 使用STM32CubeMX点亮一个LED使用STM32CubeMX直接生成程序则运行正常。 分析原因在于,少移植了2个函数:HAL_RTC_MspInit和HAL_RTC_MspDeInit。这两个函数的实现非常简单,可以靠STM32CubeMX直接生成。 void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) { __HAL_RCC_RTC_ENABLE(); HAL_NVIC_SetPrio
[单片机]
STM32死机 调试时进入HardFault_Handler定位错误的方法
STM32在运行不正常的时候我们一般会进行调试看看问题出在了哪里。但是当STM32卡死后进行调试的时候会发现进入到了一个HardFault_Handler函数里,这是一个硬件错误处理函数。通过它和MDK配合可以定位程序最后卡死的原因。 STM32卡死的原因有以下几种:数组越界操作;内存溢出,访问越界;堆栈过小;中断处理错误;电压供电异常。 现在实验一个堆栈过小的错误,让MDK来检测这个问题然后定位错误。 这个程序基于UCOSII 系统 #define TFTLCD_STK_PRIO 8 //任务的优先级 #define TFTLCD_STK_SIZE 2 //任务的堆栈大小 OS_STK TFTLCD_TASK_S
[单片机]
STM32<font color='red'>死机</font> 调试时进入HardFault_Handler定位错误的方法
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved