閑言少敘,先上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 上調試通過的串口收發(fā)測試程序,發(fā)送采用延時循環(huán),接收采用中斷,接收到的數據存入緩沖區(qū)。
有很多比較認真的實戰(zhàn)派的同學估計會下載到板子上跑一跑,它確實能跑通,看起來也沒什么問題。很多教程甚至官方的代碼都是類似的處理方法。
但這確實有點兒像陷馬坑,看似一馬平川,跑著跑著突然連馬帶人 kucha 一聲掉坑里了。這還真不是開玩笑,某知名樓宇自控公司的產品就在安裝到客戶現場后,經常莫名奇妙的死機。查來查去,查去查來,才發(fā)現問題。可是解決起來不容易啊,一個一個的去拆開,更新代碼,想想都。。。
所以同學們不要輕視任何一段代碼啊!
這段代碼的問題是,如果接收數據之間間隔時間較長,可以正常收數據。但是如果對方發(fā)送數據非常快,或者偶爾在自己還沒從串口接收寄存器取走數據的時候突然又來了數據,會導致 Overrun 標志位的置位。這個標志位一置,串口基本上就罷工了。所以,在程序中一定要有對異常情況的處理。甚至覺得不會發(fā)生的異常也不要置之不理。(想一想為什么要填充Flash的空白區(qū)域?在正常情況下代碼永遠不會跑到空白區(qū)域是吧。)
對串口異常的處理可以參考下面中斷處理函數代碼。當然也可以在主程序中定時處理,以便在中斷失效的情況下還能恢復。
// 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; }}
編輯:jq
-
寄存器
+關注
關注
31文章
5325瀏覽量
120032 -
串口
+關注
關注
14文章
1543瀏覽量
76216 -
函數
+關注
關注
3文章
4308瀏覽量
62434 -
STM
+關注
關注
1文章
555瀏覽量
42377
原文標題:單片機(MCU)如何才能不死機之串口Overrun
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論