LPC_Uart.c
上传用户:sourcesun
上传日期:2013-09-23
资源大小:362k
文件大小:14k
- /*************************************************************************
- *
- * Used with ICCARM and AARM.
- *
- * (c) Copyright IAR Systems 2003
- *
- * File name : LPC_Uart.c
- * Description : Define API for UART
- *
- * History :
- * 1. Data: July 13, 2004
- * Author: Shawn Zhang
- * Description: Create the basic function
- *
- * 2. Data: August 09, 2004
- * Author: Shawn Zhang
- * Description: Integrate two method :- by polling and by interrupt, user
- * could select it.
- *
- * 3. Data: August 17, 2004
- * Author: Shawn Zhang
- * Description: 1) Repair the bug about Tx ring buffer.
- * 2) Repair the bug about ReadTxBuf function and ISR.
- *
- * 4. Data : Oct 9, 2004
- * Author : Stanimir Bonev
- * Description : Modify some function and interface
- *
- * $Revision: 1.1 $
- **************************************************************************/
- #include "LPC_Uart.h"
- // Define globe variable
- LPC_Uart_Config_t Uart0Config = {BD9600, WordLength8, false, false, ParitySelOdd,
- false, true, FIFORXLEV2, IER_RBR | IER_RLS,
- INTERRUPT_MODE,};
-
- LPC_Uart_Config_t Uart1Config = {BD9600, WordLength8, false, false, ParitySelOdd,
- false, true, FIFORXLEV2, IER_RBR | IER_RLS,
- INTERRUPT_MODE,};
- /*************************************************************************
- * Function Name: UART_InitUartBuf
- * Parameters: LPC_Uart_Buffer_t *pUartBuf
- * Return: void
- *
- * Description: Initialize Rx & Tx buffer, which is used when adopting interrupt method
- *
- *************************************************************************/
- void UART_InitUartBuf (LPC_Uart_Buffer_t *pUartBuf)
- {
- pUartBuf->RxHeadPoint=0;
- pUartBuf->RxTailPoint=0;
-
- pUartBuf->TxHeadPoint=0;
- pUartBuf->TxTailPoint=0;
- pUartBuf->RxCount=0;
- pUartBuf->TxCount=0;
- pUartBuf->RxFlag=0;
- }
-
- /*************************************************************************
- * Function Name: UART_Init
- * Parameters: LPC_UartChanel_t DevNum
- *
- * Return: int
- * 0: sucess
- * 1: fail
- * Description: Initialize Uart, configure baut rate, frame format and FIFO
- *
- *************************************************************************/
- int UART_Init (LPC_UartChanel_t DevNum)
- {
- unsigned long Divisor, Frame, FIFO;
- LPC_Uart_Config_t *pConfig;
- if ( DevNum == UART0 )
- pConfig = &Uart0Config;
- else
- pConfig = &Uart1Config;
- if ((pConfig->BaudRate == 0) || (pConfig->BaudRate > BD115200))
- return 0;
- // baut rate
- Divisor = (SYS_GetFpclk() >>4) / pConfig->BaudRate; // Divisor = pclk / (16*bautrate)
- // frame format
- Frame = pConfig->WordLenth;
- if ( pConfig->TwoStopBitsSelect )
- Frame |= ( 1<<LCR_STOPBITSEL_BIT );
- if ( pConfig->ParityEnable )
- {
- Frame |= ( 1<<LCR_PARITYENBALE_BIT );
- Frame |= ( pConfig->ParitySelect<<LCR_PARITYSEL_BIT );
- }
- if ( pConfig->BreakEnable )
- Frame |= ( 1<<LCR_BREAKCONTROL_BIT );
- // FIFO
- if ( pConfig->FIFOEnable )
- FIFO = ((pConfig->FIFORxTriggerLevel & 0x3)<<6) | 0x1;
- // Method Mode
- if ( pConfig->MethodMode == INTERRUPT_MODE )
- UART_InitUartBuf (&pConfig->UartBuffer);
- if ( DevNum == UART0 )
- {
- // Set baut rate
- U0LCR_bit.DLAB = true; // DLAB = 1
- U0DLM = Divisor >> 8;
- U0DLL = Divisor;
- // Set frame format
- U0LCR = Frame; // DLAB = 0
- // Set FIFO
- U0FCR = FIFO;
- // Set Interrupt Enable Register
- U0IER = pConfig->InterruptEnable & 0x5;
- // Enable TxD0 and RxD0, bit 0~3=0101
- // PINSEL0 |= 0x05;
- PINSEL0_bit.P0_0 = 0x1;
- PINSEL0_bit.P0_1 = 0x1;
- }
- else if ( DevNum == UART1 )
- {
- // Set baut rate
- U1LCR_bit.DLAB = true; // DLAB = 1
- U1DLM = Divisor>>8;
- U1DLL = Divisor & 0xff;
- // Set frame format
- U1LCR = Frame; // DLAB =0
- /* Set FIFO */
- U1FCR = FIFO;
- // Set Interrupt Enable Register
- U1IER = pConfig->InterruptEnable & 0x5;
- // Enable TxD0 and RxD0, bit 16~19=0101
- // PINSEL0 |= 0x50000;
- PINSEL0_bit.P0_8 = 0x1;
- PINSEL0_bit.P0_9 = 0x1;
- }
- else
- return 1;
- return 0;
- }
- /*************************************************************************
- * Function Name: UART_PutCharByPolling
- * Parameters: LPC_UartChanel_t DevNum
- * char ch
- * Return: void
- *
- *
- * Description: Send character by polling LSR register
- *
- *************************************************************************/
- void UART_PutCharByPolling (LPC_UartChanel_t DevNum, char ch)
- {
- if ( DevNum == UART0 )
- {
- while(!U0LSR_bit.THRE);
- U0THR = ch;
- }
- else
- {
- while(!U1LSR_bit.THRE);
- U1THR = ch;
- }
- }
- /*************************************************************************
- * Function Name: UART_PutStringByPolling
- * Parameters: LPC_UartChanel_t DevNum
- * char *Buf
- * Return: int : send character count
- *
- *
- * Description: Send a string by using polling method
- *
- *************************************************************************/
- int UART_PutStringByPolling(LPC_UartChanel_t DevNum, char *Buf)
- {
- char *pBuf = Buf ;
- int SendCount = 0;
- while (*pBuf)
- {
- UART_PutCharByPolling(DevNum, *pBuf++);
- ++SendCount;
- }
- return (SendCount);
- }
- /*************************************************************************
- * Function Name: UART_GetCharByPolling
- * Parameters: LPC_UartChanel_t DevNum
- * Return: char
- *
- * Description: Receive a character from Uart by polling LSR register
- *
- *************************************************************************/
- char UART_GetCharByPolling (LPC_UartChanel_t DevNum)
- {
- if ( DevNum == UART0 )
- {
- while (!U0LSR_bit.DR);
- return (U0RBR);
- }
- while (!U1LSR_bit.DR);
- return (U1RBR);
- }
- /*************************************************************************
- * Function Name: UART_PutStringByInterrupt
- * Parameters: LPC_UartChanel_t DevNum
- * char *Buf
- * Return: int : send character count
- *
- * Description: Send a string into Uart Buffer.
- * Then Uart will send buffer data in its IRQ subroutine.
- *
- *************************************************************************/
- int UART_PutStringByInterrupt (LPC_UartChanel_t DevNum, char *Buf)
- {
- char *pBuf = Buf, ch;
- LPC_Uart_Buffer_t *pUartBuf;
- int SendCount = 0;
- unsigned long IntFlagsHold;
- if ( DevNum == UART0 )
- pUartBuf = &Uart0Config.UartBuffer;
- else
- pUartBuf = &Uart1Config.UartBuffer;
- while (*pBuf)
- {
- // if FIFO is full pending here, wait for send characters
- if (pUartBuf->TxCount >= TXBUFSIZE)
- {
- break;
- }
- ch = *pBuf & 0xff;
- pUartBuf->TxBuf[pUartBuf->TxTailPoint] = ch;
- pUartBuf->TxTailPoint = (pUartBuf->TxTailPoint+1)%TXBUFSIZE;
- IntFlagsHold = disable_IRQ();
- pUartBuf->TxCount++;
- restore_IRQ(IntFlagsHold);
- SendCount++;
- pBuf++;
- }
- if (DevNum == UART0)
- U0IER |= IER_THRE;
- else
- U1IER |= IER_THRE;
- return SendCount;
- }
- /*************************************************************************
- * Function Name: UART_GetCharByInterrupt
- * Parameters: LPC_UartChanel_t DevNum, char *ch
- * Return: 0 - Rx FIFO is empty
- * 1 - valid char
- * Description: Get character from Uart Port by making use of interrupt. At same time,
- * the received data will be stored into its buffer.
- *
- *************************************************************************/
- char UART_GetCharByInterrupt (LPC_UartChanel_t DevNum, char* Buf)
- {
- LPC_Uart_Buffer_t *pUartBuf;
- unsigned long IntFlagsHold;
- if (DevNum == UART0)
- {
- pUartBuf = &Uart0Config.UartBuffer;
- }
- else
- {
- pUartBuf = &Uart1Config.UartBuffer;
- }
- if (pUartBuf->RxCount == 0)
- return 0;
- *Buf = pUartBuf->RxBuf[pUartBuf->RxHeadPoint];
- pUartBuf->RxHeadPoint = (pUartBuf->RxHeadPoint+1)%RXBUFSIZE;
- IntFlagsHold = disable_IRQ();
- pUartBuf->RxCount--;
- restore_IRQ(IntFlagsHold);
- return 1;
- }
- /*************************************************************************
- * Function Name: UART_PutString
- * Parameters: LPC_UartChanel_t DevNum
- * char *Buf
- * Return: int : send character count
- *
- *
- * Description: Send a string
- *
- *************************************************************************/
- int UART_PutString(LPC_UartChanel_t DevNum, char *Buf)
- {
- LPC_Uart_MethodMode_t MethodMode;
- if ( DevNum == UART0 )
- MethodMode = Uart0Config.MethodMode;
- else
- MethodMode = Uart1Config.MethodMode;
- if (MethodMode)
- // interrupt method
- return(UART_PutStringByInterrupt(DevNum, Buf));
- // Polling method
- return(UART_PutStringByPolling(DevNum, Buf));
- }
- /*************************************************************************
- * Function Name: UART_GetChar
- * Parameters: LPC_UartChanel_t DevNum
- *
- * Return: char
- *
- * Description: Receive a character from Uart.
- *
- *************************************************************************/
- char UART_GetChar(LPC_UartChanel_t DevNum)
- {
- LPC_Uart_MethodMode_t MethodMode;
- char ch;
- if ( DevNum == UART0 )
- MethodMode = Uart0Config.MethodMode;
- else
- MethodMode = Uart1Config.MethodMode;
- if (MethodMode)
- {
- // interrupt method
- while(!UART_GetCharByInterrupt(DevNum,&ch));
- return(ch);
- }
- // Polling method
- return(UART_GetCharByPolling(DevNum));
- }
- /*************************************************************************
- * Function Name: UART_ReadTxBuf
- * Parameters: LPC_Uart_Buffer_t *pUartBuf
- * char *ch
- * Return: int : 1 one character or more
- * 0 no character in buffer, means current Txcount = 0
- *
- * Description: Read a character from to Uart Buffer, which is only used by IRQ subroutine.
- *
- *************************************************************************/
- #pragma inline
- static int UART_ReadTxBuf (LPC_Uart_Buffer_t *pUartBuf, char *ch)
- {
- if (pUartBuf->TxCount == 0)
- return 0;
- *ch = pUartBuf->TxBuf[pUartBuf->TxHeadPoint];
- pUartBuf->TxHeadPoint = (pUartBuf->TxHeadPoint+1)%TXBUFSIZE;
- pUartBuf->TxCount--;
- return 1;
- }
- /*************************************************************************
- * Function Name: UART0_ISR
- * Parameters: void
- * Return: void
- *
- * Description: Uart0 interrupt subroutine
- *
- *************************************************************************/
- void UART0_ISR (void)
- {
- int i;
- char temp;
- LPC_Uart_Buffer_t *pUartBuf = &Uart0Config.UartBuffer;
- switch((U0IIR>>1)&0x7)
- {
- case IIR_THRE: // continue sending data
- // Check for Transmitter FIFO enable
- if (Uart0Config.FIFOEnable)
- // when FIFO is enable load FIFODEEP bytes
- i = FIFODEEP;
- else
- // when FIFO is disable load 1 byte
- i = 1;
- do
- {
- // Check for software FIFO state and load data into transmitter hold register
- // disable interups imediatly aftre write when FIFO is empty
- if(!UART_ReadTxBuf(pUartBuf, (char*)&U0THR) || (pUartBuf->TxCount == 0))
- {
- // Disable interrup when FIFO is empty
- U0IER_bit.THREIE = false;
- break;
- }
- }
- while(--i);
- break;
- case IIR_RSL: // error manage
- temp = U0LSR;
- pUartBuf->RxFlag |= temp & 0x9E;
- break;
- case IIR_RDA: // receive data
- case IIR_CTI: // time out
- pUartBuf->RxBuf[pUartBuf->RxTailPoint] = U0RBR;
- pUartBuf->RxTailPoint = (pUartBuf->RxTailPoint+1)%RXBUFSIZE;
- // overflow
- if (++pUartBuf->RxCount > RXBUFSIZE)
- {
- pUartBuf->RxHeadPoint = pUartBuf->RxTailPoint;
- pUartBuf->RxFlag |= RC_FIFO_OVERRUN_ERR;
- }
- break;
- default:
- break;
- }
- VICVectAddr = 0; // Clear interrupt in VIC.
- }
- /*************************************************************************
- * Function Name: UART1_ISR
- * Parameters: void
- * Return: void
- *
- * Description: Uart1 interrupt subroutine
- *
- *************************************************************************/
- void UART1_ISR (void)
- {
- int i;
- char temp;
- LPC_Uart_Buffer_t *pUartBuf = &Uart1Config.UartBuffer;
- switch((U1IIR>>1)&0x7)
- {
- case IIR_THRE: // continue sending data
- // Check for Transmitter FIFO enable
- if (Uart1Config.FIFOEnable)
- // when FIFO is enable load FIFODEEP bytes
- i = FIFODEEP;
- else
- // when FIFO is disable load 1 byte
- i = 1;
- do
- {
- // Check for software FIFO state and load data into transmitter hold register
- // disable interups imediatly aftre write when FIFO is empty
- if(!UART_ReadTxBuf(pUartBuf, (char*)&U1THR) || (pUartBuf->TxCount == 0))
- {
- // Disable interrup when FIFO is empty
- U1IER_bit.THREIE = false;
- break;
- }
- }
- while(--i);
- break;
- case IIR_RSL: // error manage
- temp = U1LSR;
- pUartBuf->RxFlag |= temp & 0x9E;
- break;
- case IIR_RDA: // receive data
- case IIR_CTI: // time out
- pUartBuf->RxBuf[pUartBuf->RxTailPoint] = U1RBR;
- if (++pUartBuf->RxCount > RXBUFSIZE)
- {
- pUartBuf->RxFlag |= RC_FIFO_OVERRUN_ERR;
- }
- pUartBuf->RxTailPoint = (pUartBuf->RxTailPoint+1)%RXBUFSIZE;
- break;
- default:
- break;
- }
- VICVectAddr = 0; // Clear interrupt in VIC.
- }