STM32F10x usart数据收发

STM32F10x uart的数据发送接收就三种基本方式,轮询、中断和DMA

1. 轮询(polling)方式

以下是轮询的uart初始化以及发送接收的例子,发送和接收都用轮询的方式。
uint8_t TxBuffer[] = "Buffer Send from USARTy to USARTz using Flags";
uint8_t RxBuffer[TxBufferSize];
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */     

  /* System Clocks Configuration */
  RCC_Configuration();

  /* Configure the GPIO ports */
  GPIO_Configuration();

/* USARTy and USARTz configuration ------------------------------------------------------*/
  /* USARTy and USARTz configured as follow:
        - BaudRate = 230400 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - Even parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate = 230400;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_Even;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  /* Configure USARTy */
  USART_Init(USARTy, &USART_InitStructure);
  /* Configure USARTz */
  USART_Init(USARTz, &USART_InitStructure);

  /* Enable the USARTy */
  USART_Cmd(USARTy, ENABLE);

  /* Enable the USARTz */
  USART_Cmd(USARTz, ENABLE);

  while(TxCounter < TxBufferSize)
  {   
    /* Send one byte from USARTy to USARTz */
    USART_SendData(USARTy, TxBuffer[TxCounter++]);
    /*
        void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
        {
          assert_param(IS_USART_ALL_PERIPH(USARTx));
          assert_param(IS_USART_DATA(Data)); 
          USARTx->DR = (Data & (uint16_t)0x01FF); //往DR写发送的数据
        }
    */

    /* Loop until USARTy DR register is empty */ 
    while(USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET)
    {
    }
    //到这里表示数据发送完毕(USART_FLAG_TXE可以参考STM32F10x usart寄存器描述)
    /* Loop until the USARTz Receive Data Register is not empty */
    while(USART_GetFlagStatus(USARTz, USART_FLAG_RXNE) == RESET)
    {
    }
    //到这里表示数据接收完毕(USART_FLAG_RXNE可以参考STM32F10x usart寄存器描述)
    /* Store the received byte in RxBuffer */
    RxBuffer[RxCounter++] = (USART_ReceiveData(USARTz) & 0x7F);  

  } 
  //后面只是看发送接收数据是否一致,这与测试条件有关,不再赘述。
  /* Check the received data with the send ones */
  TransferStatus = Buffercmp(TxBuffer, RxBuffer, TxBufferSize);
  /* TransferStatus = PASSED, if the data transmitted from USARTy and  
     received by USARTz are the same */
  /* TransferStatus = FAILED, if the data transmitted from USARTy and 
     received by USARTz are different */

  while (1)
  {
  }
}

2. 中断方式读写

STM32F10x USART有很多类型的中断,每个中断类型都有一个使能标志位。
这里写图片描述
中断设定以及使用ringbuffer输入输出的流程如下
(1) 中断的初始化

  NVIC_InitTypeDef NVIC_InitStructure;
  /* Configure the NVIC Preemption Priority Bits */  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  /* Enable the USARTy Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USARTy_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  /* Enable USARTy Receive and Transmit interrupts */
  USART_ITConfig(USARTy, USART_IT_RXNE, ENABLE);
  USART_ITConfig(USARTy, USART_IT_TXE, ENABLE);

一般一个USART端口,输入输出都要设置一个中断位来触发输入输出中断,一般的输入输出只需要设置如下两个中断即可。
USART_IT_RXNE:Receive Data register not empty interrupt
USART_IT_TXE: Transmit Data Register empty interrupt

还有其他的中断位解释如下:
USART_IT_CTS: CTS change interrupt
USART_IT_LBD: LIN Break detection interrupt
USART_IT_TC: Transmission complete interrupt
USART_IT_IDLE: Idle line detection interrupt
USART_IT_PE: Parity Error interrupt
USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)

设置完USART_IT_RXNE和USART_IT_TXE中断之后,读写都会触发中断。
这里我们一般不用USART_IT_TC中断,因为一般来说使用发送数据寄存器空中断(USART_IT_TXE)
发送的效率会高一些。

下面用一个使用ringbuffer,且使用中断方式的例子来熟悉一下中断读写。
(参考http://blog.csdn.net/liyuanbhu/article/details/8886407)
中断处理函数的框架如下,如果检测到错误就清除错误,收到数了就处理。发完当前数据了就发下一个。

void USART1_IRQHandler(void)  
{  
    unsigned int data;  

    if(USART1->SR & 0x0F)   
    {  
        // See if we have some kind of error, Clear interrupt     
        data = USART1->DR;  
    }  
    else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag  
    {    
        data = USART1->DR;  
        // 对收到的数据进行处理,或者干些其他的事    
    }  
    else if(USART1->SR & USART_FLAG_TXE)   
    {  
        { // 可以发送数据了,如果没有数据需要发送,就在这里关闭发送中断  
            USART1->DR =  something;        // Yes, Send character                        
        }                                             
    }    
}      

下面给一个利用环形缓冲区的串口驱动程序。

#ifndef _COM_BUFFERED_H_  
#define _COM_BUFFERED_H_  

#define  COM1                   0  
#define  COM2                   1  

#define  COM_RX_BUF_SIZE        64                /* Number of characters in Rx ring buffer             */  
#define  COM_TX_BUF_SIZE        64                /* Number of characters in Tx ring buffer             */  

#define  COM_NO_ERR             0                /* Function call was successful                       */  
#define  COM_BAD_CH             1                /* Invalid communications port channel                */  
#define  COM_RX_EMPTY           2                /* Rx buffer is empty, no character available         */  
#define  COM_TX_FULL            3                /* Tx buffer is full, could not deposit character     */  
#define  COM_TX_EMPTY           4                /* If the Tx buffer is empty.                         */  


/************************************************************ 
 * function : COMGetCharB  
 * parameter: char port, port can be COM1 / COM2 
 * parameter: char* err   is a pointer to where an error code will be placed: 
 *                   *err is set to COM_NO_ERR   if a character is available 
 *                   *err is set to COM_RX_EMPTY if the Rx buffer is empty 
 *                   *err is set to COM_BAD_CH   if you have specified an invalid channel 
 * return   : char 
 * usage    : This function is called by your application to obtain a character from the communications 
 *               channel. 
 * changelog:  
 *************************************************************/  
unsigned char  COMGetCharB (unsigned char ch, unsigned char *err);  

/************************************************************ 
 * function : COMPutCharB  
 * parameter: char port, port can be COM1 / COM2 
 * return   :    COMM_NO_ERR   if the function was successful (the buffer was not full) 
 *               COMM_TX_FULL  if the buffer was full 
 *               COMM_BAD_CH   if you have specified an incorrect channel 

 * usage    : This function is called by your application to send a character on the communications 
 *               channel.  The character to send is first inserted into the Tx buffer and will be sent by 
 *               the Tx ISR.  If this is the first character placed into the buffer, the Tx ISR will be 
 *               enabled.  If the Tx buffer is full, the character will not be sent (i.e. it will be lost) 
 * changelog:  
 *************************************************************/  
unsigned char COMPutCharB (unsigned char port, unsigned char c);  

/************************************************************ 
 * function : COMBufferInit  
 * parameter:  
 * return   :     
 * usage    : This function is called by your application to initialize the communications module.  You 
 *             must call this function before calling any other functions. 
 * changelog:  
 *************************************************************/  
void  COMBufferInit (void);  

/************************************************************ 
 * function : COMBufferIsEmpty  
 * parameter: char port, port can be COM1 / COM2 
 * return   : char 
 * usage    : This function is called by your application to see  
 *            if any character is available from the communications channel. 
 *            If at least one character is available, the function returns 
 *            FALSE(0) otherwise, the function returns TRUE(1). 
 * changelog:  
 *************************************************************/  
unsigned char  COMBufferIsEmpty (unsigned char port);  

/************************************************************ 
 * function : COMBufferIsFull  
 * parameter: char port, port can be COM1 / COM2 
 * return   : char 
 * usage    : This function is called by your application to see if any more characters can be placed 
 *             in the Tx buffer.  In other words, this function check to see if the Tx buffer is full. 
 *             If the buffer is full, the function returns TRUE otherwise, the function returns FALSE. 
 * changelog:  
 *************************************************************/  
unsigned char COMBufferIsFull (unsigned char port);  

#endif 
/* 
 * file: com_buffered.c 
 * author: Li Yuan 
 * platform: STM32F107 
 * date: 2013-5-5 
 * version: 0.0.1 
 * description: UART Ring Buffer                             
**/  

#include "stm32f10x_usart.h"  
#include "com_buffered.h"  

#define OS_ENTER_CRITICAL()     __set_PRIMASK(1)  
#define OS_EXIT_CRITICAL()      __set_PRIMASK(0)     

/** 
 *  Enables Transmiter interrupt. 
**/  
static void COMEnableTxInt(unsigned char port)  
{  
    static USART_TypeDef* map[2] = {USART1, USART2};  
    USART_ITConfig(map[port], USART_IT_TXE, ENABLE);      
}  
/* 
********************************************************************************************************* 
*                                               DATA TYPES 
********************************************************************************************************* 
*/  
typedef struct {  
    short  RingBufRxCtr;                   /* Number of characters in the Rx ring buffer              */  
    unsigned char  *RingBufRxInPtr;                 /* Pointer to where next character will be inserted        */  
    unsigned char  *RingBufRxOutPtr;                /* Pointer from where next character will be extracted     */  
    unsigned char   RingBufRx[COM_RX_BUF_SIZE];     /* Ring buffer character storage (Rx)                      */  
    short  RingBufTxCtr;                   /* Number of characters in the Tx ring buffer              */  
    unsigned char  *RingBufTxInPtr;                 /* Pointer to where next character will be inserted        */  
    unsigned char  *RingBufTxOutPtr;                /* Pointer from where next character will be extracted     */  
    unsigned char   RingBufTx[COM_TX_BUF_SIZE];     /* Ring buffer character storage (Tx)                      */  
} COM_RING_BUF;  

/* 
********************************************************************************************************* 
*                                            GLOBAL VARIABLES 
********************************************************************************************************* 
*/  

COM_RING_BUF  COM1Buf;  
COM_RING_BUF  COM2Buf;  


/************************************************************ 
 * function : COMGetCharB  
 * parameter: char port, port can be COM1 / COM2 
 * parameter: char* err   is a pointer to where an error code will be placed: 
 *                   *err is set to COM_NO_ERR   if a character is available 
 *                   *err is set to COM_RX_EMPTY if the Rx buffer is empty 
 *                   *err is set to COM_BAD_CH   if you have specified an invalid channel 
 * return   : char 
 * usage    : This function is called by your application to obtain a character from the communications 
 *               channel. 
 * changelog:  
 *************************************************************/  
unsigned char  COMGetCharB (unsigned char port, unsigned char *err)  
{  
//    unsigned char cpu_sr;  

    unsigned char c;  
    COM_RING_BUF *pbuf;  

    switch (port)   
    {                                          /* Obtain pointer to communications channel */  
        case COM1:  
             pbuf = &COM1Buf;  
             break;  

        case COM2:  
             pbuf = &COM2Buf;  
             break;  

        default:  
             *err = COM_BAD_CH;  
             return (0);  
    }  
    OS_ENTER_CRITICAL();  
    if (pbuf->RingBufRxCtr > 0)                            /* See if buffer is empty                   */  
    {                                                        
        pbuf->RingBufRxCtr--;                              /* No, decrement character count            */  
        c = *pbuf->RingBufRxOutPtr++;                      /* Get character from buffer                */  
        if (pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE])   
        {        
            pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];   /* Wrap OUT pointer     */  
        }  
        OS_EXIT_CRITICAL();  
        *err = COM_NO_ERR;  
        return (c);  
    } else {  
        OS_EXIT_CRITICAL();  
        *err = COM_RX_EMPTY;  
        c    = 0;                                        /* Buffer is empty, return 0              */  
        return (c);  
    }  
}  


/************************************************************ 
 * function : COMPutCharB  
 * parameter: char port, port can be COM1 / COM2 
 * return   :    COMM_NO_ERR   if the function was successful (the buffer was not full) 
 *               COMM_TX_FULL  if the buffer was full 
 *               COMM_BAD_CH   if you have specified an incorrect channel 

 * usage    : This function is called by your application to send a character on the communications 
 *               channel.  The character to send is first inserted into the Tx buffer and will be sent by 
 *               the Tx ISR.  If this is the first character placed into the buffer, the Tx ISR will be 
 *               enabled.  If the Tx buffer is full, the character will not be sent (i.e. it will be lost) 
 * changelog:  
 *            1.first implimented by liyuan 2010.11.5 
 *************************************************************/  
unsigned char COMPutCharB (unsigned char port, unsigned char c)  
{  
//    unsigned char cpu_sr;  

    COM_RING_BUF *pbuf;  
    switch (port)   
    {                                                     /* Obtain pointer to communications channel */  
        case COM1:  
             pbuf = &COM1Buf;  
             break;  

        case COM2:  
             pbuf = &COM2Buf;  
             break;  

        default:  
             return (COM_BAD_CH);  
    }  

    OS_ENTER_CRITICAL();  
    if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) {           /* See if buffer is full                    */  
        pbuf->RingBufTxCtr++;                              /* No, increment character count            */  
        *pbuf->RingBufTxInPtr++ = c;                       /* Put character into buffer                */  
        if (pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE]) { /* Wrap IN pointer           */  
            pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];  
        }  
        if (pbuf->RingBufTxCtr == 1) {                     /* See if this is the first character       */  
            COMEnableTxInt(port);                          /* Yes, Enable Tx interrupts                */  
            OS_EXIT_CRITICAL();  
        } else {  
            OS_EXIT_CRITICAL();  
        }  
        return (COM_NO_ERR);  
    } else {  
        OS_EXIT_CRITICAL();  
        return (COM_TX_FULL);  
    }  
}  

/************************************************************ 
 * function : COMBufferInit  
 * parameter:  
 * return   :     
 * usage    : This function is called by your application to initialize the communications module.  You 
 *             must call this function before calling any other functions. 
 * changelog:  
 *************************************************************/  
void  COMBufferInit (void)  
{  
    COM_RING_BUF *pbuf;  

    pbuf                  = &COM1Buf;                     /* Initialize the ring buffer for COM0     */  
    pbuf->RingBufRxCtr    = 0;  
    pbuf->RingBufRxInPtr  = &pbuf->RingBufRx[0];  
    pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];  
    pbuf->RingBufTxCtr    = 0;  
    pbuf->RingBufTxInPtr  = &pbuf->RingBufTx[0];  
    pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];  

    pbuf                  = &COM2Buf;                     /* Initialize the ring buffer for COM1     */  
    pbuf->RingBufRxCtr    = 0;  
    pbuf->RingBufRxInPtr  = &pbuf->RingBufRx[0];  
    pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];  
    pbuf->RingBufTxCtr    = 0;  
    pbuf->RingBufTxInPtr  = &pbuf->RingBufTx[0];  
    pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];  
}  

/************************************************************ 
 * function : COMBufferIsEmpty  
 * parameter: char port, port can be COM1 / COM2 
 * return   : char 
 * usage    : This function is called by your application to see  
 *            if any character is available from the communications channel. 
 *            If at least one character is available, the function returns 
 *            FALSE(0) otherwise, the function returns TRUE(1). 
 * changelog:  
 *************************************************************/  
unsigned char  COMBufferIsEmpty (unsigned char port)  
{  
//    unsigned char cpu_sr;  

    unsigned char empty;  
    COM_RING_BUF *pbuf;  
    switch (port)   
    {                                                     /* Obtain pointer to communications channel */  
        case COM1:  
             pbuf = &COM1Buf;  
             break;  

        case COM2:  
             pbuf = &COM2Buf;  
             break;  

        default:  
             return (1);  
    }  
    OS_ENTER_CRITICAL();  
    if (pbuf->RingBufRxCtr > 0)  
    {                                                      /* See if buffer is empty                   */  
        empty = 0;                                         /* Buffer is NOT empty                      */  
    }   
    else   
    {  
        empty = 1;                                         /* Buffer is empty                          */  
    }  
    OS_EXIT_CRITICAL();  
    return (empty);  
}  


/************************************************************ 
 * function : COMBufferIsFull  
 * parameter: char port, port can be COM1 / COM2 
 * return   : char 
 * usage    : This function is called by your application to see if any more characters can be placed 
 *             in the Tx buffer.  In other words, this function check to see if the Tx buffer is full. 
 *             If the buffer is full, the function returns TRUE otherwise, the function returns FALSE. 
 * changelog:  
 *************************************************************/  
unsigned char COMBufferIsFull (unsigned char port)  
{  
//    unsigned char cpu_sr;  

    char full;  
    COM_RING_BUF *pbuf;  
    switch (port)   
    {                                                     /* Obtain pointer to communications channel */  
        case COM1:  
             pbuf = &COM1Buf;  
             break;  

        case COM2:  
             pbuf = &COM2Buf;  
             break;  

        default:  
             return (1);  
    }  
    OS_ENTER_CRITICAL();  
    if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) {           /* See if buffer is full                    */  
        full = 0;                                      /* Buffer is NOT full                       */  
    } else {  
        full = 1;                                       /* Buffer is full                           */  
    }  
    OS_EXIT_CRITICAL();  
    return (full);  
}  


// This function is called by the Rx ISR to insert a character into the receive ring buffer.  
static void  COMPutRxChar (unsigned char port, unsigned char c)  
{  
    COM_RING_BUF *pbuf;  

    switch (port)   
    {                                                     /* Obtain pointer to communications channel */  
        case COM1:  
             pbuf = &COM1Buf;  
             break;  

        case COM2:  
             pbuf = &COM2Buf;  
             break;  

        default:  
             return;  
    }  
    if (pbuf->RingBufRxCtr < COM_RX_BUF_SIZE) {           /* See if buffer is full                    */  
        pbuf->RingBufRxCtr++;                              /* No, increment character count            */  
        *pbuf->RingBufRxInPtr++ = c;                       /* Put character into buffer                */  
        if (pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE]) { /* Wrap IN pointer           */  
            pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];  
        }  
    }  
}  


// This function is called by the Tx ISR to extract the next character from the Tx buffer.  
//    The function returns FALSE if the buffer is empty after the character is extracted from  
//    the buffer.  This is done to signal the Tx ISR to disable interrupts because this is the  
//    last character to send.  
static unsigned char COMGetTxChar (unsigned char port, unsigned char *err)  
{  
    unsigned char c;  
    COM_RING_BUF *pbuf;  

    switch (port)   
    {                                          /* Obtain pointer to communications channel */  
        case COM1:  
             pbuf = &COM1Buf;  
             break;  

        case COM2:  
             pbuf = &COM2Buf;  
             break;  

        default:  
             *err = COM_BAD_CH;  
             return (0);  
    }  
    if (pbuf->RingBufTxCtr > 0) {                          /* See if buffer is empty                   */  
        pbuf->RingBufTxCtr--;                              /* No, decrement character count            */  
        c = *pbuf->RingBufTxOutPtr++;                      /* Get character from buffer                */  
        if (pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE])   
        {       
            pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];   /* Wrap OUT pointer     */  
        }  
        *err = COM_NO_ERR;  
        return (c);                                        /* Characters are still available           */  
    } else {  
        *err = COM_TX_EMPTY;  
        return (0);                                      /* Buffer is empty                          */  
    }  
}  


void USART1_IRQHandler(void)  
{  
    unsigned int data;  
    unsigned char err;  

    if(USART1->SR & 0x0F)   
    {  
        // See if we have some kind of error     
        // Clear interrupt (do nothing about it!)      
        data = USART1->DR;  
    }  
    else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag  
    {    
        data = USART1->DR;  
        COMPutRxChar(COM1, data);                    // Insert received character into buffer       
    }  
    else if(USART1->SR & USART_FLAG_TXE)   
    {  
        data = COMGetTxChar(COM1, &err);             // Get next character to send.                 
        if (err == COM_TX_EMPTY)   
        {                                            // Do we have anymore characters to send ?     
                                                     // No,  Disable Tx interrupts                  
            //USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, ENABLE);  
            USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;  
        }   
        else   
        {  
            USART1->DR = data;        // Yes, Send character                        
        }                                             
    }    
}      

void USART2_IRQHandler(void)  
{  
    unsigned int data;  
    unsigned char err;  

    if(USART2->SR & 0x0F)   
    {  
        // See if we have some kind of error     
        // Clear interrupt (do nothing about it!)      
        data = USART2->DR;  
    }  
    else if(USART2->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag  
    {    
        data = USART2->DR;  
        COMPutRxChar(COM2, data);                    // Insert received character into buffer       
    }  
    else if(USART2->SR & USART_FLAG_TXE)   
    {  
        data = COMGetTxChar(COM2, &err);             // Get next character to send.                 
        if (err == COM_TX_EMPTY)   
        {                                            // Do we have anymore characters to send ?     
                                                     // No,  Disable Tx interrupts                  
            //USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, ENABLE);  
            USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;  
        }   
        else   
        {  
            USART2->DR = data;        // Yes, Send character                        
        }                                             
    }    
}  

下面给个例子主程序,来演示如何使用上面的串口驱动代码。

#include "misc.h"  
#include "stm32f10x.h"  
#include "com_buffered.h"  

void UART_PutStrB (unsigned char port, uint8_t *str)  
{  
    while (0 != *str)  
    {  
        COMPutCharB(port, *str);  
        str++;  
    }  
}  

void USART1_Init(void)  
{  
    GPIO_InitTypeDef GPIO_InitStructure;  
    USART_InitTypeDef USART_InitStructure;  
    NVIC_InitTypeDef NVIC_InitStructure;  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);  

    /* Configure USART Tx as alternate function push-pull */  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);  

    /* Configure USART Rx as input floating */  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);  

    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_Rx | USART_Mode_Tx;  
    USART_Init(USART1, &USART_InitStructure );   

        USART_Cmd(USART1, ENABLE);  

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

void USART2_Init(void)  
{  
    GPIO_InitTypeDef GPIO_InitStructure;  
    USART_InitTypeDef USART_InitStructure;  
    NVIC_InitTypeDef NVIC_InitStructure;  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);  

    /* Configure USART Tx as alternate function push-pull */  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(GPIOD, &GPIO_InitStructure);  

    /* Configure USART Rx as input floating */  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;  
    GPIO_Init(GPIOD, &GPIO_InitStructure);  

    GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);  
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);  

    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_Rx | USART_Mode_Tx;  
    USART_Init(USART2, &USART_InitStructure );   

        USART_Cmd(USART2, ENABLE);  

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure);  
}  


int main(void)  
{  
    unsigned char c;  
    unsigned char err;  

    USART1_Init();  
    USART2_Init();    
    COMBufferInit();  
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  

    UART_PutStrB(COM1, "Hello World!\n");  
    for(;;)  
    {  
        c = COMGetCharB(COM1, &err);  
        if(err == COM_NO_ERR)  
        {  
            COMPutCharB(COM1, c);  
        }  
    }     
}  

3. DMA方式

http://blog.csdn.net/hongzg1982/article/details/47280667

你可能感兴趣的:(Linux驱动基础)