Вы находитесь на странице: 1из 32

Unit 3:

LPC2148 Serial Port


Programming
Prof: K S Khandelwal
Sinhgad College of Engineering, Pune
Email: kunalkhandelwal13@gmail.com
UART0 and UART1 features:
 Two UARTs

 UART0 is Null modem (Rx & Tx pin only ) where as UART1 is modem
capable.

 16 byte FIFO message buffer for Receive and Transmit

 Receiver FIFO trigger points at 1, 4, 8, and 14 bytes.

 Register locations conform to ‘550 industry standard.

 Built-in fractional baud rate generator with auto-bauding capabilities.

 Mechanism that enables software and hardware flow control implementation.

Pins: TxD RxD Both the UART modules are identical, except the
UART1 block has an additional full modem interface.
UART0 P0.0 P0.1 This includes all the pins for RS232 compatibility like
UART1 P0.8 P0.9 flow control pins (CTS, RTS) etc.
Pins associated with UART0 & UART1
Pins associated with UART1
Pins associated with UART0
Registers used in UART
Data Related 1. U0RBR: Receiver Buffer Register (READ ONLY) -> Stores Received Data
Registers 2. U0THR:Transmit Holding Register (WRITE ONLY) -> Data in this will be
transmitted
Control and Status 1. U0FCR: FIFO Control Register -> Rx and Tx FIFO Controller
Registers 2. U0LCR: Line Control Register -> Selects bits for word
length, stop, parity and DLAB
3. U0LSR: Line Status Register -> Show Tx & Rx status
4. U0TER: Transmit Enable Register -> Enable Data Transmission

Interrupt Related 1. U0IER: Interrupt Enable Register -> RBR & THRE interrupt enabler
Registers 2. U0IIR: Interrupt Identification Register -> Interrupts can be identified

Baud Rate Set-up 1. U0DLL & U0DLM: Divisor Latch registers -> used to set baud rate
related Registers 2. U0FDR: Fractional Divisor Register -> baud rate fractional
divider
3. U0ACR: Auto-baud Control Register -> Auto baud rate controller
Other Registers 1. U0SCR: Scratch Pad Reg.
Registers used for UART Programming in LPC214x
Data Related Registers :
1. U0RBR – Receiver Buffer Register (READ ONLY!):
• This register contains the top most byte(8-bit data chunk) in the Rx
FIFO i.e the oldest received data in FIFO.
• To properly read data from U0RBR , the DLAB(Divisor Latch Access) bit
in U0LCR register must be first set to 0.
• Also , as per the user manual “The right approach for fetching the valid
pair of received byte and its status bits is first to read the content of
the U0LSR register, and then to read a byte from the U0RBR.”
• (Note : If you are using 7,6 or 5 Bits for data then other remaining bits
are automatically padded with 0s)

2. U0THR – Transmit Holding Register (WRITE ONLY!):


• U0THR contains the top most byte in Tx FIFO and in this case its the
newest(latest) transmitted data.
• As in the case with U0RBR , we must set DLAB=0 to access U0THR for
write operation.
Control and Status Registers :
1) U0FCR – FIFO Control Register : Used to control Rx/Tx FIFO operations.

7 6 5 4 3 2 1 Bit 0
RX Trigger Level R R R TX FIFO RX FIFO FIFO
Reset Reset Enable

Bit 0: FIFO Enable : 1 Enable both Rx and Tx FIFOs and 0 to disable.

Bit 1 – Rx FIFO Reset : Writing a 1 will clear and reset Rx FIFO.

Bit 2 – Tx FIFO Reset : Writing a 1 will clear and reset Tx FIFO.

Bits [7 to 6] : Used to determine that how many UART0 Rx FIFO


characters must be written before an interrupt is activated.
[00] (i.e trigger level 0) for 1 character.
[01] (i.e trigger level 1) for 4 characters.
[10] (i.e trigger level 2) for 8 characters.
[11] (i.e trigger level 3) for 14 characters.
2) ULCR0/1 – Line Control Register : 7 6 5 4 3 2 1 0
Divisor Latch Break Parity Parity Stop bit Word length
Used to configure the UART block (i.e the Access Bit Control Select Enable select select
data format used in transmission).
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
7 6 5 4 3 2 1 0
3) U0LSR – Line Status Register :
RXFE TEMT THRE BI FE PE OE RDR
used to read the status of Rx and Tx blocks.

Bit Symbol Value Description


0 U0RBR is empty
0 Receiver Data Ready
1 U0RBR contains valid data
0 Overrun error status is inactive
1 Overrun Error
1 Overrun error status is active
0 Parity error status is inactive
2 Parity Error
1 Parity error status is active
0 Framing error status is inactive
3 Framing Error
1 Framing error status is active
0 Break interrupt status is inactive
4 Break Interrupt
1 Break interrupt status is active
0 U0THR contains valid data
5 Transmitter Holding Register Empty
1 U0THR is empty
0 U0THR and/or the U0TSR contains valid data
6 Transmitter Empty
1 U0THR and the U0TSR are empty
0 U0RBR contains no UART0 RX errors
7 Error in RX FIFO
1 At least one UART0 RX error in U0RBR
4) U0TER – Transmit Enable Register :
This register is used to enable UART transmission.

 When bit-7 (i.e TXEN) is set to 1 Tx block will be


enabled and will keep on transmitting data as soon
as its ready.

 If bit-7 is set to 0 then Tx will stop transmission.


Other bits are reserved.
Interrupt Related Registers :

1) U0IER – Interrupt Enable Register:


 It is used to enable or disable the interrupts corresponding
to UART
Set a bit to 0 to disable and 1 to enable the corresponding
interrupt.
Bit 0 – RBR Interrupt Enable
Bit 1 – THRE Interrupt Enable
Bit 2 – RX Line Status Interrupt Enable
Bit 3 – ATBOInt Enable
Bit 4 – ATEOInt Enable
Where ATBOInt = Auto Baud Time-Out Interrupt ,
ATEO = End of Auto Baud Interrupt and
rest of the bits are reserved.
2) U0IIR – Interrupt Identification Register:
This register is organized as follows:
Bit 0 – Interrupt Pending :
 0 means atleast one interrupt is pending ,
 1 means no interrupts are pending.
 Note: This bit is ACTIVE LOW!
Bits [3 to 1] – Interrupt Identification :
 [011] is for Receive Line Status(RLS) ,
 [010] means Receive Data Available(RDA) ,
 110 is for Character Time-out Indicator(CTI) ,
 [001] is for THRE Interrupt.
Bits [7 to 6] – FIFO Enable.
Bit 8 – ABEOInt :
 1 means Auto Baud Interrupt has successfully ended and
 0 otherwise.
Bit 9 – ABTOInt : 1 means Auto Baud Interrupt has Timed-out.
All others bits are reserved.
Baud Rate Setup related registers :
1) U0DLL and U0DLM – Divisor Latch registers:
 Both of them hold 8-bit values.
 These register together form a 16-bit divisor value which is
used in baud rate generation.
 U0DLM holds the upper 8-bits and U0DLL holds the lower 8-
bits and the formation is “[U0DLM:U0DLL]“.
 Since these form a divisor value and division by zero is
invalid, the starting value for U0DLL is 0x01 (and not 0x00)
i.e the starting value in combined formation is “[0x00:0x01]”
i.e 0x0001.
 In order to access and use these registers properly,
DLAB bit in U0LCR must be first set to 1.
Baud Rate Setup related registers :
2) U0FDR – Fractional Divider Register :
 This register is used to set the prescale value for baud rate generation.
 The input clock is the peripheral clock and output is the desired clock
defined by this register
31:8 MULVAL DIVADDVAL

Reserved 7 6 5 4 3 2 1 0

This register actually holds divisor and a multiplier values for prescaling which are:

Bit [3 to 0] – DIVADDVAL : This is Bit [7 to 4] – MULVAL : This is prescale


the prescale divisor value. multiplier value.
. If this value is 0 then fractional baud Even if fractional baud rate generator is
rate generator wont have any effect not used the value in this register must be
on Uart Baud rate. more than or equal to 1 else UART0 will
not operate properly.

Remark from User manual : “If the fractional divider is active (DIVADDVAL > 0) and
DLM = 0, the value of the DLL register must be 2 or greater!”
UART Baud Rate Generation:
Note :
 In real world there are very less chances that you will
get the actual baudrate same as the desired baudrate.
 In most cases the actual baudrate will drift a little above
or below the desired baud and also, as the desired
baudrate increases this drift or error will also increase –
this is because of the equation itself and the
 limitations on MULVAL , DIVADDVAL! For e.g. if the
desired baud rate is 9600 and you get a baud like 9590 ,
9610 , 9685 , 9615 , etc.. then in almost all cases it will
work as required.
 In short , a small amount of error in actual baudrate is
generally tolerable in most systems.
Calculating Baud Rate in LPC 2148: UART0
The formula for calculating
baud rate is given as :

which can be further


simplified to :

with following conditions strictly applied :

1. 0 < MULVAL <= 15 , Where PCLK is the Peripheral Clock value in Hz ,


2. 0 <= DIVADDVAL <= 15, U0DLM and U0DLL are the divisor registers and
if DIVADDVAL > 0 & DLM = 0 finally DIVADDVAL and MULVAL are part of the
then, DLL >= 2 Fractional baudrate generator register.

As it can been seen this formula has 2 prominent parts which are : A Base value and
a Fractional Multiplier i.e:
BaudRate = [ Base ] x [ Fraction(i.e. Prescale) ]

This Fractional Multiplier can be used to scale down or keep the base value as it is ..
hence its very useful for fine-tuning and getting the baudrate as accurate as possible.
Examples for calculating Baud Rates
1. We start with DLM=0 , DIVADDVAL=0 and MULVAL=1 and
get an initial value for DLL.
2. We will get a very close baudrate to the desired one. (if we
are lucky)
3. If not then we perform some finetuning using DLM ,
MULVAL and DIVADDVAL and get a new value for DLM

Ex 1 : PCLK = 30Mhz and Required Baudrate is 9600 bauds for UART0

1. Lets start with U0DLM = 0 , DIVADDVAL = 0 and MULVAL = 1


2. We have PCLK = 30 Mhz = 30 x 106 Hz

UART0 Baud rate =

3. Substituting values for U0DLM = 0 , DIVADDVAL = 0 and MULVAL = 1

UART0 Baud rate = =


;

U0DLL = = 195.3125
We get U0DLL = 195.3125 , since it must be an integer we use 195.

Let us calculate BaudRate Error as = Actual BaudRate – Desired BaudRate.

With U0DLL = 195 our actual Now all we have to do is to get this
baud rate will be = 9615.38 with error as low as possible.
an error of +15.38 from 9600.

First lets compute the required This can be done by multiplying it


fraction given as: by a suitable fraction defined using
[Desired Baud / Actual Baud MULVAL and DIVADDVAL – as
Rate]. = 9600/ 9615.38 = 0.9984. given in equation.
Now What?
The closest downscale value
In short this is the value i.e possible(<1) to 0.9948 is 0.9375
0.9984 that needs to be multiplied when MULVAL=15 &
by baud value we got above to DIVADDVAL=1.
bring back it to ~9600. But 0.9375 is too less because
9615.38x0.9375 = 9014.42
This the value which is way too far.
we use

Luckily when U0DLL = 183 we get a Now , one thing can be done is
baud rate of 9605.53 i.e ~9605! that we set MULVAL = 15 and now
Yea! start decreasing U0DLL from 195
For PCLK = 30Mhz and Required
Baudrate is 9600 bauds for UART0

Hence the final settings in this case will be : PCLK = 30 x 106 Hz

U0DLL = 183

U0DLM = 0

MULVAL = 15

DIVADDVAL = 1
Examples for calculating Baud Rates
Ex 2 : PCLK = 60Mhz and Required Baudrate is 9600 bauds for UART0

1. Lets start with U0DLM = 0 , DIVADDVAL = 0 and MULVAL = 1


2. We have PCLK = 60 Mhz = 60 x 106 Hz

UART0 Baud rate =

3. Substituting vales for U0DLM = 0 , DIVADDVAL = 0 and MULVAL = 1

UART0 Baud rate = = ; Now What?

U0DLL = = 390.625 out of range since U0DLL is 8-bit!

Initially we made U0DLM ‘0’, Now set U0DLM = 1 to get U0DLL in range

9600 = ; U0DLL = 135


We get U0DLL = 134.625 , since it must be an integer we use 135.

Let us calculate BaudRate Error as = Actual BaudRate – Desired BaudRate.

With U0DLL = 135 our actual Now all we have to do is to get this
baud rate will be = 9590.79 with error as low as possible.
an error of -9.21 from 9600.

First lets compute the required Let us say this can be done by
fraction given as: multiplying it by a suitable fraction
[Desired Baud / Actual Baud defined using MULVAL and
Rate]. = 9600/ 9590.79 = 1.0009 DIVADDVAL – as given in equation.

Now What?
The fractional value we need to
multiply our current baud to get Hence, in such case we have to use
back to ~9600 is 1.0009 but that’s MULVAL = 15 and find new value
out of range(>1) for a factor for U0DLL..
This the value
we use

Here we get U0DLL = 110 which Now , one thing can be done is
gives a baud of 9605.53 which is that we set MULVAL = 15 and now
~9605! start decreasing U0DLL from 110
For PCLK = 60Mhz and Required
Baudrate is 9600 bauds for UART0

Hence the final settings in this case will be : PCLK = 60 x 106 Hz

U0DLL = 110

U0DLM = 1

MULVAL = 15

DIVADDVAL = 1
Program: type on keyboard & display on serial terminal

 In this example you will see the characters that you type on your
keyboard - seems like typing in an editor? NO!.
 The serial Terminal only displays the character that it receives via
serial Port.
 When you type a character it is directly sent to the other side via
serial port.
 So , in order for us to see the character which we typed, we need to
send back the same character i.e. echo it back to PC.
 This is what the program does.
 As soon as the MCU receives a character from the Rx pin .. it then
sends the same character back to PC via the Tx Pin and it gets
displayed in the Serial Terminal.
UART0: Read & Write Function
U0Read() - Read Data from UART0:

#define RDR (1<<0) // Receiver Data Ready


char U0Read(void)
{ while( !(U0LSR & RDR ) ); // wait till any data arrives into Rx FIFO
return U0RBR;
}

U0Write() - Write Data to UART0:

#define THRE (1<<5) // Transmit Holding Register Empty


void U0Write(char data)
{
while ( !(U0LSR & THRE ) ); // wait till the THR is empty
// now we can write to the Tx FIFO
U0THR = data;
}
Program1 :type on keyboard & display on
serial terminal
#include <lpc214x.h>

#define PLOCK 0x00000400 // for PLL


#define THRE (1<<5) // Transmit Holding Register Empty
#define RDR (1<<0) // Receiver Data Ready
#define MULVAL 15
#define DIVADDVAL 1
#define NEW_LINE 0xA // Character for new line .. analogus to '\n'
#define ENTER 0xD // Ascii code for Enter

void initUART0(void);
void U0Write(char data);
char U0Read(void);

void initClocks(void);
void setupPLL0(void);
void feedSeq(void);
void connectPLL0(void);
Program:type on keyboard & display on serial terminal
void initUART0(void)
{
PINSEL0 = 0x5; /* Select TxD for P0.0 and RxD for P0.1 */
U0LCR = 3 | (1<<7) ; /* 8 bits, no Parity, 1 Stop bit | DLAB set to 1 */
U0DLL = 110;
U0DLM = 1;
U0FDR = (MULVAL<<4) | DIVADDVAL; /* MULVAL=15(bits - 7:4) , DIVADDVAL=0(bits - 3:0) */
U0LCR &= 0x0F; //Set DLAB=0 to lock MULVAL and DIVADDVAL
//BaudRate is now ~9600 and we are ready for UART communication!
}
void U0Write(char data)
{
// wait till the THR is empty
while ( !(U0LSR & THRE ) );
// now we can write to the Tx FIFO
U0THR = data;
}
char U0Read(void)
{
while( !(U0LSR & RDR ) ); // wait till any data arrives into Rx FIFO
return U0RBR;
}
Configuring PLL and Clock Initalization

//Note :12Mhz Xtal is connected to LPC2148. void initClocks(void)


void setupPLL0(void)
{
{ // PPLE=1 & PPLC=0 so it will be enabled
PLL0CON = 0x01; setupPLL0();
// set the multipler to 5 (i.e actually 4)
// i.e 12x5 = 60 Mhz (M - 1 = 4)!!! feedSeq();
// Set P=2 since we want FCCO in range!!! connectPLL0();
PLL0CFG = 0x24;
feedSeq();
}
void feedSeq(void) // PCLK is same as CCLK i.e 60Mhz
{ VPBDIV = 0x01;
PLL0FEED = 0xAA;
PLL0FEED = 0x55; }
}
void connectPLL0(void)
{ // check whether PLL has locked on to the desired freq
by reading the lock bit in the PPL0STAT register
while( !( PLL0STAT & PLOCK ));
PLL0CON = 0x03; // now enable(again) and connect
}
Program:type on keyboard & display on
serial terminal
int main(void)
{
initClocks(); // Set CCLK=60Mhz and PCLK=60Mhz
initUART0();

while(1)
{
char c = U0Read(); // Read Data from Rx
if( c == ENTER ) // Check if user pressed Enter key
{
U0Write(NEW_LINE); // Send New Line ASCII code change line
}
else
{
U0Write(c); // Write it to Tx to send it back
}
}

return 0;
}
Program 2: Configuring and Initializing UART
 We will use the following configuration for UART0:
•BaudRate = 9600 buads (with PCLK=15Mhz)
• Data Length = 8 bits
• No Parity Bit
• and 1 Stop Bit
 In order to get bauds at 15Mhz PCLK we must use the
following settings for baud generation :

U0DLL = 97 ; U0DLM = 1 ; MULVAL = 0 ;


DIVADDVAL=0
(You can convert these values to Hex =or= direclty
use it in decimal form)
Now , lets make a simple program to configure and initialize UART0

/* Select TxD for P0.0 and RxD for P0.1 */


// This is done by placing ‘01’ at bit positions
1:0 & 3:2 resp. in Pinsel0 register

RxD TxD

PINSEL0 =x05
/* 8 bits, no Parity, 1 Stop bit, DLAB set to 1 */
//We now use Line Control Register (U0LCR) to configure the
UART block (i.e the data format used in transmission)

U0LCR = 3 | (1<<7) ; OR U0LCR = 0x83;

//Setting U0LCR Reg

/* 9600 Baud Rate @ 15MHz VPB Clock*/


U0DLL = 97;
// Use DLL register to set

U0LCR &= 0x03; // Set DLAB=0 to lock MULVAL and DIVADDVAL

//BaudRate is now ~9600 and we are ready for UART communication!


#include <stdio.h> /* prototype declarations for I/O functions */
#include <LPC21xx.H> /* LPC21xx definitions */
char msg[]={"\n\r Code for UART0"};
int main (void)
{
/* execution starts here*/

long int n;

PINSEL0 = 0x00000005; //set line ctrl reg. for UART0 with above parameters
U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
U0DLL = 97; /* 9600 Baud Rate @ 15MHz VPB Clock*/

U0LCR = 0x03; /* DLAB = 0 */


while(1)
{
n=0;
while(msg[n]!='\0') //chk end of msg
{
U0THR = msg[n++];
while(!(U0LSR&0x40));
}
}
}

Вам также может понравиться