閑言少敘,,先上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 Configuration void 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 Configuration void 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 Configuration void 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 Handler void 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 上調(diào)試通過的串口收發(fā)測試程序,,發(fā)送采用延時循環(huán),,接收采用中斷,,接收到的數(shù)據(jù)存入緩沖區(qū),。 有很多比較認(rèn)真的實戰(zhàn)派的同學(xué)估計會下載到板子上跑一跑,它確實能跑通,,看起來也沒什么問題,。很多教程甚至官方的代碼都是類似的處理方法。 但這確實有點兒像陷馬坑,,看似一馬平川,,跑著跑著突然連馬帶人 kucha 一聲掉坑里了。這還真不是開玩笑,,某知名樓宇自控公司的產(chǎn)品就在安裝到客戶現(xiàn)場后,,經(jīng)常莫名奇妙的死機(jī)。查來查去,,查去查來,才發(fā)現(xiàn)問題,??墒墙鉀Q起來不容易啊,一個一個的去拆開,,更新代碼,,想想都。,。,。 所以同學(xué)們不要輕視任何一段代碼啊,! 這段代碼的問題是,,如果接收數(shù)據(jù)之間間隔時間較長,可以正常收數(shù)據(jù),。但是如果對方發(fā)送數(shù)據(jù)非??欤蛘吲紶栐谧约哼€沒從串口接收寄存器取走數(shù)據(jù)的時候突然又來了數(shù)據(jù),,會導(dǎo)致 Overrun 標(biāo)志位的置位,。這個標(biāo)志位一置,串口基本上就罷工了,。所以,,在程序中一定要有對異常情況的處理。甚至覺得不會發(fā)生的異常也不要置之不理,。(想一想為什么要填充Flash的空白區(qū)域,?在正常情況下代碼永遠(yuǎn)不會跑到空白區(qū)域是吧,。) 對串口異常的處理可以參考下面中斷處理函數(shù)代碼。當(dāng)然也可以在主程序中定時處理,,以便在中斷失效的情況下還能恢復(fù),。 // USART1 Interrupt Handler void 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; } }
|