www.pudn.com > uart.zip > uart_drv.c, change:2015-10-23,size:23719b


/******************************************************************************* 
 * Copyright (c) 2015 Suzhou Robot Information Technology Co., Ltd. 
 * Filename   : usart.c 
 * Author     : zj       Version:0.0.1      Date:2015.09.06 
 * Description: 串口驱动模块,实现两路485通讯 
 * Others     : 
 * History    : 
 * <Author>  <Date>    <Version> <Description> 
 *  zj     2015.09.06   0.0.1     从YBMPS3030扩展板移植到YBBM3710电池巡检仪 
 ******************************************************************************/ 
 
/***********************************头文件*************************************/ 
#include "uart_drv.h" 
#include "systime.h" 
#include <string.h> // 包含NULL定义 
 
/***********************************宏定义*************************************/ 
//======定义调试输出====== 
/* C Library output implements */ 
#ifdef __GNUC__ 
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf 
   set to 'Yes') calls __io_putchar() */ 
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) 
#else 
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) // 定义打印输出 
#endif /* __GNUC__ */ 
//======================== 
 
#define MAX_UART_RX_BUF_SZ 512 // 接收buf大小 
#define MAX_UART_TX_BUF_SZ MAX_UART_RX_BUF_SZ // 发送buf大小 
 
// 缺省接收使能空等待字节阈值(接收该数值数据对应的时间:3.5字节*1.14ms/字节 = 3.99ms) 
#define Default_RxNopBytes 3 // 相当于3*1.14+1=4ms延时,小于2ms上层接收不全 
#define Default_TxNopTick 3   // 缺省发送使能空等待,相当于3*1.14+1=4ms延时,小于2ms发送乱码 
#define TX_DATALEN_THRESHOLD (MAX_UART_RX_BUF_SZ / 2) // 发送数据阈值 
#define RX_DATALEN_THRESHOLD (MAX_UART_RX_BUF_SZ / 2) // 接收数据阈值 
 
/********************************内部函数声明**********************************/ 
void uart_init(uart_config_t *pCfg); 
void uart_process(void); 
static void uart_rx_enable_event(void); 
static void uart_rx_data_prepare_event(void); 
static void uart_tx_enable_event(void); 
static void ReceiveUart2Buff(uart_t *pUart); 
static void SendUartFromBuff(uart_t *pUart); 
static void ReadyToReceive(uart_t *pUart); 
static void ReadyToSend(uart_t *pUart); 
 
/* 定义指定串口配置下发送一字节理论需要的延时,N*ms/字节+1ms=Mms */ 
#define BYTEMS_BAUD(num, cfg) \ 
    (((num) * ((((cfg).USART_WordLength == USART_WordLength_8b) ? 8 : 9) + 2) * 1000 \ 
            +((cfg).USART_BaudRate-1))/(cfg).USART_BaudRate) 
 
/**********************************变量定义************************************/ 
/* 串口接收与发送buf */ 
uint8_t rxBuf[USART_CH_CNT][MAX_UART_RX_BUF_SZ]; 
uint8_t txBuf[USART_CH_CNT][MAX_UART_TX_BUF_SZ]; 
// 串口本地配置 
uart_t uartCfg[USART_CH_CNT] = {0}; 
// 打印串口本地配置 
uart_t *pDemoUart = NULL; 
// 串口全双工与半双工定义,全双工:TRUE,半双工:FALSE 
static bool duplex[USART_CH_CNT] = {false, false}; 
// 当前数据帧长,收到的数据达到此长度才开始从串口发送 
static unsigned int g_frame_tx_max_len = 1; 
// 串口引脚配置 
static usart_cfg_t usartpin[USART_CH_CNT] = { 
    { // 顶板的串口1做上位机串口 
        {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_9, GPIO_Speed_50MHz, GPIO_Mode_AF_PP},       // Tx引脚 
        {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_10, GPIO_Speed_50MHz, GPIO_Mode_IN_FLOATING}, // Rx引脚 
        {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_8, GPIO_Speed_50MHz, GPIO_Mode_Out_PP},       // Tx使能脚 
        {Bit_SET, Bit_RESET},   // Tx使能脚IO状态 
        USART1,                 // 串口号 
        RCC_APB2Periph_USART1,  // 所属总线 
        USART1_IRQn,            // 串口中断 
        {   // 波特率等详细配置 
            9600,USART_WordLength_9b,USART_StopBits_1, 
            USART_Parity_Even,USART_Mode_Rx | USART_Mode_Tx, 
            USART_HardwareFlowControl_None 
        } 
    }, 
    { // 底板的串口2做调试串口 
        {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_2, GPIO_Speed_50MHz, GPIO_Mode_AF_PP},       // Tx引脚 
        {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_3, GPIO_Speed_50MHz, GPIO_Mode_IN_FLOATING}, // Rx引脚 
        {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_1, GPIO_Speed_50MHz, GPIO_Mode_Out_PP},      // Tx使能脚 
        {Bit_SET, Bit_RESET},   // Tx使能脚IO状态 
        USART2,                 // 串口号 
        RCC_APB1Periph_USART2,  // 所属总线 
        USART2_IRQn,            // 串口中断 
        {   // 波特率等详细配置 
            115200,USART_WordLength_9b,USART_StopBits_1, 
            USART_Parity_Even,USART_Mode_Rx | USART_Mode_Tx, 
            USART_HardwareFlowControl_None 
        } 
    } 
}; 
// 串口波特率配置含义 
static const unsigned int g_uart_baudrate[5] = { 
    2400, 4800, 9600, 19200, 115200 
}; 
// 串口校验位配置含义 
static const unsigned short g_uart_parity[3] = { 
    USART_Parity_No, USART_Parity_Even, USART_Parity_Odd 
}; 
// 串口停止位配置含义 
static const unsigned short g_uart_stopbits[3] = { 
    USART_StopBits_1_5, USART_StopBits_1, USART_StopBits_2 
}; 
 
//////////////////////////////////////////////////////////////////////////////// 
///////////////////////////////////接口函数///////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
/******************************************************************************* 
*Function    : uart_init 
*Description : 串口硬件相关初始化 
*Parameter   : pCfg[in] - 串口配置 
*Return      : 
*Others      :  
*******************************************************************************/ 
void uart_init(uart_config_t *pCfg) 
{ 
    int i; 
    unsigned short tempData; 
    NVIC_InitTypeDef NVIC_InitStructure; 
 
    for (i = 0; i < USART_CH_CNT; i++) { 
        if (pCfg != NULL) { 
            usartpin[i].cfg.USART_BaudRate = g_uart_baudrate[pCfg->baudrate]; 
            usartpin[i].cfg.USART_Parity = g_uart_parity[pCfg->parity]; 
            usartpin[i].cfg.USART_StopBits = g_uart_stopbits[pCfg->stopbits]; 
            if (usartpin[i].cfg.USART_Parity != USART_Parity_No) { 
                /* 如果是奇偶校验,数据位为9位 */ 
                usartpin[i].cfg.USART_WordLength = USART_WordLength_9b; 
            } else { 
                /* 如果是无校验,数据位为8位 */ 
                usartpin[i].cfg.USART_WordLength = USART_WordLength_8b; 
            } 
        } 
         
        // 初始化串口IO引脚 
        gpio_init(&usartpin[i].iorx); 
        gpio_init(&usartpin[i].iotx); 
         
        // 初始化串口时钟 
        if (RCC_APB2Periph_USART1 == usartpin[i].clk){ 
            RCC_APB2PeriphClockCmd(usartpin[i].clk, ENABLE);  
        }else{ 
            RCC_APB1PeriphClockCmd(usartpin[i].clk, ENABLE); 
        } 
         
        // 初始化串口波特率等配置 
        USART_Init(usartpin[i].reg, &usartpin[i].cfg); 
 
        // 启动串口 
        USART_Cmd(usartpin[i].reg, ENABLE); 
 
        // 初始化串口中断 
        NVIC_InitStructure.NVIC_IRQChannel = usartpin[i].irq; 
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; // 指定抢占式优先级 
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        // 指定响应优先级 
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
        NVIC_Init(&NVIC_InitStructure); 
 
        // 初始化收发buf 
        loopbuff_init(&uartCfg[i].rxbuf, rxBuf[i], MAX_UART_RX_BUF_SZ); 
        loopbuff_init(&uartCfg[i].txbuf, txBuf[i], MAX_UART_TX_BUF_SZ); 
 
        // 给配置赋初值 
        uartCfg[i].cfg = &usartpin[i]; 
        uartCfg[i].duplex = duplex[i]; 
        uartCfg[i].rxen_tick = 0; 
        uartCfg[i].RxTickOkTag = false; 
        tempData = BYTEMS_BAUD(Default_RxNopBytes, uartCfg[i].cfg->cfg); 
        uartCfg[i].RxFrameNopNum =  ((tempData >= 2) ? tempData : 2); 
        uartCfg[i].info.ORE_cnt = 0; 
        uartCfg[i].info.Tx_cnt = 0; 
        uartCfg[i].info.Rx_cnt = 0; 
 
        // 收发状态Tick计数赋初值 
        uartCfg[i].uart_lastTick.rx_en_lastTick = 0; 
        uartCfg[i].uart_lastTick.rx_ok_lastTick = 0; 
        uartCfg[i].uart_lastTick.tx_en_lastTick = 0; // 没写发送buf之前不使能发送中断 
 
        // 使能接收 
        if (uartCfg[i].duplex) { 
            /* 如果是全双工 */ 
            USART_ITConfig(usartpin[i].reg, USART_IT_RXNE, ENABLE); // Enable USART Receive interrupts   
        }else{ 
            /* 如果是半双工 */ 
            gpio_init(&usartpin[i].iotxen); // 初始化串口发送使能脚 
            USART_ITConfig(usartpin[i].reg, USART_IT_RXNE, ENABLE); // Enable USART Receive interrupts 
            // 关闭发送使能脚(不能向外面发送数据) 
            GPIO_WriteBit(usartpin[i].iotxen.port, usartpin[i].iotxen.pin, usartpin[i].iotxen_status.off);  
        } 
    } 
} 
 
/******************************************************************************* 
*Function    : uart_process 
*Description : 串口轮询函数 
*Parameter   : 
*Return      : 
*Others      :  
*******************************************************************************/ 
void uart_process(void) 
{ 
    uart_rx_enable_event(); // 半双工模式下恢复接收中断 
    uart_rx_data_prepare_event(); // 接收数据可被上层读取标志 
    uart_tx_enable_event(); // 恢复发送中断 
} 
 
/******************************************************************************* 
*Function    : uart_put_byte 
*Description : 向串口发送一字节数据,先添加到缓冲区,条件满足后才开始发送(打开发送中断) 
*Parameter   : pUart[in/out] - 串口配置结构体指针 
               UartData[in] - 要发送的1字节数据 
               allDataLen[in] - 当前数据帧的总长度,当数据收满时才开始从串口发送出去 
*Return      : true - 写入缓存成功 
               false - 写入缓存失败 
*Others      :  
*******************************************************************************/ 
bool uart_put_byte(uart_t *pUart, unsigned char UartData, unsigned int allDataLen) 
{ 
    if (loopbuff_push(&pUart->txbuf, UartData) < 0) { 
        /* 如果写入缓存失败 */ 
        return false; 
    } else { 
        /* 如果写入缓存成功 */ 
        if (systime_get_systick()) { 
            pUart->uart_lastTick.tx_en_lastTick = systime_get_systick(); // 开始发送计时,3ms不再写入数据后则开始发送 
        } else { 
            pUart->uart_lastTick.tx_en_lastTick = 1; 
        } 
         
        if (g_frame_tx_max_len != allDataLen) { 
            g_frame_tx_max_len = allDataLen; // 存到buf的数据长度达到最大帧长则开始发送 
        } 
        return true; 
    } 
} 
 
/******************************************************************************* 
*Function    : set_print_uart 
*Description : 设置调试打印串口 
*Parameter   : pUart[in] - 串口配置结构体指针 
*Return      : 
*Others      :  
*******************************************************************************/ 
void set_print_uart(uart_t *pUart) 
{ 
    pDemoUart = pUart; 
} 
 
/******************************************************************************* 
*Function    : get_print_uart 
*Description : 读取调试打印串口配置结构体 
*Parameter   : 
*Return      : 调试串口配置结构体指针 
*Others      :  
*******************************************************************************/ 
uart_t *get_print_uart(void) 
{ 
  return (pDemoUart); 
} 
 
//////////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////内部私有函数/////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
/******************************************************************************* 
*Function    : uart_rx_enable_event 
*Description : 恢复接收中断轮询函数(轮询rxen_tick个ms后开启发送中断) 
*Parameter   : 
*Return      : 
*Others      : 
*******************************************************************************/ 
static void uart_rx_enable_event(void) 
{ 
    unsigned char i; 
 
    for (i=0; i<USART_CH_CNT; i++) { 
        if(uartCfg[i].rxen_tick > 0){ 
            /* 如果需要使能接收状态 */ 
            if (systime_pass_systick(uartCfg[i].uart_lastTick.rx_en_lastTick) 
                >= uartCfg[i].rxen_tick) { 
                /* 如果延时时间到 */ 
                uartCfg[i].rxen_tick = 0; // 清接收使能计时,等待下次半双工发送以后重载初值 
 
                /* 全双工模式下,因为发送发送时会关闭接收中断,需要在这里打开接收中断; 
                       全双工模式下,接收中断保持在常开状态,此处对其无影响 */ 
                USART_ITConfig(uartCfg[i].cfg->reg, USART_IT_RXNE, ENABLE); // Enable USART Receive interrupts 
                // 使能外部接收功能 
                GPIO_WriteBit(uartCfg[i].cfg->iotxen.port, 
                              uartCfg[i].cfg->iotxen.pin, 
                              uartCfg[i].cfg->iotxen_status.off); 
            } 
        } 
    } 
} 
 
/******************************************************************************* 
*Function    : uart_rx_data_prepare_event 
*Description : 设置接收数据可被上层读取的标志 
*Parameter   : 
*Return      : 
*Others      :  
*******************************************************************************/ 
static void uart_rx_data_prepare_event(void) 
{ 
    unsigned char i; 
 
    /* 达到以下2种条件的任何一种,上层才能读取数据: 
        1、距离接收最后1字节数据的时间达到17ms, 
        2、接收buf达到阈值 */ 
    for (i=0; i<USART_CH_CNT; i++) { 
        if (uartCfg[i].info.Rx_cnt > 0) { // 如果收到过数据 
            if (systime_pass_systick(uartCfg[i].uart_lastTick.rx_ok_lastTick) 
                >= uartCfg[i].RxFrameNopNum) { 
                /* 1、距离接收最后1字节数据的时间达到4ms */ 
                uartCfg[i].RxTickOkTag = true; // 置数据可读取标志 
                uartCfg[i].uart_lastTick.rx_ok_lastTick = 0; 
                uartCfg[i].info.Rx_cnt = 0; 
            } else { 
            } 
        } else { 
        } 
 
        if (loopbuff_getlen(&uartCfg[i].rxbuf, 0) 
               >= RX_DATALEN_THRESHOLD) { 
        /* 2、接收buf达到阈值256字节 */ 
        uartCfg[i].RxTickOkTag = true; // 置数据可读取标志 
        } else { 
        } 
    } 
} 
 
/******************************************************************************* 
*Function    : uart_tx_enable_event 
*Description : 恢复发送中断轮询函数 
*Parameter   : 
*Return      : 
*Others      : 
*******************************************************************************/ 
static void uart_tx_enable_event(void) 
{ 
    unsigned char i; 
    unsigned int len = 0; 
 
    for (i=0; i<USART_CH_CNT; i++) { 
        /* 达到以下3种条件的任何一种,才能开始发送数据: 
             1、发送buf达到指定帧包长度, 
             2、发送buf达到阈值, 
             3、距离上次向发送buf写数据的时间达到3ms */ 
        len = loopbuff_getlen(&uartCfg[i].txbuf, 0); // 获取buf长度 
        if (len >= g_frame_tx_max_len) { 
            /* 1.如果达到指定帧包长度 */ 
            uartCfg[i].info.Tx_cnt = 0; // 清零数据帧长计数 
            ReadyToSend(&uartCfg[i]); // 开启发送中断 
        } else if (len >= TX_DATALEN_THRESHOLD) { 
            /* 2.如果达到发送数据buf阈值 */ 
            uartCfg[i].info.Tx_cnt = 0; // 清零数据帧长计数 
            ReadyToSend(&uartCfg[i]); // 开启发送中断 
        } else if (uartCfg[i].uart_lastTick.tx_en_lastTick > 0) { 
            if (systime_pass_systick(uartCfg[i].uart_lastTick.tx_en_lastTick) 
                    >= BYTEMS_BAUD(Default_TxNopTick, uartCfg[i].cfg->cfg)) { 
                /* 3.如果距离上次写发送数据数据的时间达到2ms */ 
                uartCfg[i].info.Tx_cnt = 0; // 清零数据帧长计数 
                ReadyToSend(&uartCfg[i]); // 开启发送中断 
            } 
        } else { 
        } 
    } 
} 
 
/******************************************************************************* 
*Function    : ReceiveUart2Buff 
*Description : 从UART寄存器中读取一个字节到缓冲区 
*Parameter   : pUart[in/out] - 串口配置结构体指针 
*Return      : 
*Others      :  
*******************************************************************************/ 
static void ReceiveUart2Buff(uart_t *pUart) 
{ 
    ploop_buff_t lpbuf = &pUart->rxbuf; 
     
    // Read one byte from the receive data register  
    if (!loopbuff_isfull(lpbuf)) { 
        /* 如果接收buf非满,则从硬件寄存器读1字节数据 */ 
        loopbuff_push(lpbuf, USART_ReceiveData(pUart->cfg->reg)); 
    } else { 
        /* 如果接收buf满,则丢弃硬件寄存器的数据 */ 
        USART_ReceiveData(pUart->cfg->reg); // 空读,清中断 
    } 
 
    pUart->RxTickOkTag = false; // 清接收定时标志,要等待固定延时之后上层才能读取数据 
    pUart->uart_lastTick.rx_ok_lastTick = systime_get_systick(); // 重载上层可读取数据的Tick值 
    pUart->info.Rx_cnt++; 
} 
 
/******************************************************************************* 
*Function    : SendUartFromBuff 
*Description : 从缓冲区中发送一个数据到UART 
*Parameter   : pUart[in/out] - 串口配置结构体指针 
*Return      : 
*Others      :  
*******************************************************************************/ 
static void SendUartFromBuff(uart_t *pUart) 
{ 
    ploop_buff_t lpbuf = &pUart->txbuf; 
     
    if (loopbuff_isempty(lpbuf)) { 
        /* 如果发送缓存为空,没有数据要发送 */ 
        pUart->uart_lastTick.tx_en_lastTick = 0; // 关闭发送使能中断 
        ReadyToReceive(pUart); // 把状态切换为接收 
    } else { 
        /* 如果发送缓存中有数据,则读出1字节数据并发送 */ 
        USART_SendData(pUart->cfg->reg, loopbuff_pull(lpbuf)); // Write one byte to the transmit data register 
        pUart->info.Tx_cnt++; 
    } 
} 
 
/******************************************************************************* 
*Function    : ReadyToReceive 
*Description : 准备接收数据环境 
*Parameter   : pUart[in/out] - 串口配置结构体指针 
*Return      : 
*Others      :  
*******************************************************************************/ 
static void ReadyToReceive(uart_t *pUart) 
{ 
    USART_ITConfig(pUart->cfg->reg, USART_IT_TXE, DISABLE); // Disable the USART Transmit interrupt 
 
    if (!pUart->duplex ){ 
        /* 如果是半双工模式,因为发送时会将发送中断关闭,因此这里保证打开接收中断 */ 
        // 赋值接收使能Tick为发送2字节所需要的时间,走过该Tick后发送使能开启,时间小于2ms时会出现发送乱码 
        pUart->rxen_tick = BYTEMS_BAUD(12, pUart->cfg->cfg); 
        pUart->uart_lastTick.rx_en_lastTick = systime_get_systick(); // 半双工模式发送数据以后重载接收使能要比较的tick 
    } else { 
        /* 如果是全双工模式,接收中断保持在常开状态,不用处理 */ 
    } 
} 
 
/******************************************************************************* 
*Function    : ReadyToSend 
*Description : 开启发送中断 
*Parameter   : 
*Return      : 
*Others      :  
*******************************************************************************/ 
static void ReadyToSend(uart_t *pUart) 
{ 
    if( !pUart->duplex ) 
    { 
        /* 如果串口是半双工,则在发送时先将发送中断关闭 */ 
        USART_ITConfig(pUart->cfg->reg, USART_IT_RXNE, DISABLE); // Enable USART Receive interrupts 
        // 禁用外部接收功能,启用发送功能  
        GPIO_WriteBit(pUart->cfg->iotxen.port, pUart->cfg->iotxen.pin, pUart->cfg->iotxen_status.on);            
    } 
 
    USART_ITConfig(pUart->cfg->reg, USART_IT_TXE, ENABLE); // Enable the USART Transmit interrupt 
} 
 
/******************************************************************************* 
*Function    : PUTCHAR_PROTOTYPE 
*Description : 实现串口打印函数printf,Retargets the C library printf function to the USART. 
*Parameter   : ch[in] - 要打印的1字节数据 
*Return      : ch - 已打印的数据 
*Others      : 注意!半双工模式下用printf会丢数据 
*******************************************************************************/ 
PUTCHAR_PROTOTYPE 
{ 
#ifdef DEBUG_USART_OUTPUT 
    if (pDemoUart == NULL) { 
        return ch; // 没有设备调试口时不输出信息 
    } 
     
    if (!loopbuff_isfull(&pDemoUart->txbuf)) { 
        /* 如果发送buf非满 */ 
        loopbuff_push(&pDemoUart->txbuf, (uint8_t)ch); // 先将数据存入硬件发送buf 
    } else { 
        /* 如果发送buf满,忽略当前数据继续发送以前的 */ 
    } 
 
    if (systime_get_systick()) { 
        pDemoUart->uart_lastTick.tx_en_lastTick = systime_get_systick(); // 开始发送计时,3ms不再写入数据后则开始发送 
    } else { 
        pDemoUart->uart_lastTick.tx_en_lastTick = 1; 
    } 
 
    if (g_frame_tx_max_len != 20) { 
        g_frame_tx_max_len = 20; // 存到buf的数据长度达到固定20字节则开始发送 
    } 
#endif 
     
    return ch; 
} 
 
//////////////////////////////////////////////////////////////////////////////// 
///////////////////////////////////中断函数///////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
/******************************************************************************* 
*Function    : USART1_IRQHandler 
*Description : 串口1中断函数 
*Parameter   : 
*Return      : 
*Others      :  
*******************************************************************************/ 
void USART1_IRQHandler(void) 
{ 
    UART_IRQHandler(&uartCfg[0]); 
} 
 
/******************************************************************************* 
*Function    : USART2_IRQHandler 
*Description : 串口2中断函数 
*Parameter   : 
*Return      : 
*Others      :  
*******************************************************************************/ 
void USART2_IRQHandler(void) 
{ 
    UART_IRQHandler(&uartCfg[1]); 
} 
 
/******************************************************************************* 
*Function    : UART_IRQHandler 
*Description : 串口公用中断处理 
*Parameter   : _this[in/out] - 串口配置结构体指针 
*Return      : 
*Others      :  
*******************************************************************************/ 
void UART_IRQHandler(puart_t _this) 
{ 
     USART_TypeDef *USARTx; 
      
     USARTx = _this->cfg->reg; 
      
    /* 发生ORE(溢出错误)中断时,有两种情况: 
        (1)因为当前接收寄存器中还有有效数据 
        (2)当前寄存器中的数据已经读取完 */ 
    if (USART_GetFlagStatus(USARTx, USART_FLAG_ORE) != RESET) { 
        /* 如果发生溢出错误 */ 
        if (USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) != RESET) { 
            /* 如果接收寄存器不空 */ 
            ReceiveUart2Buff(_this);   // 读数据到缓冲    
        }else{ 
            /* 如果没有接收数据 */ 
            USART_ReceiveData(USARTx); // 用空读数据的方式清中断    
        } 
        _this->info.ORE_cnt++; 
    } 
     
    /* 接收中断 */ 
    if (USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET){ // RXNE 
        ReceiveUart2Buff(_this); // 读数据到缓冲 
    } 
    /* 发送请求中断 */ 
    if (USART_GetITStatus(USARTx, USART_IT_TXE) != RESET) { // TXE 
        /* 如果进入硬件发送寄存器空中断 */ 
        SendUartFromBuff(_this); // 准备发送数据    
    } 
    /* 空闲中断 */ 
    if (USART_GetITStatus(USARTx, USART_IT_IDLE) != RESET) { 
        USART_ReceiveData(USARTx); // 空读清中断 
    } 
     
    /* 其它中断,仅当开启这些中断时使用 */ 
    if (USART_GetITStatus(USARTx, USART_FLAG_PE)) { 
        USART_ReceiveData(USARTx); // 空读,清中断 
    } 
    if (USART_GetITStatus(USARTx, USART_FLAG_FE)) { 
        USART_ReceiveData(USARTx); // 空读,清中断 
    } 
    if (USART_GetITStatus(USARTx, USART_FLAG_NE)) { 
        USART_ReceiveData(USARTx); // 空读,清中断 
    } 
} 
 
//////////////////////////////////////////////////////////////////////////////// 
///////////////////////////////////测试代码///////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////// 
 
#ifdef UART_TEST 
unsigned char *gp_data = "abcdefghijklmnopqrstyvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n"; 
/** 
 * 串口测试1: 测试串口发送,如果不出现乱码则通过 
 */ 
void uart_test1(void) 
{ 
    unsigned int i; 
    systime_init(); 
    uart_init(NULL); 
    set_print_uart(&uartCfg[1]); // 使用底板的串口2 
     
    while (1) { 
        for (i=0; i<10000; i++) { 
            uart_process(); 
        } 
        printf("%s", gp_data); // 调试输出 
        //uart_put_byte(&uartCfg[0], 0x55, 1); // 正常输出 
    } 
} 
#endif