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

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