LPC1100 Series Microcontroller UART LPC1100 series Cortex-M0 microcontroller has an asynchronous serial port (UART) that complies with the 16C550 industrial standard. This port also adds a modem interface, and the DSR, DCD and RI Modem signals are only used for the pin configuration of the LQFP48 and PLCC44 packages.
characteristic
16-byte transmit and receive FIFO;
Register location complies with 16C550 industrial standard;
Receiver FIFO trigger point can be 1, 4, 8 and 14 bytes;
Built-in baud rate generator;
Fractional divider for precise baud rate control, and automatic baud rate detection capability and mechanism for software flow control;
Support software or hardware flow control execution;
Contains standard Modem interface signals (CTS, DCD, DTS, DTR, RI, RTS);
Supports 9-bit mode and output enable of RS-458/EIA-485.
【Experimental steps】:
First look at the schematic diagram of the UART on the board
PL-2303HX is a UART-USB chip. Let's ignore its principle here. We only learn how to send data from the CPU to this TXD RXD.
1. LPC11C14 UART register description
Only part of it is posted here
The specific register analysis will not be elaborated here. Let's first look at how we define it in the header file.
/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
/** @addtogroup LPC11xx_UART LPC11xx Universal Asynchronous Receiver/Transmitter
@{
*/
typedef struct
{
union {
__I uint32_t RBR; /*!< Offset: 0x000 Receiver Buffer Register (R/ ) */
__O uint32_t THR; /*!< Offset: 0x000 Transmit Holding Register ( /W) */
__IO uint32_t DLL; /*!< Offset: 0x000 Divisor Latch LSB (R/W) */
};
union {
__IO uint32_t DLM; /*!< Offset: 0x004 Divisor Latch MSB (R/W) */
__IO uint32_t IER; /*!< Offset: 0x000 Interrupt Enable Register (R/W) */
};
union {
__I uint32_t IIR; /*!< Offset: 0x008 Interrupt ID Register (R/ ) */
__O uint32_t FCR; /*!< Offset: 0x008 FIFO Control Register ( /W) */
};
__IO uint32_t LCR; /*!< Offset: 0x00C Line Control Register (R/W) */
__IO uint32_t MCR; /*!< Offset: 0x010 Modem control Register (R/W) */
__I uint32_t LSR; /*!< Offset: 0x014 Line Status Register (R/ ) */
__I uint32_t MSR; /*!< Offset: 0x018 Modem status Register (R/ ) */
__IO uint32_t SCR; /*!< Offset: 0x01C Scratch Pad Register (R/W) */
__IO uint32_t ACR; /*!< Offset: 0x020 Auto-baud Control Register (R/W) */
uint32_t RESERVED0;
__IO uint32_t FDR; /*!< Offset: 0x028 Fractional Divider Register (R/W) */
uint32_t RESERVED1;
__IO uint32_t TER; /*!< Offset: 0x030 Transmit Enable Register (R/W) */
uint32_t RESERVED2[6];
__IO uint32_t RS485CTRL; /*!< Offset: 0x04C RS-485/EIA-485 Control Register (R/W) */
__IO uint32_t ADRMATCH; /*!< Offset: 0x050 RS-485/EIA-485 address match Register (R/W) */
__IO uint32_t RS485DLY; /*!< Offset: 0x054 RS-485/EIA-485 direction control delay Register (R/W) */
__I uint32_t FIFOLVL; /*!< Offset: 0x058 FIFO Level Register (R) */
} LPC_UART_TypeDef;
/*@}*/ /* end of group LPC11xx_UART */
Related macro definitions (partial)
****************************************************************************/
#ifndef __UART_H
#define __UART_H
#define RS485_ENABLED 0
#define TX_INTERRUPT 0 /* 0 if TX uses polling, 1 interrupt driven. */
#define MODEM_TEST 0
#define IER_RBR (0x01<<0)
#define IER_THRE (0x01<<1)
#define IER_RLS (0x01<<2)
#define IIR_PEND 0x01
#define IIR_RLS 0x03
#define IIR_RDA 0x02
#define IIR_CTI 0x06
#define IIR_THRE 0x01
#define LSR_RDR (0x01<<0)
#define LSR_OE (0x01<<1)
#define LSR_PE (0x01<<2)
#define LSR_FE (0x01<<3)
#define LSR_BI (0x01<<4)
#define LSR_THRE (0x01<<5)
#define LSR_TEMT (0x01<<6)
#define LSR_RXFE (0x01<<7)
#define UART0_RBUF_SIZE 64
2. UART initialization
[cpp] view plain copy
/*****************************************************************************
** Function name: UARTInit
**
** Descriptions: Initialize UART0 port, setup pin select,
** clock, parity, stop bits, FIFO, etc.
**
** parameters: UART baudrate
** Returned value: None
**
*****************************************************************************/
void UARTInit(uint32_t baudrate)
{
uint32_t Fdiv;
uint32_t regVal;
UARTTxEmpty = 1;
UARTCount = 0;
NVIC_DisableIRQ(UART_IRQn);
LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
LPC_IOCON->PIO1_6 |= 0x01; /* UART RXD */
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x01; /* UART TXD */
/* Enable UART clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */
LPC_UART->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
regVal = LPC_SYSCON->UARTCLKDIV;
Fdiv = ((SystemAHBFrequency/regVal)/16)/baudrate ; /*baud rate */
LPC_UART->DLM = Fdiv / 256;
LPC_UART->DLL = Fdiv % 256;
LPC_UART->LCR = 0x03; /* DLAB = 0 */
LPC_UART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
/* Read to clear the line status. */
regVal = LPC_UART->LSR;
/* Ensure a clean start, no data in either TX or RX FIFO. */
while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
while ( LPC_UART->LSR & LSR_RDR )
{
regVal = LPC_UART->RBR; /* Dump data from RX FIFO */
}
/* Enable the UART Interrupt */
NVIC_EnableIRQ(UART_IRQn);
#if TX_INTERRUPT
LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */
#else
LPC_UART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */
#endif
return;
}
UART and CPIO ports are multiplexed in CortexM0. Here we see PIO1_6 and PIO1_7 are used.
1. Set the IO port
Take PIO1_7 register as an example
You can see that the lower 3 bits are used to configure pin function 001 to TXD, and the configuration of PIO1_6 is the same.
LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */
LPC_IOCON->PIO1_6 |= 0x01; /* UART RXD */
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x01; /* UART TXD */
2. Clock settings
/* Enable UART clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */
3. Set the baud rate and data bit
LPC_UART->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
regVal = LPC_SYSCON->UARTCLKDIV;
Fdiv = ((SystemAHBFrequency/regVal)/16)/baudrate ; /*baud rate */
4. UART corresponding configuration
LPC_UART->DLM = Fdiv / 256;
LPC_UART->DLL = Fdiv % 256;
LPC_UART->LCR = 0x03; /* DLAB = 0 */
LPC_UART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
Line 4 FCR is the FIFO control register. It controls the use and mode of the UART FIFO.
5. Enable interrupt and other operations
/* Read to clear the line status. */
regVal = LPC_UART->LSR;
/* Ensure a clean start, no data in either TX or RX FIFO. */
while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
while ( LPC_UART->LSR & LSR_RDR )
{
regVal = LPC_UART->RBR; /* Dump data from RX FIFO */
}
/* Enable the UART Interrupt */
NVIC_EnableIRQ(UART_IRQn);
#if TX_INTERRUPT
LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */
#else
LPC_UART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */
#endif
LCR register function
3. Sending Data
[cpp] view plain copy
/*****************************************************************************
** Function name: UARTSend
**
** Descriptions: Send a block of data to the UART 0 port based
** on the data length
**
** parameters: buffer pointer, and data length
** Returned value: None
**
*****************************************************************************/
void UARTSend(uint8_t *BufferPtr, uint32_t Length)
{
while ( Length != 0 )
{
/* THRE status, contain valid data */
#if !TX_INTERRUPT
while ( !(LPC_UART->LSR & LSR_THRE) );
LPC_UART->THR = *BufferPtr;
#else
/* Below flag is set inside the interrupt handler when THRE occurs. */
while ( !(UARTTxEmpty & 0x01) );
LPC_UART->THR = *BufferPtr;
UARTTxEmpty = 0; /* not empty in the THR until it shifts out */
#endif
BufferPtr++;
Length--;
}
return;
}
4. Receiving Data
Here we use interrupt
/*****************************************************************************
** Function name: UART_IRQHandler
**
** Descriptions: UART interrupt handler
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void UART_IRQHandler(void)
{
uint8_t IIRValue, LSRValue;
uint8_t Dummy = Dummy;
IIRValue = LPC_UART->IIR;
IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if (IIRValue == IIR_RLS) /* Receive Line Status */
{
LSRValue = LPC_UART->LSR;
/* Receive Line Status */
if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
{
/* There are errors or break interrupt */
/* Read LSR will clear the interrupt */
UARTStatus = LSRValue;
Dummy = LPC_UART->RBR; /* Dummy read on RX to clear
interrupt, then bail out */
return;
}
if (LSRValue & LSR_RDR) /* Receive Data Ready */
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt */
UARTBuffer[UARTCount++] = LPC_UART->RBR;
if (UARTCount >= UART0_RBUF_SIZE)
{
UARTCount = 0; /* buffer overflow */
}
}
}
else if (IIRValue == IIR_RDA) /* Receive Data Available */
{
/* Receive Data Available */
UARTBuffer[UARTCount++] = LPC_UART->RBR;
if (UARTCount >= UART0_RBUF_SIZE)
{
UARTCount = 0; /* buffer overflow */
}
}
else if (IIRValue == IIR_CTI) /* Character timeout indicator */
{
/* Character Time-out indicator */
UARTStatus |= 0x100; /* Bit 9 as the CTI error */
}
else if (IIRValue == IIR_THRE) /* THRE, transmit holding register empty */
{
/* THRE interrupt */
LSRValue = LPC_UART->LSR; /* Check status in the LSR to see if
valid data in U0THR or not */
if (LSRValue & LSR_THRE)
{
UARTTxEmpty = 1;
}
else
{
UARTTxEmpty = 0;
}
}
return;
}
Let's learn about UART interrupts.
For the UART interface, there are two situations that can trigger the UART receive interrupt: the number of received bytes reaches the trigger point (RDA) of the receive FIFO, and the receive timeout (CTI).
(1) The number of received bytes reaches the trigger point (RDA) in the receive FIFO
The LPC1100 series Cortex-M0 microcontroller UART interface has a 16-byte receive FIFO. The receive trigger point can be set to 1, 4, 8, or 14 bytes. When the number of bytes received reaches the receive trigger point, an interrupt is triggered.
Through the UART FIFO control register U0FCR, the receive trigger point is set to "8-byte trigger". Then when the UART receives 8 bytes, the RDA interrupt will be triggered (Note: under the premise of enabling the receive interrupt).
Let's take a look at IIR
V. Other operations
[cpp] view plain copy
/*******************************************************************************
* Function Name : UART0_PutChar
* Description : Send a char to uart0 channel.
* Input : c
* Output : None
* Return : None
*******************************************************************************/
void UART0_PutChar(char ch)
{
while(!(LPC_UART->LSR & LSR_THRE));
LPC_UART->THR = ch;
}
/*******************************************************************************
* Function Name : uart0_sendstring
* Description : Send string to uart0 channel.
* Input : pString -- string
* Output : None
* Return : None
*******************************************************************************/
void UART0_PutString(char *pString)
{
while(*pString)
{
UART0_PutChar(*pString++);
}
}
/*******************************************************************************
* Function Name : UART0_printf
* Description : print format string.
* Input : fmt
* Output : None
* Return : None
*******************************************************************************/
void UART0_printf(char *fmt, ...)
{
char uart0_pString[101];
va_list uart0_ap;
va_start(uart0_ap, fmt);
vsnprintf(uart0_pString, 100, fmt, uart0_ap);
UART0_PutString(uart0_pString);
will_end(uart0_ap);
}
/*******************************************************************************
* Function Name : UART0_GetChar
* Description : print format string.
* Input : fmt
* Output : None
* Return : None
*******************************************************************************/
uint8_t UART0_GetChar(uint8_t *ch)
{
if(UART_op != UARTCount)
{
*ch = UARTBuffer[UART_op];
UART_on ++;
if(UART_op >= UART0_RBUF_SIZE)
UART_on = 0;
return 1;
}
return 0;
}
Previous article:LPC11C14 startup code analysis
Next article:GPIO Interrupts for LPC178x/7x
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Keysight Technologies Helps Samsung Electronics Successfully Validate FiRa® 2.0 Safe Distance Measurement Test Case
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- 【RPi PICO】Run Fuzix system
- 【EVAL-M3-TS6-665PN】2. PFC working principle
- EEWORLD University ---- SimpleLink? Wi-Fi ??? CC3220 Project Introduction
- [Question and answer post] Jianchi CDK FAQ
- [Zero-knowledge ESP8266 Tutorial] Quick Start 11- Tilt switch to control your light
- About the dynamic load response of the switching power supply, the oscillation phenomenon of the D-pole waveform of the MOS, and the delay problem of output voltage switching
- MotionDRV DC servo drive PID parameter tuning
- Which one is better among ceramic antenna, PCB antenna and IPEX antenna?
- Get accurate, fast and stable analog voltage from digital PWM signal
- EEWorld invites you to dismantle (fifth issue) - Gosund CP5 Pro smart power strip dismantling report