一文了解串口打印

闲言少叙,先上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;  }}
(0)

相关推荐

  • GD32E230串口DMA发送接收

    串口使用DMA可以节省MCU运行的时间,节省效率,把单片机内部资源用到最优化.串口DMA就是配置好初始化后,调用串口发送程序时先把要发送的数据保存到DMA缓存,然后使能DMA发送,接下来串口就由硬件自 ...

  • 单片机数据通信怎么学?这个工具要用好:串口通信

    刚开始学单片机的你,是不是会因用程序把LED点亮而感到高兴,会因用程序把数码管点亮而感到高兴.这是好事,这也是想继续学习下去的动力. 但是到了与数据相关的实验时,却感觉很难有所进步.有时候,把驱动写好 ...

  • STM32串口通信基本原理

    通信方式 并行通信 传输原理:数据各个位同时传输 优点:速度快(一个引脚传输一个位) 缺点:占用引脚资源多 串行通信 传输原理:数据按位顺序传输 优点:占用引脚资源少(一个引脚都可以) 缺点:速度相对 ...

  • STM32系统学习——USART(串口通信)

    串口通信是一种设备间非常常用的串行通行方式,其简单便捷,大部分电子设备都支持. 一.物理层 常用RS-232标准,主要规定了信号的用途.通信接口以及信号的电平标准. "DB9接口" ...

  • 分有多节的Word文档如何打印指定页

    Word文档经过分节后,如果编制了重复页码,打印时问题就出现了.例如,前两节均有编号为"3"-"10"的页码,当需要仅仅打印第二节的3-10页时就会遇到难题,因 ...

  • word文档无法打印文件怎么办?Word怎么设置打印双面?

    Word是我们平时工作和学习中经常使用的一种办公软件,主要是用来处理各种文档文件.在我们在Word中写好我们需要的文档后就可以直接连接打印机打印处理了.但是,在我们使用的过程中,经常会遇到Word文档 ...

  • 专题:胡不归最小值问题培优42题,有12道二次函数中考真题,有word文档可打印

    近年来,"胡不归最小值问题"在各地中考试卷中频频出现. 这套<胡不归最小值问题专练提升42题>.前面30题是简单基础的考试真题,适合八年级同学来练习. 后面第31-41 ...

  • 可以打印文档不能打印图片怎么办?

    大家在打印图片的时候经常遇到打印不成功或者打印出来不是自己想要大小的情况,这样的情况应该怎样解决呢? 下面小编就来给大家讲解一下. 首先,请确保您的打印机安装正常,并且可以正常工作哦~可以用word或 ...

  • 教你文档双面打印的四种方法

    在日常办公中要求对文档进行双面打印是很常见的,在 打印机 没有自带双面打印单元的情况下,如何既节约人力成本,又能快速实现双面打印呢?具体情况具体分析,一起看看在下面 在日常办公中要求对文档进行双面打印 ...

  • 替代串口打印,快来围观嵌入式中另一种打印调试的方法

    一.前言 在我们的嵌入式开发中,常常把printf重定向到MCU的串口外设,再配合上位机界面软件,通过打印调试信息的方式来调试我们的嵌入式软件. 此处,我们介绍另一种打印调试的方法--SEGGER 的 ...

  • 串口打印知多少?

    常规打印方法 在STM32的应用中,我们常常对printf进行重定向的方式来把打印信息printf到我们的串口助手. 在MDK环境中,我们常常使用MicroLIB+fputc的方式实现串口打印功能,即 ...

  • 该文档未能打印 文档名:打印机名 单击这儿 显示红问号

    该文档未能打印 文档名:打印机名 单击这儿 ,打开打印队列.要得到协助,请单机"帮助"菜单上的"疑难解答".右下角任务栏打印窗口显示红问号 检查驱动,检查接线, ...