LPC_Uart.c
上传用户:sourcesun
上传日期:2013-09-23
资源大小:362k
文件大小:14k
源码类别:

DNA

开发平台:

Asm

  1. /*************************************************************************
  2.  *
  3.  *    Used with ICCARM and AARM.
  4.  *
  5.  *    (c) Copyright IAR Systems 2003
  6.  *
  7.  *    File name   : LPC_Uart.c
  8.  *    Description : Define API for UART
  9.  *
  10.  *    History :
  11.  *    1. Data: July 13, 2004                                              
  12.  *       Author: Shawn Zhang                                                    
  13.  *       Description: Create the basic function    
  14.  *
  15.  *    2. Data: August 09, 2004                                              
  16.  *       Author: Shawn Zhang                                                    
  17.  *       Description: Integrate two method :- by polling and by interrupt, user 
  18.  *          could select it.
  19.  *
  20.  *    3. Data: August 17, 2004                                              
  21.  *       Author: Shawn Zhang                                                    
  22.  *       Description:  1) Repair the bug about Tx ring buffer.
  23.  *           2) Repair the bug about ReadTxBuf function and ISR.
  24.  *
  25.  *    4. Data        : Oct 9, 2004 
  26.  *       Author      : Stanimir Bonev
  27.  *       Description : Modify some function and interface  
  28.  *
  29.  *    $Revision: 1.1 $
  30.  **************************************************************************/
  31. #include "LPC_Uart.h"
  32. // Define globe variable
  33. LPC_Uart_Config_t Uart0Config = {BD9600, WordLength8, false, false, ParitySelOdd, 
  34.           false, true, FIFORXLEV2, IER_RBR | IER_RLS,
  35.           INTERRUPT_MODE,};
  36.               
  37. LPC_Uart_Config_t Uart1Config = {BD9600, WordLength8, false, false, ParitySelOdd, 
  38.           false, true, FIFORXLEV2, IER_RBR | IER_RLS,
  39.           INTERRUPT_MODE,};
  40. /*************************************************************************
  41.  * Function Name: UART_InitUartBuf
  42.  * Parameters: LPC_Uart_Buffer_t *pUartBuf
  43.  * Return: void
  44.  *
  45.  * Description: Initialize Rx & Tx buffer, which is used when adopting interrupt method
  46.  *  
  47.  *************************************************************************/
  48. void UART_InitUartBuf (LPC_Uart_Buffer_t *pUartBuf)
  49. {
  50.   pUartBuf->RxHeadPoint=0;
  51.   pUartBuf->RxTailPoint=0;
  52.   
  53.   pUartBuf->TxHeadPoint=0;
  54.   pUartBuf->TxTailPoint=0;
  55.   pUartBuf->RxCount=0;
  56.   pUartBuf->TxCount=0;
  57.   pUartBuf->RxFlag=0;
  58. }
  59.               
  60. /*************************************************************************
  61.  * Function Name: UART_Init
  62.  * Parameters: LPC_UartChanel_t DevNum
  63.  *      
  64.  * Return: int 
  65.  *              0: sucess
  66.  *    1: fail
  67.  * Description: Initialize Uart, configure baut rate, frame format and FIFO
  68.  *  
  69.  *************************************************************************/
  70. int UART_Init (LPC_UartChanel_t DevNum)
  71. {
  72. unsigned long Divisor, Frame, FIFO;
  73. LPC_Uart_Config_t *pConfig;
  74.   if ( DevNum == UART0 )
  75.     pConfig = &Uart0Config;
  76.   else
  77.     pConfig = &Uart1Config;
  78.   if ((pConfig->BaudRate == 0) || (pConfig->BaudRate > BD115200))
  79.     return 0;
  80.   // baut rate
  81.   Divisor = (SYS_GetFpclk() >>4) / pConfig->BaudRate; // Divisor = pclk / (16*bautrate)
  82.   // frame format
  83.   Frame = pConfig->WordLenth;
  84.   if ( pConfig->TwoStopBitsSelect )
  85.     Frame |= ( 1<<LCR_STOPBITSEL_BIT );
  86.   if ( pConfig->ParityEnable )
  87.   {
  88.     Frame |= ( 1<<LCR_PARITYENBALE_BIT );
  89.     Frame |= ( pConfig->ParitySelect<<LCR_PARITYSEL_BIT );
  90.   }
  91.   if ( pConfig->BreakEnable )
  92.     Frame |= ( 1<<LCR_BREAKCONTROL_BIT );
  93.   // FIFO
  94.   if ( pConfig->FIFOEnable )
  95.     FIFO = ((pConfig->FIFORxTriggerLevel & 0x3)<<6) | 0x1;
  96.   // Method Mode
  97.   if ( pConfig->MethodMode == INTERRUPT_MODE )
  98.     UART_InitUartBuf (&pConfig->UartBuffer);
  99.   if ( DevNum == UART0 )
  100.   {
  101.     // Set baut rate
  102.     U0LCR_bit.DLAB = true;  // DLAB = 1
  103.     U0DLM = Divisor >> 8;
  104.     U0DLL = Divisor;
  105.     // Set frame format
  106.     U0LCR = Frame;          // DLAB = 0
  107.     // Set FIFO
  108.     U0FCR = FIFO;
  109.     // Set Interrupt Enable Register
  110.     U0IER = pConfig->InterruptEnable & 0x5;
  111.     // Enable TxD0 and RxD0, bit 0~3=0101
  112. //    PINSEL0 |= 0x05;
  113.     PINSEL0_bit.P0_0 = 0x1;
  114.     PINSEL0_bit.P0_1 = 0x1;
  115.   }
  116.   else if ( DevNum == UART1 )
  117.   {
  118.     // Set baut rate
  119.     U1LCR_bit.DLAB = true;      // DLAB = 1
  120.     U1DLM = Divisor>>8;
  121.     U1DLL = Divisor & 0xff;
  122.     // Set frame format
  123.     U1LCR = Frame;              // DLAB =0
  124.     /* Set FIFO */
  125.     U1FCR = FIFO;
  126.     // Set Interrupt Enable Register
  127.     U1IER = pConfig->InterruptEnable & 0x5;
  128.     // Enable TxD0 and RxD0, bit 16~19=0101
  129. //    PINSEL0 |= 0x50000;
  130.     PINSEL0_bit.P0_8 = 0x1;
  131.     PINSEL0_bit.P0_9 = 0x1;
  132.   }
  133.   else
  134.     return 1;
  135.   return 0;
  136. }
  137. /*************************************************************************
  138.  * Function Name: UART_PutCharByPolling
  139.  * Parameters: LPC_UartChanel_t DevNum
  140.  *         char ch
  141.  * Return: void
  142.  *
  143.  *
  144.  * Description: Send character by polling LSR register
  145.  *  
  146.  *************************************************************************/
  147. void UART_PutCharByPolling (LPC_UartChanel_t DevNum, char ch)
  148. {
  149.   if ( DevNum == UART0 )
  150.   {
  151.     while(!U0LSR_bit.THRE);
  152.     U0THR = ch;
  153.   }
  154.   else
  155.   {
  156.     while(!U1LSR_bit.THRE);
  157.     U1THR = ch;
  158.   }
  159. }
  160. /*************************************************************************
  161.  * Function Name: UART_PutStringByPolling
  162.  * Parameters: LPC_UartChanel_t DevNum
  163.  *         char *Buf
  164.  * Return: int : send character count
  165.  *
  166.  *
  167.  * Description: Send a string by using polling method 
  168.  *  
  169.  *************************************************************************/
  170. int UART_PutStringByPolling(LPC_UartChanel_t DevNum, char *Buf)
  171. {
  172. char *pBuf = Buf ;
  173. int SendCount = 0;
  174.   while (*pBuf)
  175.   {
  176.     UART_PutCharByPolling(DevNum, *pBuf++);
  177.     ++SendCount;
  178.   }
  179.   return (SendCount);
  180. }
  181. /*************************************************************************
  182.  * Function Name: UART_GetCharByPolling
  183.  * Parameters: LPC_UartChanel_t DevNum
  184.  * Return: char 
  185.  *
  186.  * Description: Receive a character from Uart by polling LSR register
  187.  *  
  188.  *************************************************************************/
  189. char UART_GetCharByPolling (LPC_UartChanel_t DevNum)
  190. {
  191.   if ( DevNum == UART0 )
  192.   {
  193.     while (!U0LSR_bit.DR);
  194.     return (U0RBR);
  195.   }
  196.   while (!U1LSR_bit.DR);
  197.   return (U1RBR);
  198. }
  199. /*************************************************************************
  200.  * Function Name: UART_PutStringByInterrupt
  201.  * Parameters: LPC_UartChanel_t DevNum
  202.  *         char *Buf
  203.  * Return: int : send character count
  204.  *
  205.  * Description: Send a string into Uart Buffer. 
  206.  *    Then Uart will send buffer data in its IRQ subroutine.
  207.  *  
  208.  *************************************************************************/
  209. int UART_PutStringByInterrupt (LPC_UartChanel_t DevNum, char *Buf)
  210. {
  211. char *pBuf = Buf, ch;
  212. LPC_Uart_Buffer_t *pUartBuf;
  213. int SendCount = 0;
  214. unsigned long IntFlagsHold;
  215.   if ( DevNum == UART0 )
  216.     pUartBuf = &Uart0Config.UartBuffer;
  217.   else
  218.     pUartBuf = &Uart1Config.UartBuffer;
  219.   while (*pBuf)
  220.   {
  221.     // if FIFO is full pending here, wait for send characters
  222.     if (pUartBuf->TxCount >= TXBUFSIZE)
  223.     {
  224.       break;
  225.     }
  226.     ch = *pBuf & 0xff;    
  227.     pUartBuf->TxBuf[pUartBuf->TxTailPoint] = ch;
  228.     pUartBuf->TxTailPoint = (pUartBuf->TxTailPoint+1)%TXBUFSIZE;
  229.     IntFlagsHold = disable_IRQ();
  230.     pUartBuf->TxCount++;
  231.     restore_IRQ(IntFlagsHold);
  232.     SendCount++;
  233.     pBuf++;
  234.   }
  235.   if (DevNum == UART0)
  236.     U0IER |= IER_THRE;
  237.   else
  238.     U1IER |= IER_THRE;
  239.   return SendCount;
  240. }
  241. /*************************************************************************
  242.  * Function Name: UART_GetCharByInterrupt
  243.  * Parameters:  LPC_UartChanel_t DevNum, char *ch
  244.  * Return:  0 -  Rx FIFO is empty 
  245.  *          1 - valid char
  246.  * Description: Get character from Uart Port by making use of interrupt. At same time,
  247.  *    the received data will be stored into its buffer.
  248.  *  
  249.  *************************************************************************/
  250. char UART_GetCharByInterrupt (LPC_UartChanel_t DevNum, char* Buf)
  251. {
  252. LPC_Uart_Buffer_t *pUartBuf;
  253. unsigned long IntFlagsHold;
  254.   if (DevNum == UART0)
  255.   {
  256.     pUartBuf = &Uart0Config.UartBuffer;
  257.   }
  258.   else
  259.   {
  260.     pUartBuf = &Uart1Config.UartBuffer;
  261.   }
  262.   if (pUartBuf->RxCount == 0)
  263.     return 0;
  264.   *Buf = pUartBuf->RxBuf[pUartBuf->RxHeadPoint];
  265.   pUartBuf->RxHeadPoint = (pUartBuf->RxHeadPoint+1)%RXBUFSIZE;
  266.   IntFlagsHold = disable_IRQ();
  267.   pUartBuf->RxCount--;
  268.   restore_IRQ(IntFlagsHold);
  269.   return 1;
  270. }
  271. /*************************************************************************
  272.  * Function Name: UART_PutString
  273.  * Parameters: LPC_UartChanel_t DevNum
  274.  *         char *Buf
  275.  * Return: int : send character count
  276.  *
  277.  *
  278.  * Description: Send a string 
  279.  *  
  280.  *************************************************************************/
  281. int UART_PutString(LPC_UartChanel_t DevNum, char *Buf)
  282. {
  283. LPC_Uart_MethodMode_t MethodMode;
  284.   if ( DevNum == UART0 )
  285.     MethodMode = Uart0Config.MethodMode;
  286.   else
  287.     MethodMode = Uart1Config.MethodMode;
  288.   if (MethodMode)
  289.     // interrupt method
  290.     return(UART_PutStringByInterrupt(DevNum, Buf));
  291.   // Polling method
  292.   return(UART_PutStringByPolling(DevNum, Buf));
  293. }
  294. /*************************************************************************
  295.  * Function Name: UART_GetChar
  296.  * Parameters: LPC_UartChanel_t DevNum
  297.  *
  298.  * Return: char 
  299.  *
  300.  * Description: Receive a character from Uart.
  301.  *  
  302.  *************************************************************************/
  303. char UART_GetChar(LPC_UartChanel_t DevNum)
  304. {
  305. LPC_Uart_MethodMode_t MethodMode;
  306. char ch;
  307.   if ( DevNum == UART0 )
  308.     MethodMode = Uart0Config.MethodMode;
  309.   else
  310.     MethodMode = Uart1Config.MethodMode;
  311.   if (MethodMode)
  312.   {
  313.     // interrupt method
  314.     while(!UART_GetCharByInterrupt(DevNum,&ch));
  315.     return(ch);
  316.   }
  317.   // Polling method
  318.   return(UART_GetCharByPolling(DevNum));
  319. }
  320. /*************************************************************************
  321.  * Function Name: UART_ReadTxBuf
  322.  * Parameters: LPC_Uart_Buffer_t *pUartBuf
  323.  *         char *ch
  324.  * Return: int : 1 one character or more
  325.  *     0 no character in buffer, means current Txcount = 0
  326.  *
  327.  * Description: Read a character from to Uart Buffer, which is only used by IRQ subroutine.
  328.  *  
  329.  *************************************************************************/
  330. #pragma inline
  331. static int UART_ReadTxBuf (LPC_Uart_Buffer_t *pUartBuf, char *ch)
  332. {
  333.   if (pUartBuf->TxCount == 0)
  334.     return 0;
  335.   *ch = pUartBuf->TxBuf[pUartBuf->TxHeadPoint];
  336.   pUartBuf->TxHeadPoint = (pUartBuf->TxHeadPoint+1)%TXBUFSIZE;
  337.   pUartBuf->TxCount--;
  338.   return 1;
  339. }
  340. /*************************************************************************
  341.  * Function Name: UART0_ISR
  342.  * Parameters: void
  343.  * Return: void
  344.  *
  345.  * Description: Uart0 interrupt subroutine
  346.  *  
  347.  *************************************************************************/
  348. void UART0_ISR (void)
  349. {
  350. int i;
  351. char temp;
  352. LPC_Uart_Buffer_t *pUartBuf = &Uart0Config.UartBuffer;
  353.   switch((U0IIR>>1)&0x7)
  354.   {
  355.   case IIR_THRE:  // continue sending data
  356.     // Check for Transmitter FIFO enable
  357.     if (Uart0Config.FIFOEnable) 
  358.       // when FIFO is enable load FIFODEEP bytes
  359.       i = FIFODEEP;
  360.     else
  361.       // when FIFO is disable load 1 byte
  362.       i = 1;
  363.     do
  364.     {
  365.       // Check for software FIFO state and load data into transmitter hold register
  366.       // disable interups imediatly aftre write when FIFO is empty
  367.       if(!UART_ReadTxBuf(pUartBuf, (char*)&U0THR) || (pUartBuf->TxCount == 0))
  368.       {
  369.         // Disable interrup when FIFO is empty
  370.         U0IER_bit.THREIE = false;
  371.         break;
  372.       }
  373.     }
  374.     while(--i);
  375.     break;
  376.   case IIR_RSL: // error manage
  377.     temp = U0LSR;
  378.     pUartBuf->RxFlag |= temp & 0x9E;
  379.     break;
  380.   case IIR_RDA: // receive data
  381.   case IIR_CTI: // time out
  382.     pUartBuf->RxBuf[pUartBuf->RxTailPoint] = U0RBR;
  383.     pUartBuf->RxTailPoint = (pUartBuf->RxTailPoint+1)%RXBUFSIZE;
  384.     // overflow
  385.     if (++pUartBuf->RxCount > RXBUFSIZE)
  386.     {
  387.       pUartBuf->RxHeadPoint = pUartBuf->RxTailPoint;
  388.       pUartBuf->RxFlag |= RC_FIFO_OVERRUN_ERR;
  389.     }
  390.     break;
  391.   default:
  392.     break;
  393.   }
  394.   VICVectAddr = 0;    // Clear interrupt in VIC.
  395. }
  396. /*************************************************************************
  397.  * Function Name: UART1_ISR
  398.  * Parameters: void
  399.  * Return: void
  400.  *
  401.  * Description: Uart1 interrupt subroutine
  402.  *  
  403.  *************************************************************************/
  404. void UART1_ISR (void)
  405. {
  406. int i;
  407. char temp;
  408. LPC_Uart_Buffer_t *pUartBuf = &Uart1Config.UartBuffer;
  409.   switch((U1IIR>>1)&0x7)
  410.   {
  411.   case IIR_THRE:  // continue sending data
  412.     // Check for Transmitter FIFO enable
  413.     if (Uart1Config.FIFOEnable) 
  414.       // when FIFO is enable load FIFODEEP bytes
  415.       i = FIFODEEP;
  416.     else
  417.       // when FIFO is disable load 1 byte
  418.       i = 1;
  419.     do
  420.     {
  421.       // Check for software FIFO state and load data into transmitter hold register
  422.       // disable interups imediatly aftre write when FIFO is empty
  423.       if(!UART_ReadTxBuf(pUartBuf, (char*)&U1THR) || (pUartBuf->TxCount == 0))
  424.       {
  425.         // Disable interrup when FIFO is empty
  426.         U1IER_bit.THREIE = false;
  427.         break;
  428.       }
  429.     }
  430.     while(--i);
  431.     break;
  432.   case IIR_RSL: // error manage
  433.     temp = U1LSR;
  434.     pUartBuf->RxFlag |= temp & 0x9E;
  435.     break;
  436.   case IIR_RDA: // receive data
  437.   case IIR_CTI: // time out
  438.     pUartBuf->RxBuf[pUartBuf->RxTailPoint] = U1RBR;
  439.     if (++pUartBuf->RxCount > RXBUFSIZE)
  440.     {
  441.       pUartBuf->RxFlag |= RC_FIFO_OVERRUN_ERR;
  442.     }
  443.     pUartBuf->RxTailPoint = (pUartBuf->RxTailPoint+1)%RXBUFSIZE;
  444.     break;
  445.   default:
  446.     break;
  447.   }
  448.   VICVectAddr = 0;    // Clear interrupt in VIC.
  449. }