LPC2148 UART
LPC2148 UART
The simplest way to communicate between a computer and a microcontroller is through UART
i.e. Universal Asynchronous Receiver Transmitter. It is a type of Serial Communication Protocol
and it uses only two wires for transferring the data. Normally, we need to connect the
microcontroller to the computer using a COM Port. But the modern day computers and laptops
doesn’t include a COM port as the USB ports have replaced them.
Hence now – a – days, the interface between a microcontroller and the computer is through USB
Port with the help of USB – to – RS232 modules that are based on the USB – to – UART Bridge
ICs like CP210x from Silicon Labs or FT232R from FTDI.
Basics of UART
Before going to the UART Programming in LPC2148 MCUs, let us first see some basics of the
UART Protocol. As mentioned earlier, the UART Protocol uses only two wires (or pins in a
device like microcontroller) to transmit the data. In that, one is for transmitting the data and the
pin is called TX pin in the device. The other pin is used to receive the data and is called RX pin.
As UART is a serial communication, the data is transmitted in a series of packets. Usually, a
packet consists of 4 parts: a start bit, the actual data, a parity bit and stop bits. The following
image shows a typical structure of the data packet in UART.
UART in LPC2148
Coming to UART in LPC2148, the LPC214x series of MCUs have two UART blocks called
UART0 and UART1. Each UART block is associated with two pins, one for transmission and
the other for receiving.
In UART0 block, the TXD0 (Transmit) and RXD0 (Receive) pins in the device are P0.0 and
P0.1 respectively. In case of UART1, the TXD1 and RXD1 pins are P0.8 and P0.9 respectively.
UART0 UART1
TXD0 P0.0 TXD1 P0.8
RXD0 P0.1 RXD1 P0.9
Both the UART modules are identical, except the UART1 block has an additional full modem
interface. This includes all the pins for RS232 compatibility like flow control pins (CTS, RTS)
etc.
Both the UART blocks have 16 byte Receive and Transmit FIFO structures to hold the transmit
and receive data. In order to control the data access and assembly, the UART blocks have two
registers each.
23 | Prepared By: U. U. Deshpande
For the transmitter operation, the TX has two special registers called Transmit Holding Register
(THR) and Transmit Shift Register (TSR). In order to transmit the data, it is first sent to THR
and then moved to TSR.
For the receiver operation, the RX has two special registers called Receiver Buffer Register
(RBR) and Receive Shift Register (RSR). When the data is received, it is first stored in the RSR
and then moved to RBR.
Registers associated with UART in LPC2148
There are many registers involved with the UART blocks. UART0 and UART1 have a similar
register structure and here we are mentioning some of the important registers of the UART0
block. In order to access the registers in UART1 block, simply replace the ‘0’ with ‘1’.
UART0 Receiver Buffer Register (U0RBR): The Receiver Buffer Register consists of the top
byte of the RX FIFO. This is the data that is first arrived and Bit 0 contains the oldest data. In
case the received data is less than 8 bits, the remaining bits are padded with 0’s. In order to
access the U0RBR register, the Divisor Latch Access bit (DLAB) in the UART0 Line Control
Register (U0LCR) must be set to 0. With reference to the user manual, it is advised that the
U0LSR register is read first and then the U0RBR register is read.
UART0 Transmit Holding Register (U0THR): The Transmit Holding Register consists of the
top byte of the TX FIFO i.e. the oldest data. Bit 0 (LSB) is the first data to be transmitted. In
order to access the U0THR register, the Divisor Latch Access Bit (DLAB) bit in the UART0
Line Control Register (U0LCR) must be made zero.
UART0 Divisor Latch Registers (U0DLL and U0DLM): The Divisor Latch Registers determine
the baud rate of the UART0. The Divisor Latch is a part of the Baud Rate Generator. The
U0DLL and U0DLM registers contains the lower and higher 8 – bits of the divisor and together
they form the 16 – bit divisor value. Since it contains the divisor value, the U0DLL cannot
contain 0x00 as division by zero is invalid. Hence, the minimum value for the U0DLM:U0DLL
combination is 0x00:0x01. In order to access the Divisor Latch Registers, the Divisor Latch
Access Bit (DLAB) bit in the UART0 Line Control Register (U0LCR) must be set to 1.
UART0 Fractional Divider Register (U0FDR): The Fractional Divider Register contains the bits
that control the prescale for the baud rate generator. U0FDR contains the divisor and multiplier
values for prescaling. Both the divisor (DIVADDVAL) and multiplier (MULVAL) values are
stored as 4 – bit values. Bit 0 to Bit 3 in U0FDR contains the pre – scaler divisor value for baud
rate generation. For the baud rate generator to have an impact on the baud rate of the UART, the
divisor value must not be 0. Bit 4 to bit 7 in U0FDR contains the pre – scaler multiplier value.
For proper working of the UART0, the value in multiplier must be greater than or equal to 1.
This is also applicable even if the baud rate generator is not used.
UART0 Interrupt Enable Register (U0IER): The Interrupt Enable Register is used to enable or
disable the interrupts corresponding to UART0. Bit 0 is for RBR Interrupt, Bit 1 is for THRE
interrupt, Bit 2 is for RX Line Status Interrupt, Bit 8 is for End of Auto – baud interrupt and Bit 9
is for Auto – baud Time out interrupt. When a bit is 0, the interrupt is disabled and when the bit
is 1, the interrupt is enabled.
UART0 Interrupt Identification Register (U0IIR): The Interrupt Identification Register is used
to provide the code for priority and status of the pending interrupt.
24 | Prepared By: U. U. Deshpande
UART0 FIFO Control Register (U0FCR): The FIFO Control Register controls the operation of
the RX and TX FIFOs in UART0. Bit 0 is used to enable or disable the FIFO. Bit 1 is used to
reset the RX FIFO. Bit 2 is used to reset the TX FIFO. Bits 6 and 7 are used to control when the
interrupt must occur i.e. after how many receiver characters.
UART0 Line Control Register (U0LCR): The Line Control Register is used to set the format
of the data which is transmitted or received.
Bit Name Value Description
00 5 bit data length
01 6 bit data length
1:0 Word Length
10 7 bit data length
11 8 bit data length
0 1 stop bit
2 Stop Bit
1 2 stop bits
0 Disable Parity
3 Parity Enable
1 Enable Parity
00 Odd Parity
01 Even Parity
5:4 Parity Select
10 Forced 1 parity
11 Forced 0 parity
0 Disable break transmission
6 Break Control
1 Enable break transmission
0 Disable access to Divisor Latches
7 Divisor Latch Access Bit (DLAB)
1 Enable access to Divisor Latches
UART0 Line Status Register (U0LSR): The Line Status Register gives us the information about
the RX and TX blocks in UART0.
UART0 Transmit Enable Register (U0TER): The Transmit Enable Register is used to enable
the data transmission i.e. it is used to enable implementation of software flow control. The Bit 7
in U0TER register i.e. TXEN is the only bit available for user. When this bit is high, the UART0
TX will keep on sending data. When this bit becomes 0, the data transmission will stop.
Baud Rate Generation in UART
The formula for calculating UART baud rate is given below,
25 | Prepared By: U. U. Deshpande
The following rules must be followed for the Baud rate generation.
Minimum value for MULVAL must be 1 i.e. 0 < MULVAL <= 15.
The value for DIVADDVAL can be between 0 and 15 with both the extremes included i.e.
0 <= DIVADDVAL <= 15.
In order to get a baud rate of 9600 (which is the most common baud rates) at a peripheral clock
frequency of 60 MHz, the following calculations must be followed.
Try with DLM (U0DLM) = 0, DIVADDVAL = 0, MULVAL = 1. By substituting these values in
above formula, then we get DLL (U0DLL) as 390.625. Since U0DLL is an 8 – bit register, this
value is out of range.
By continuing this trial and error method, we end up at the following settings in order to get a
baud rate of 9600 (approximately) with PCLK being 60 MHz.
U0DLM = 1, U0DLL = 110, DIVADDVAL = 1, MULVAL = 15
26 | Prepared By: U. U. Deshpande
1. Initialization of UART0
We can consider it to be 98 or 97. It will make the baud rate slightly less or more than 9600. This small change is
tolerable. We will consider 97. Since 97 is less than 256 and register values cannot contain fractions, we will take
U0DLM = 0. This will give U0DLM = 97.
void UART0_init(void)
{
PINSEL0 = PINSEL0 | 0x00000005; /* Enable UART0 Rx0 and Tx0 pins of UART0 */
U0LCR = 0x83; /* DLAB = 1, 1 stop bit, 8-bit character length */
U0DLM = 0x00; /* For baud rate of 9600 with Pclk = 15MHz */
U0DLL = 0x61; /* We get these values of U0DLL and U0DLM from formula */
U0LCR = 0x03; /* DLAB = 0 to Lock MULVAL and DIVADDVAL* /
}
2. Receiving character
Monitor the RDR bit in U0LSR register to see if valid data is available in U0RBR register.
unsigned char UART0_RxChar(void) /*A function to receive a byte on UART0 */
{
while( (U0LSR & 0x01) == 0); /*Wait till RDR bit becomes 1 which tells that receiver contains valid
data */
return U0RBR;
}
3. Transmitting character
Monitor the THRE bit in U0LSR register. When this bit becomes 1, it indicates that U0THR register is empty and
the transmission is completed.
void UART0_TxChar(char ch) /*A function to send a byte on UART0 */
{
U0THR = ch;
while( (U0LSR & 0x20) == 0 ); /* Wait till THRE bit becomes 1 which tells that transmission is
completed */
}
#include <lpc214x.h>
#include <stdint.h>
#include "UART.h"
int main(void)
{
char receive;
UART0_init();
while(1)
{
receive = UART0_RxChar();
UART0_SendString("\r\n");
}
}
UART Programming in LPC2148
We will see the configuring and initialization of the UART0 block in the following example
where we send some data to the Computer.
#include <lpc214x.h>
#define New_Line 0xA
void UARTWrite(char data);
int main(void)
{
char msg[] = { ‘E’,’l’,’e’,’c’,’t’,’r’,’o’,’n’,’i’,’c’,’s’,’ ‘,’H’,’u’,’b’,’\0′ };
int c=0; // counter
/* Configuring PLL for generation of 60 MHz CCLK and PCLK */
PLL0CON = 0x01;
PLL0CFG = 0x23;
PLL0FEED = 0xaa;
PLL0FEED = 0x55;
while(!(PLL0STAT & 0x00000400));
PLL0CON = 0x03;
PLL0FEED = 0xaa;
PLL0FEED = 0x55;
VPBDIV = 0x01;
/*Configure and Initialize UART */
PINSEL0 = 0x5; /*Select TxD for P0.0 and RxD for P0.1*/
U0LCR = 0x83; /*8 data bits, no Parity, 1 Stop bit | DLAB is set to 1*/
U0DLL = 0x6e; /* DLL set to 110*/
U0DLM = 0x01; /* DLM set to 1*/
U0FDR = 0xf1; /* MULVAL bits – 7:4) is set to 15 and DIVADDVAL (bits – 3:0) is set to 1*/
U0LCR &= 0x0f; // Set DLAB=0 to lock MULVAL and DIVADDVAL
while (1)
{
while( msg[c]!=’\0′ )
{
UARTWrite(msg[c]);
c++;
}
UARTWrite(New_Line);
c=0;
}
}
void UARTWrite(char data)
{
while ( !(U0LSR & 0x20 ) ); // wait till the THR is empty
U0THR = data;
}
27 | Prepared By: U. U. Deshpande
Analog-to-Digital Converter (ADC)
Features:
• 10 bit successive approximation analog to digital converter (one in LPC2141/2
and two in LPC2144/6/8).
• Input multiplexing among 6 or 8 pins (ADC0 and ADC1).
• Power-down mode.
• Measurement range 0 V to VREF (typically 3 V; not to exceed VDDA voltage
level).
• 10 bit conversion time ≥ 2.44 μs.
• Burst conversion mode for single or multiple inputs.
• Optional conversion on transition on input pin or Timer Match signal.
• Global Start command for both converters (LPC2144/6/8 only).
Description:
Basic clocking for the A/D converters is provided by the APB clock. A
programmable divider is included in each converter, to scale this clock to the 4.5
MHz (max) clock needed by the successive approximation process. A fully
accurate conversion requires 11 of these clocks.
28 | Prepared By: U. U. Deshpande
ADC Registers
O Control Register: Selects channel, clock freq, resolution, conversion mode,
method of issue of SoC, edge for conversion
O Global Start Register: Used to initiate simultaneous conversion on both ADCs
O Status Register:
Allows simultaneous checking of status of all A/D channels,
Contains done, overrun, interrupt flags
O Data Registers (DR0 – DR7): Contains most recent converted data and EoC
status on respected ch,
O Global Data Register: Contains done bit, most converted data, ch number
O Interrupt Enable Register: Enables interrupt on Eoc by each channel.
29 | Prepared By: U. U. Deshpande
30 | Prepared By: U. U. Deshpande
31 | Prepared By: U. U. Deshpande
32 | Prepared By: U. U. Deshpande
Programming ADC registers – Examples (Construction of control words)
Select ADC-0, Channel-1, Clock frequency 4 MHz (let PCLK is 60 MHz), Software
controlled mode and 10-bit resolution. Power-up ADC and issue start of conversion.
33 | Prepared By: U. U. Deshpande
Digital-to-Analog Converter (DAC)
34 | Prepared By: U. U. Deshpande
SPI Interface
SPI (Synchronous Peripheral Interface) is one of the important protocols used in
Microcontrollers to establish serial communication between two devices. This protocol was
widely used in many devices since the data transfer rate is pretty high than other protocols such
as UART and I2C. This article deals with SPI protocol tutorial using ARM 7 Microcontroller.
The above design shows two controllers one of which is Master which transmits the data and the
other one is the slave which receives the data and exhibit it its port1. The port 1 is provided with
8 LED’s which indicate represents the received data from the master controller.
SPI PROTOCOL:
SPI is a synchronous, full duplex protocol which basically requires three communication lines to
establish the connection between the devices. Hence it was also called as 3 wire interface
protocol. A controller should act as a master and other should act like slaves. A master can have
multiple slaves also both the master and slave can transmit/receive data. ARM 7
Microcontrollers possess two SPI controllers which controls SPI0 and SPI1.
PIN FUNCTIONS:
As i said above three communication line forms the backbone of this protocol, however a fourth
one was also used to select the slaves by the master. The function of the Pins used in our
controller is as follows.
MOSI – Master Output Slave Input pin serves as output pin for the Master and input for Slave.
MISO – Master Input Slave Output serves as input pin fro Master and output for the slave.
SCK – This pin generates the required clock for the communication to takes place. Master
generates clock and feed the pulse to the slave device.
SSEL – This pin is used to select the slave device when multiple slave devices are used along
with a single master. The SSEL is an active low pin, so to select a particular slave this pin should
be pulled low.
REGISTERS USED IN SPI PROTOCOL:
In ARM7 controllers we use four registers to control the operation of the SPI they are as follows.
SPCR REGISTER:
SPI control register is an 8 bit register which is used to set the modes in which we SPI to operate.
I have added a snippet of the bit functions in the register for better understanding.
40 | Prepared By: U. U. Deshpande
SPSR REGISTER:
SPI status register is an 8 bit register which reveals the status of the SPI communication such as
completion of transmission/ reception, mode fault etc.
SPDR REGISTER:
This register holds the data for transmission and reception. Data can be transmitted by writing in
this register and data received can be read from this register.
SPCCR REGISTER:
This register controls the frequency of a master’s SCK. The value of this register must be an
even number and should be greater than or equal to 8. The SPI clock frequency is governed by
the formula
SPI rate = PCLK (Processor Clock rate) / SPCCR value
41 | Prepared By: U. U. Deshpande
STEPS TO PROGRAM SPI IN ARM CONTROLLERS:
MASTER MODE:
1. Select the functions of the pins MISO, MOSI, SCK using the PINSEL0 register.
2. Set the direction of the SSEL pin for selecting the slave connected to the controller.
3. Load the appropriate calculated value in the SPCCR register to generate the required clock
frequency.
4. Select the master mode and set the clock phase, polarity using the SPCR register.
5. Select the slave by pulling the SSEL pin low.
6. Write the data in the SPDR register for transmission.
7. Check the status of the transmission by reading the SPIF bit in the SPSR register.
SLAVE MODE:
1. Select the slave mode using the SPCR register.
2. Wait until the SPIF flag in the status register is set.
3. Read the data from the SPDR register in the slave controller.
CODE:
This code was built using Keil uVision 4 compiler. The code was built in such a way to transmit
data from a Master controller to the slave controller where the data is then sent to PORT 1.
#include<lpc21xx.h>
int main(void)
{
PINSEL0=(1<<8)|(1<<10)|(1<<12); //Selecting SPI pins
IODIR0=(1<<7);
IOSET0=(1<<7);
S0SPCCR=8; //SPI frequency
S0SPCR=0x38; //SPI master mode
IOCLR0=(1<<7);
while(1)
{
S0SPDR=0xff; //Data transmission
while(!(S0SPSR&(1<<7))); //Status check
S0SPDR=0x0f;
while(!(S0SPSR&(1<<7)));
}
}
NOTE:
Make changes in the above code as stated in the Programming steps of the Slave controller to
obtain the code for the slave device.
You can use any pin to select the slave by pulling it low.
Multiple slaves can be connected to a single master by assigning each slave select that is SSEL
pins from the master for the slaves.
42 | Prepared By: U. U. Deshpande
I2C in LPC2148 ARM7 Microcontroller
We will learn about how to program I2C in LPC2148 ARM7 Microcontroller. Also, we will
interface serial EEPROM 24LC512 to LPC2148 Microchip. We will test EEPROM by writing to
and reading from it. I2C communication protocol is most famous protocol in embedded systems.
What is I2C and how it works?
I2C bus has become one of the most important microcontroller subsystem used for interfacing
various IC devices with microcontroller. It is unique for its ability to maximize hardware
efficiency & circuit simplicity. The I2C bus uses only 2-bidirectional data lines for
communicating with the microcontroller. This bus is called Inter IC or I2C bus. All I2C-bus
compatible devices incorporate an on-chip interface which allows them to communicate directly
with each other via I2C-bus. I2C protocol specification can support up to 128 devices attached to
the same bus. Today many I2C IC devices available in the market such as Serial EEPROM, I/O
Expander, RTC, ADC, DAC, Sensors etc.
Typical I2C Master Slave Connection:
The I2C protocol uses master and slave method, the master which is in most cases a
microcontroller while the slave can be any I2C device such as Serial EEPROM, RTC etc. The
I2C protocol uses only two signals: clock and data. The Clock referred as SCL (Serial
Clock) while data is referred as SDA (Serial Data).
I2C
In I2C protocol we have to use special combinations of signal conditions. Fundamentally, there
are just two conditions START and STOP. A START condition is generated by master
followed by 7-bit of address, then a Read/Write (R/W) bit. If a slave device detects an
address match then it sends ACK by driving SDA low during the next clock cycle; if no
slave recognizes the address then the SDA line will left alone and pulled up high. Once
43 | Prepared By: U. U. Deshpande
ACK received, data will be either sent to the slave device or read from the slave device
(depending on the status of R/W bit).
Therefore, each byte is 9-bits in which 7-bits in which 7-bits for address and one R/W plus one
ACK/NAK, or 8-bit data plus one ACK/NAK. The last data byte of a transaction should
generally be followed by NAK, to indicate that it is intended to be the final byte. After this,
either a STOP or a ReSTART should be issued by the master. Bus errors are rarely introduced
when using a dedicated I2C peripheral on the master.
Features of I2C in LPC2148 ARM7 Microcontroller:
LPC2148 supports two fast I2C-buses (I2C0 & I2C1).
I2C bus interface that may be configured as Master, Slave or Master/Slave.
Supports programmable clock to allow adjustment of multiple data speed: standard (100 kbps),
fast (400 kbps) and high speed (3.4 Mbps).
Supports bi-directional data transfer between master and slave.
I2C protocol is useful where many devices connected on the bus. This helps to reduce the cost
and complexity of circuit as more devices allowed to communicate through same bus.
The I2C bus may be used for test and diagnostic purposes.
Application: Interfaces to external I2C standard parts such as serial EEPROM, Ram, and LCDs
etc.
Registers of I2C in LPC2148 ARM7 Microcontroller
Before we proceed any further and write C Program to interface EEPROM using I2C in
LPC2148 ARM7 Microcontroller. Let’s have a look at registers which we need to configure in
our code. The I2C peripheral interface is composed of seven registers. The functional details of
those registers are provided down below:
Register Name Description & Function
I2C0 Control Set Register: This register control the setting of bits in the I2CON register that
controls operation of the I2C interface. Writing a one to a bit of this register causes the
corresponding bit in the I2C Control Register to be set. Writing a zero has no effect.
I2C0CONSET contains the following control bits:
I2C0CONSET I2EN (Enable): is set to enable the I2C interface.
STA (Start): is set to enter master mode and send a START condition.
STO (Stop): sends STOP condition in master mode, and recover from an error in slave mode.
AA (Assert ACK): is set to request an acknowledge be returned from the slave device.
SI (Interrupt): is set to indicate a state change in the I2C Controller.
I2C0 Control Clear Register: This register control clearing of bits in the I2CON register the
controls operation of the I2C interface. Writing a one to a bit of this register causes the
corresponding bit in the I2C control register to be cleared. Writing zero has no effect.
I2C0CONCLR contains following control bits:
I2C0CONCLR
I2ENC: disables the I2C Controller.
STAC: clears START flag.
AAC: Clears the Assert ACK flag.
SIC: Clears the I2C interrupt flag.
I2C0 Status Register: During I2C operation this register provides detailed status codes that
I2C0STAT
allow software to determine the next action needed.
I2C0DAT I2C0 Data Register: During master or slave transmit mode, data to be transmitted is written to
44 | Prepared By: U. U. Deshpande
this register. During master or slave receive mode, data that has been received may be read
from this register.
I2C0 Slave Address Register: This register is readable & writable, and is only used when I2C
interface is set to slave mode. In master mode, this register has no effect. I2C0ADR contains
I2C0ADR
the 7-bit slave address for operation of the I2C interface in slave mode. The least significant bit
(LSB) determine whether a slave respond to the general call address.
I2C0 SCH Duty Cycle Register High Half Word: This register determines the high time of
I2C0SCLH
the I2C Clock (contains the SCL high duty cycle count)
I2C0 SCL Duty Cycle Register High Half Word: This register determines the low time of
the I2C Clock. (Contains the SCL low duty cycle count). I2C0SCLL and I2C0SCLH together
I2C0SCLL
determine the clock frequency generated by an I2C master and certain times used in slave
mode.
Example Project: Let’s interface serial EEPROM 24LC512 using I2C in LPC2148 ARM7
Microcontroller. The interfacing I2C-EEPROM with LPC2148 is very simple and straight
forward. Here we will perform read, write and erase operations on EEPROM by using I2C and
the value will be displayed on serial port using UART0. A delay is occurring in every single data
read from EEPROM. The delay depends on compiler how it optimizes the loop as soon as you
make changes in options the delay changes.
Circuit Setup: I2C in LPC2148 ARM7 Microcontroller
I2C in LPC2148 ARM7 Microcontroller
24LC512 EEPROM Connection to LPC2148
45 | Prepared By: U. U. Deshpande
The principal we learn on this I2C serial EEPROM device can be applied to other I2C
devices as well, the differences is only on the terms used; on the serial EEPROM we use memory
address for storing and retrieving the data, while on the other I2C devices such as Microchip
MCP23008 8-bit I/O expander or Dallas DS1307 Real Time Clock we use register address for
writing and reading the data.
That’s all you really need to know in order to use external I²C EEPROM chip. I hope this
post will help you get program I2C in LPC2148 ARM7 Microcontroller to read, write and erase
data of EEPROM. In our future posts, we will explore SPI Protocol of LPC2148 ARM7
Microcontroller.
46 | Prepared By: U. U. Deshpande