本次串口调试过程中遇到两个问题:
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();
}