Uart uses TxD(Transmit) Pin for sending Data and RxD(Receive) Pin to get data. UART sends & receives data in form of chunks or packets.
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.
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 which we will see in later section. 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. Please keep this in mind while doing baud-rate calculations. In order to access and use these registers properly, DLAB bit in U0LCR must be first set to 1.
2) U0FDR – Fractional Divider Register : This register is used to set the prescale Interfacing of LPC2148 with UART1 and GSM Modulevalue for baud rate generation. The input clock is the peripheral clock and output is the desired clock defined by this register. This register actually holds to different 4-bit values (a divisor and a multiplier) for prescaling which are:
- Bit [3 to 0] – DIVADDVAL : This is the prescale divisor value. If this value if 0 then fractional baud rate generator wont have any effect on Uart Baud rate.
- Bit [7 to 4] – MULVAL : This is prescale multiplier value. Even if fractional baud rate generator is not used the value in this register must be more than or equal to 1 else UART0 will not operate properly.
- Other Bits reserved.
Remark from Usermanual : “If the fractional divider is active (DIVADDVAL > 0) and DLM = 0, the value of the DLL register must be 2 or greater!”
Control and Status Registers :
1) U0FCR – FIFO Control Register : Used to control Rx/Tx FIFO operations.
- Bit 0 – FIFO Enable : 1 to 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. - Others bits are reserved.
2) U0LCR – Line Control Register : Used to configure the UART block (i.e the data format used in transmission).
- Bit [1 to 0] – Word Length Select : Used to select the length of an individual data chunk. [00] for 5 bit character length. Similarly [01] , [10] , [11] for 6 , 7 , 8 bit character lengths respectively.
- Bit 2 – Stop bit select : 0 for using 1 stop bit and 1 for using 2 stop bits.
- Bit 3 – Parity Enable : 0 to disabled Partiy generation & checking and 1 to enable it.
- Bit [5 to 4] – Parity Select : [00] to Odd-parity , [01] for Even-parity , [10] for forced “1”(Mark) parity and [11] for forced “0”(Space) parity.
- Bit 6 – Break Control : 0 to disable break transmission and 1 to enable it. TxD pin will be forced to logic 0 when this bit is 1!
- Bit 7 – Divisior Latch Access bit : 0 to disable access to divisor latches and 1 to enable access.
3) U0LSR – Line Status Register : used to read the status of Rx and Tx blocks.
- Bit 0 – Receiver Data Ready(RDR) : 0 means U0RBR is empty(i.e Rx FIFO is empty) and 1 means U0RBR contains valid data.
- Bit 1 – Overrun Error(OE) : 0 means Overrun hasn’t occured and 1 means Overrun has occured. Overrun is the condition when RSR(Receive Shift Register)[See note 1] has new character assembled but the RBR FIFO is full and the new assembled character is eventually lost since no data is written into FIFO if its full. (Note: Reading U0LSR clears this bit)
- Bit 2 – Parity Error(PE) : 0 mean no parity error and 1 mean a parity error has occured. When the value of the parity bit in the recieved character is in wrong state then a parity error occurs. (Note: Reading U0LSR clears this bit)
- Bit 3 – Framing Error(FE) : 0 means no framing error has occured and 1 means that a framing error has taken place. Framing error occurs when the stop bit of a received character is zero. (Note: Reading U0LSR clears this bit)
- Bit 4 – Break Interrupt : 0 means no Break Interrupt occures and 1 means that it has occured. A Break Interrupt occurs when the RxD line is pulled low (i.e all 0s) i.e held in spacing state for 1 full character after which Rx Block goes into Idle state. Rx Block gets back to active state when RxD pin is pulled high (i.e all 1s) i.e held in marking state for 1 full character. (Note: Reading U0LSR clears this bit)
- Bit 5 – Transmit Holding Register Empty(THRE) : 0 means U0THR contains valid data and 1 means its empty.
- Bit 6 – Transmitter Empty (TEMT) : 0 means U0THR and/or U0RSR contains valid data and 1 means that both U0THR and U0RSR are empty.
- Bit 7 – Error in RX FIFO(RXFE) : 0 means that U0RBR has no Rx Errors or Rx FIFO is disabled(i.e 0th bit in U0FCR is 0) and 1 means that U0RBR has atleast one error. (Note: This bit is cleared only if U0LSR is read and there are no other subsequent errors in Rx FIFO .. else this bit will stay 1)
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: 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: Refer User Manual when in doubt. In some application the usage of this register might get a bit complicated.
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
CODE FOR PROJECT :
main.c –
#include<lpc214x.h> #include "header.h" #include "lcd.h" #include "uart.h" #include "pll.h" char keypad1[11],x; void io_init() { PINSEL0=0x05; PINSEL1=0x00; PINSEL2=0x00; IO0DIR|=0xff<<16; IO1DIR=0x3c<<16; } void dialpad() { IO1CLR=(1<<row1); IO1SET=(1<<row2) | (1<<row3) | (1<<row4); delay(100); if(!(IO1PIN & (1<<col1))) { lcddata('1'); keypad1[x]='1'; x++; delay(100); } else if(!(IO1PIN & (1<<col2))) { lcddata('2'); keypad1[x]='2'; x++; delay(100); } else if(!(IO1PIN & (1<<col3))) { lcddata('3'); keypad1[x]='3'; x++; } else if(!(IO1PIN & (1<<col4))) { lcddata('4'); keypad1[x]='4'; x++; delay(100); } IO1CLR=(1<<row2); IO1SET=(1<<row1) | (1<<row3) | (1<<row4);; delay(2); if(!(IO1PIN & (1<<col1))) { lcddata('5'); keypad1[x]='5'; x++; delay(100); } else if(!(IO1PIN & (1<<col2))) { lcddata('6'); keypad1[x]='6'; x++; delay(100); } else if(!(IO1PIN & (1<<col3))) { lcddata('7'); keypad1[x]='7'; x++; delay(100); } else if(!(IO1PIN & (1<<col4))) { lcddata('8'); keypad1[x]='8'; x++; delay(100); } IO1CLR=(1<<row3); IO1SET=(1<<row1) | (1<<row2) | (1<<row4); delay(5); if(!(IO1PIN & (1<<col1))) { lcddata('9'); keypad1[x]='9'; x++; delay(100); } else if(!(IO1PIN & (1<<col2))) { lcddata('0'); keypad1[x]='0'; x++; delay(100); } else if(!(IO1PIN & (1<<col3))) { lcdcmd(0x01); lcdstring("Sending Message"); sendsms(); } else if(!(IO1PIN & (1<<col4))) { lcdcmd(0x01); lcdstring("Calling to...."); dial(); } IO1CLR=(1<<row4); IO1SET=(1<<row1) | (1<<row2) | (1<<row3); delay(100); if(!(IO1PIN & (1<<col1))) { lcddata('*'); keypad1[x]='*'; x++; delay(100); } else if(!(IO1PIN & (1<<col2))) { lcddata('#'); keypad1[x]='#'; x++; delay(100); } else if(!(IO1PIN & (1<<col3))) { lcdcmd(0x01); lcdstring("Read Message"); readsms(); } else if(!(IO1PIN & (1<<col4))) { lcdcmd(0x01); lcdstring("Receive Call..."); recieve(); } } void readmsgstring(char *str) { int i; while(str[i]) { while(str[i]!='5') i++; if(str[i]=='5') break; } i++; } void recieve() { txstring("AT\r"); rxdata(); txstring("ATA"); rxdata(); } void dial() { txstring("AT\r"); rxdata(); txdata('\r'); delay(10); txstring("ATD"); txstring(keypad1); txdata(0x3b); //for ; lcdstring("Calling to..."); lcdcmd(0xc0); lcdstring(keypad1); rxdata(); delay(1); } void readsms() { char result; txstring("AT\r"); rxdata(); txdata('\r'); delay(10); txstring("AT+CMGF=1"); rxdata(); txdata('\r'); delay(10); txstring("AT+CMGD=4"); rxdata(); txdata('\r'); delay(10); //sreadmsgstring(U0RBR); txstring("AT+CMGR=1"); rxdata1(); } void sendsms() { txstring("AT\r"); rxdata(); txdata('\r'); delay(10); txstring("AT+IPR=9600\r"); rxdata(); txdata('\r'); delay(10); txstring("AT+CMGF=1\r"); rxdata(); txdata('\r'); delay(10); lcdcmd(0x01); lcdstring(keypad1); txstring("AT+CMGS="); txdata(0x22); //txdata(keypad1[x]); txstring(keypad1); txdata(0x22); txdata(0x0d); txstring("Hello......"); txdata(0x1A); } int main() { io_init(); clk_init(); lcdinit(); uart_init(); while(1) { lcdcmd(0x01); lcdstring("Enter Number:"); lcdcmd(0xc0); x=0; while(x<11) { dialpad(); delay(50); } keypad1[x]='\0'; } }
header.h –
#include<lpc214x.h> #include<string.h> #define PLOCK 10 #define THRE 5 #define RDR 0 #define lcdport IO0SET #define lcdportclr IO0CLR #define rs 16 #define en 18 #define row1 18 #define row2 19 #define row3 20 #define row4 21 #define col1 22 #define col2 23 #define col3 24 #define col4 25 void delay(int); void cmd(); void lcdcmd(char); void disp(); void lcddata(char); void lcdinit(); void lcdstring(char *); void dial(); void readsms(); void sendsms(); void recieve();
lcd.h –
#include "header.h" void delay(int time) { int i ,j; for(i=0;i<time;i++) for(j=0;j<7500;j++); } void cmd() { lcdportclr=(1<<rs); //lcdportclr=(1<<rw); lcdport=(1<<en); delay(1); lcdportclr=(1<<en); } void lcdcmd(char ch) { lcdport = (ch>>4 & 0x0f)<<19; cmd(); lcdportclr=(ch>>4 & 0x0f)<<19; lcdport= (ch & 0x0f)<<19; cmd(); lcdportclr= (ch & 0x0f)<<19; } void disp() { lcdport=(1<<rs); //lcdportclr=(1<<rw); lcdport=(1<<en); delay(1); lcdportclr=(1<<en); } void lcddata(char ch) { lcdport = (ch>>4 & 0x0f)<<19; disp(); lcdportclr=(ch>>4 & 0x0f)<<19; lcdport= (ch & 0x0f)<<19; disp(); lcdportclr= (ch & 0x0f)<<19; } void lcdinit() { lcdcmd(0x02); lcdcmd(0x28); lcdcmd(0x0e); } void lcdstring(char *str) { while(*str!='\0') { lcddata(*str); str++; } }
uart.h –
#include "header.h" void uart_init() { PINSEL0|=0x050000; U1LCR=0x83; U1DLL=0x61; U1DLM=0x00; U1LCR=0x03; } void txdata(char ch) { U1THR=ch; while(!(U1LSR & (1<<THRE))); } void txstring(char *str) { while(*str) { txdata(*str); str++; } } void rxdata() { char str[3],i; for(i=0;i<2;i++) { while(!(U1LSR & (1<<RDR))); str[i]=U1RBR; U1FCR=0x07; } str[i]='\0'; lcdcmd(0x01); lcdstring(str); delay(10); if(strcmp("OK",str)==0) { return; } } void rxdata1() { char str1[20],j; for(j=0;j<12;j++) { while(!(U1LSR & (1<<RDR))); str1[j]=U1RBR; } str1[j]='\0'; lcdcmd(0x01); lcdstring(str1); delay(10); while(str1[j]) { while(str1[j]!='5') j++; if(str1[j]=='5') break; } j++; lcddata(j); }
pll.h –
void clk_init() { PLL0CON=0x01; PLL0CFG=0x24; PLL0FEED=0xAA; PLL0FEED=0x55; while(!(PLL0STAT & (1<<PLOCK))); PLL0CON=0x03; PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x00; }