📄 lpc_uart.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2003
*
* File name : LPC_Uart.c
* Description : Define API for UART
*
* History :
* 1. Date: July 13, 2004
* Author: Shawn Zhang
* Description: Create the basic function
*
* 2. Date: August 09, 2004
* Author: Shawn Zhang
* Description: Integrate two method :- by polling and by interrupt, user
* could select it.
*
* 3. Date: 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. Date : Oct 9, 2004
* Author : Stanimir Bonev
* Description : Modify some function and interface
*
* $Revision: 13961 $
**************************************************************************/
#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_UartChannel_t DevNum
*
* Return: int
* 0: success
* 1: fail
* Description: Initialize Uart, configure baud rate, frame format and FIFO
*
*************************************************************************/
int UART_Init (LPC_UartChannel_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;
// baud rate
Divisor = (SYS_GetFpclk() >>4) / pConfig->BaudRate; // Divisor = pclk / (16*baudrate)
// 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 baud 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 baud 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_UartChannel_t DevNum
* char ch
* Return: void
*
*
* Description: Send character by polling LSR register
*
*************************************************************************/
void UART_PutCharByPolling (LPC_UartChannel_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_UartChannel_t DevNum
* char *Buf
* Return: int : send character count
*
*
* Description: Send a string by using polling method
*
*************************************************************************/
int UART_PutStringByPolling(LPC_UartChannel_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_UartChannel_t DevNum
* Return: char
*
* Description: Receive a character from Uart by polling LSR register
*
*************************************************************************/
char UART_GetCharByPolling (LPC_UartChannel_t DevNum)
{
if ( DevNum == UART0 )
{
while (!U0LSR_bit.DR);
return (U0RBR);
}
while (!U1LSR_bit.DR);
return (U1RBR);
}
/*************************************************************************
* Function Name: UART_PutStringByInterrupt
* Parameters: LPC_UartChannel_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_UartChannel_t DevNum, char *Buf)
{
char *pBuf = Buf, ch;
LPC_Uart_Buffer_t *pUartBuf;
int SendCount = 0;
unsigned long save;
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;
save = __get_interrupt_state();
__disable_interrupt();
pUartBuf->TxCount++;
__set_interrupt_state(save);
SendCount++;
pBuf++;
}
if (DevNum == UART0)
U0IER |= IER_THRE;
else
U1IER |= IER_THRE;
return SendCount;
}
/*************************************************************************
* Function Name: UART_GetCharByInterrupt
* Parameters: LPC_UartChannel_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_UartChannel_t DevNum, char* Buf)
{
LPC_Uart_Buffer_t *pUartBuf;
unsigned long save;
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;
save = __get_interrupt_state();
__disable_interrupt();
pUartBuf->RxCount--;
__set_interrupt_state(save);
return 1;
}
/*************************************************************************
* Function Name: UART_PutString
* Parameters: LPC_UartChannel_t DevNum
* char *Buf
* Return: int : send character count
*
*
* Description: Send a string
*
*************************************************************************/
int UART_PutString(LPC_UartChannel_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_UartChannel_t DevNum
*
* Return: char
*
* Description: Receive a character from Uart.
*
*************************************************************************/
char UART_GetChar(LPC_UartChannel_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 interrupts immediately after write when FIFO is empty
if(!UART_ReadTxBuf(pUartBuf, (char*)&U0THR) || (pUartBuf->TxCount == 0))
{
// Disable interrupt 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 interrupts immediately after write when FIFO is empty
if(!UART_ReadTxBuf(pUartBuf, (char*)&U1THR) || (pUartBuf->TxCount == 0))
{
// Disable interrupt 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.
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -