1. 程式人生 > >STM32F103的USART除錯日誌

STM32F103的USART除錯日誌

本次串列埠除錯過程中遇到兩個問題:

1、傳送資料出現死迴圈:

     具體表現為: 程式卡死在 while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);  無資料輸出。TXD線上只是低電平,傳送埠指示燈常亮。

注:串列埠1的引腳定義是PA.09,PA.10

    解決問題:

串列埠初始化時:USART1 和USART6 要使用   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx, ENABLE);而

USART2, USART3, UART4 , UART5要使用 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USARTx, ENABLE) ;問題得以解決。

typedef  struct _UART_CFG
{
	USART_TypeDef* UartNo;
	PIN_CFG Tx;
	PIN_CFG RX;
	uint32_t BaudRate;
	
}UART_CFG;


void Comm_Port_Init(void)
{
	UART_CFG uart_comm;

	uart_comm.UartNo = UART_COM;
	uart_comm.Tx.Pin= GPIO_Pin_9;
	uart_comm.Tx.Port = GPIOA;
	uart_comm.RX.Pin =  GPIO_Pin_10;
	uart_comm.RX.Port = GPIOA;
	uart_comm.BaudRate = BAUD_COM;
	Uart_Init(uart_comm);
}

void Uart_Init(UART_CFG uart)
{
	uint8_t Uart_IRQChannel_No;
	uint32_t RCC_APB1Periph;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	if(uart.UartNo == USART1)
	{
		Uart_IRQChannel_No = USART1_IRQn;
		RCC_APB1Periph = RCC_APB2Periph_USART1;
        RCC_APB2PeriphClockCmd(RCC_APB1Periph, ENABLE);
	}
	else if(uart.UartNo == USART2)
	{
		Uart_IRQChannel_No = USART2_IRQn;
		RCC_APB1Periph = RCC_APB1Periph_USART2;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
	}
	else if(uart.UartNo == USART3)
	{
		Uart_IRQChannel_No = USART3_IRQn;
		RCC_APB1Periph = RCC_APB1Periph_USART3;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
	}
	else if(uart.UartNo == UART4)
	{
		Uart_IRQChannel_No = UART4_IRQn;
		RCC_APB1Periph = RCC_APB1Periph_UART4;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
	}
	else
	{
		Uart_IRQChannel_No = UART5_IRQn;
		RCC_APB1Periph = RCC_APB1Periph_UART5;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
	}
	
	GPIO_InitStructure.GPIO_Pin = uart.Tx.Pin;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(uart.Tx.Port, &GPIO_InitStructure);
   
	GPIO_InitStructure.GPIO_Pin = uart.RX.Pin;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(uart.RX.Port, &GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = uart.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_Init(uart.UartNo, &USART_InitStructure);//初始化外設 USARTx 暫存器

	USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
	USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
	USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
	USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
	USART_ClockInit(uart.UartNo, &USART_ClockInitStructure);

	USART_Cmd(uart.UartNo, ENABLE);
	USART_ITConfig(uart.UartNo,USART_IT_RXNE,ENABLE);//ENABLE-DISABLE//使能或者失能指定的 USART 中斷

	NVIC_InitStructure.NVIC_IRQChannel = Uart_IRQChannel_No;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);   
}

2、接收資料中斷出現死迴圈:

具體表現:收到資料程式會不斷進入中斷,USART_GetITStatus 檢查又沒有中斷髮生。本函式一退出就重新再進入,就這樣死迴圈了。原始碼如下:

void USART2_IRQHandler(void)
{
    BYTE  Data = 0;
    OSIntEnter();
    if(USART_GetITStatus(USART1,USART_IT_RXNE)  !=   RESET)          
         //檢查指定的usart是否發生了中斷
    {
        Data  =   USART_ReceiveData(USART2);
        // do something at this;    處理資料
        USART_ClearFlag(USART2,USART_FLAG_TC ); //清除中斷標誌
    }
    else
    {
        USART_ClearFlag(UART_COM, USART_IT_ORE);
    }
    OSIntExit();
}

解決辦法:

進入中斷後必須第一時間清零RXNE,如沒及時清零,下一幀資料過來時就會產生Overrun error!

更改為如下程式碼就OK了。

void USART2_IRQHandler(void)
{
    BYTE  Data = 0;
    OSIntEnter();
    if(USART_GetITStatus(USART1,USART_IT_RXNE)  !=   RESET) 
      //檢查指定的usart是否發生了中斷
    {
        Data  =   USART_ReceiveData(USART2);
        USART_ClearFlag(USART2,USART_FLAG_TC ); //清除中斷標誌

        // do something at this;    處理資料
    }
    else
    {
        USART_ClearFlag(UART_COM, USART_IT_ORE);
    }
    OSIntExit();
}