Monday, February 25, 2019

8051 C programs

Interfacings

Interrupt Structure

  • ARM7 Processor hardware interrupt inputs: 2, (FIQ. IRQ)
  • LPC2148 external interrupt inputs: 4 (available on 9 pins)
  • Processor and on-chip user peripherals generate interrupts
  • LPC2148 uses ARM PrimeCell (PL190) Vectored Interrupt Controller for managing interrupts.
  • PL190 is interfaced to ARM core through the fast AHB bus
When interrupt occurs:
  1. VIC identifies the source of interrupts
  2. Passes requests on interrupt request pins as per the configuration
  3. If more than one interrupt occurs at a time, VIC resolves priority

Vectored Interrupt Controller (VIC)

  • 32 interrupt request inputs, LPC2148 uses 22 of 32 interrupts
  • Categorizes into Fast Interrupt Request, Vectored IRQ, Non Vectored IRQ interrupts
  • Any of the 22 interrupts can be assigned to FIQ / VIRQ / NVIRQ
  • FIQ: Generally, only one interrupt is assigned, VIC provides ISR address. If more than one is assigned to FIQ, VIC combines all, generates VICFIQ, provides only one ISR address for all FIQ (Non-Vectored FIQ) .
  • VIRQ & NVIRQ
  • VIC has 16 VIRQ slots, Slot-0 to Slot-15. Any IRQ configured interrupts can be assigned to any slot. Priorities are in the order of slot number.
  • Interrupts configured as IRQ, not assigned any VIRQ slot, is assigned as NVIRQ
  • VIRQ & NVIRQ interrupts are combined and VICIRQ is generated
  • Programs can handle 1 FIQ, 16 VIRQ, 1 NVIRQ (total 18) interrupts
VIC.png

VIC Registers (only important listed)

  1. VICIntSelect: High, Low bits select interrupts as FIQ, IRQ respectively
  2. VICIntEnable: High bit enables FIQ or IRQ classified interrupts
  3. VICIntEnClr: High bit disables FIQ or IRQ classified, enabled interrupts
  4. VICSoftInt: Generates any interrupt by software. High bit generates corresponding interrupt
  5. VICSoftIntClr: Clears a bit in Software Interrupt register
  6. VICIRQStatus: A high bit indicates corresponding IRQ classified, enabled IRQ interrupt is active
  7. VICFIQStatus: A high bit indicates corresponding FIQ classified, enabled IRQ interrupt is active
  8. VICVectAddr: Holds ISR addr of active interrupt. Writing any value indicates End of Interrupt
  9. VICVectAddr0 – VICVectAddr15: Hold ISR addresses for slots 0 to 15
  10. VICVectCntl0 – VICVectCntl15: Control 16 IRQ slots, assigns sources to each slot. Bit [4:0] selects VIC channel, bit [5] select VIRQ / NVIRQ, high / low bit provides dedicated / default ISR addr.

Programming VIC registers

  • VICIntSelect: Set / reset the bits for FIQ / IRQ classification
  • VICVectCtrlx: Assign VIRQ slot ‘x’ to IRQ classified interrupt
  • VICVectAddrx: Write ISR addr of VIRQ interrupt assigned to slot ‘x’
  • VICIntEnable: Enable interrupts 

Programming VIC registers: Examples

1) Programming VICIntSelect register
VICIntSelect = 0x0000 0010; // enable VIC Timer-0 channel as VFIQ interrupt  (by default all interrupts are VIRQ enabled) //
2) Programming VICVectCntlx register 
VICVectCntl0=(0x01<<5)|0x04; // assign VIRQ Slot-0 to Timer-0, enable Slot-0  (bit[4:0] is channel no. bit[5] enables slot) //
3) Programming VICVectAddrx register
void Timer0ISR(void) __irq;      // declare prototype for ISR//unsigned long int T0vectaddr;    // declare variable to hold Timer-0 ISR address//T0vectaddr=(unsigned)Timer0ISR; // place ISR address in variable//VICVectAddr0 = T0vectaddr;      // write ISR address into Slot-0 VectAddr reg//
4) Programming VICIntEnable register
VICIntEnable = 0x00000010;    // enable Timer-0 interrupt//

Handling FIQ interrupts

  • Branch instruction at 0x0000001C uses address of FIQ handler directly and goes to FIQ routine. This reduces interrupt latency. 
  • If more than one interrupt are assigned as FIQ, the handler routine identifies the source of interrupt. This increases interrupt latency. 
  • Executes codes respective of identified interrupts. 
  • Clears flags set by peripherals in their interrupt registers o End of interrupt.

Handling IRQ interrupts

  • On interrupt, processor executes branch instruction from interrupt vector table at 0x 00000018 and branches to IRQ handler routine 
  • Reads VICVectAddr reg that holds address of highest priority pending VIRQ Slot-x interrupt. If no slot is assigned, it holds address of default vect address 
  • Branches to handler routine. 
  • Reads interrupt register of the peripheral, identifies actual source, executes codes respective of the interrupt. 
  • Clears interrupt flags set by peripherals in their interrupt registers. 
  • Writes a dummy word into VICVectAddr register to indicate EoI, to clear respective interrupt in VIC interrupt priority hardware. 
  • Returns back to interrupted program, re-enables interrupts.

LED Interfacing with LPC2148

Schematic Diagram

LED.png

Interfacing Description

Port Pin No.LED 
P0.15D1
P0.16D2
P0.17D3
P0.18D4
P0.19D5
P0.20D6
P0.21D7
P0.22D8
Program

#include<lpc21xx.h>
void delay(void);
int main (void)
{
IODIR0 = 0x007F8000; //configure P0.15 to P0.22 as an output pins
while (1)                            //Loop forever   
{     
IOSET0=0x007F8000; //turn LEDs ON by setting P0.15 to P0.22 as High   
delay();
IOCLR0=0x007F8000; //turn LEDs Off by setting P0.15 to P0.22 as Low
delay();   
}
}
void delay(void)
{
 unsigned int j;  
 for(j=0;j<1000000;j++);
}

LCD Interfacing with LPC2148

Introduction to LCD


The LCDs have a parallel interface, meaning that the microcontroller has to manipulate several interface pins at once to control the display. The interface consists of the following pins:

LCD Pin Description

LCD pin no.LCD pin nameLCD pin Description
1VssGround pin of the LCD module.
2VccPower to LCD module (+5V supply)
3VEEContrast adjustment pin
4RSRegister select pin
RS=0 command register.
RS=1 data register. 
5R/WRead/Write modes
R/W=1; Read mode
R/W=1; Write mode
6ENThis pin is meant for enabling the LCD module
7-14DB0 to DB78 data pins
15LED+Anode of the back light LED
16LED-Cathode of the back light LED
The process of controlling the display involves putting the data that form the image of what you want to display into the data registers, then putting instructions in the instruction register. 
Mostly used commands or instructions for LCD
Sr.No.InstructionHex
1Function Set: 8-bit mode, 1 Line, 5x7 Dots matrix for each character display0x30
2Function Set: 8-bit mode, 2 Line, 5x7 Dots matrix for each character display0x38
3Function Set: 4-bit mode, 1 Line, 5x7 Dots matrix for each character display0x20
4Function Set: 4-bit mode, 2 Line, 5x7 Dots matrix for each character display0x28
5Clear display screen0x01
6Return Home0x02
7Decrement cursor(Shift to left)0x04
8Increment cursor(Shift to Right)0x06
9Display off Cursor off0x08
10Display on Cursor on0x0E
11Display on Cursor off0x0C
12Display on Cursor blinking0x0F
13Shift entire display left0x18
14Shift entire display right0x1C
15Move cursor left by one character0x10
16Move cursor right by one character0x14
17Clear Display (also clear DDRAM content)0x01
18Force cursor position on  first position of  first 0x80 
19Force cursor position on  first position of  second row 0xC0 

Schematic Diagram

LCD.png

Interfacing Description

LPC2148 Port Pin No.LCD Pins
P1.16D0
P1.17D1
P1.18D2
P1.19D3
P1.20D4
P1.21D5
P1.22D6
P1.23D7
P1.25RS
P0.29EN
P0.10BC

Embedded C code for the Interfacing

#include<lpc21xx.h>
void lcdcmd(unsigned int cmd);
void lcddata(unsigned int data);
void delay(unsigned int itime);
int main()
{
  unsigned char array[]="WIKINOTE FOUNDATION";
  unsigned int i=0;
  PINSEL0=0X00000000;
  PINSEL1=0X00000000;
  PINSEL2=0X00000000;
  IODIR0=0X20000400;
  IODIR1=0X02FF0000;
  IOCLR0=0X00000400;
  lcdcmd(0x38);
  delay(100);
  lcdcmd(0x06);
  delay(100);
  lcdcmd(0x01);
  delay(100);
  lcdcmd(0x0e);
  delay(100);
  lcdcmd(0x80);
  delay(100);
 
  for(i=0;i<7;i++)
  {
    lcddata(array[i]);
    delay(1000);
   
  }
  lcdcmd(0xc0);
  delay(100);
  for(i=9;i<19;i++)
  {
   lcddata(array[i]);
    delay(1000);
  }
  return 0;
}
void delay(unsigned int itime)
{
  int i,j;
  for(i=0;i<itime;i++)
  for(j=0;j<200;j++);
}
void lcdcmd(unsigned int cmd )
{
 IOCLR1=0X00FF0000;
 cmd=cmd<<16;
 IOSET1=cmd;
 IOCLR1=0X02000000;
 IOSET0=0X20000000;
 delay(100);
 IOCLR0=0X20000000;
}
void lcddata(unsigned int data )
{
 IOCLR1=0X00FF0000;
 data=data<<16;
 IOSET1=data;
 IOCLR1=0X02000000;
 IOSET0=0X20000000;
 delay(100);
 IOCLR0=0X20000000;
}

Keypad Interfacing with LPC2148

Schematic Diagram

keyboard_interfacing.png

Interfacing Description

LPC2148 Port Pin No.LCD Pins
P1.16D0
P1.17D1
P1.18D2
P1.19D3
P1.20D4
P1.21D5
P1.22D6
P1.23D7
P0.28RS
P0.29EN
P0.10BC
LPC2148 Port Pin No.Keyboard connection
P0.2,P0.3,P0.4,P0.5
Column Read Lines
 P0.6,P0.7,P0.8,P0.9Row Scan Lines

Embedded C program for the Interfacing

#include<lpc21xx.h>
void lcdcmd(unsigned int);
void lcddata(unsigned int);
void delay_lcd(void);
int main(void)
{
   while(1)
{
 IODIR1=0x00ff0000;
 IODIR0=0x300003c0;
 lcdcmd(0x38);
 lcdcmd(0x0e);
 lcdcmd(0x01);
 lcdcmd(0x06);
 lcdcmd(0x83);
 lcdcmd(0xC0);
IO0PIN=0x00000380;// First Scan Line(row status) if(( IO0PIN & 0x0000003c )!= 0x0000003c))////(row & column) {
switch(IO0PIN & 0x0000003c)
 {
case 0x00000038 : lcddata("C");break;
case 0x00000034 : lcddata("D");break;
case 0x0000002c : lcddata("E");break;
case 0x0000001c : lcddata("F");break;
 }
 }
 IO0PIN=0x00000340;// Second Scan Line(row status) if(( IO0PIN & 0x0000003c )!= 0x0000003c) )////(row & column) {
switch(IO0PIN & 0x0000003c)
 {
case 0x00000038 : lcddata("8");break;
case 0x00000034 : lcddata("9");break;
case 0x0000002c : lcddata("A");break;
case 0x0000001c : lcddata("B");break;
 }
 }
        IO0PIN=0x000002c0;// Third Scan Line(row) if(( IO0PIN & 0x0000003c )!= 0x0000003c)////(row & column {
switch(IO0PIN & 0x0000003c)
 {
case 0x00000038 : lcddata("4");break;
case 0x00000034 : lcddata("5");break;
case 0x0000002c : lcddata("6");break;
case 0x0000001c : lcddata("7");break;
 }
 }
 IO0PIN=0x000001c0; // Four Scan Line(row)  if(( IO0PIN & 0x0000003c )!= 0x0000003c)////(row & column) {
switch(IO0PIN & 0x0000003c)
 {
case 0x00000038 : lcddata("0");break;
case 0x00000034 : lcddata("1");break;
case 0x0000002c : lcddata("2");break;
case 0x0000001c : lcddata("3");break;
 }
 }
 delay_lcd();
}
}
void lcdcmd(unsigned int cmddata)
{
 IOCLR1=0x00ff0000;
 IOCLR0=0x10000000;
 cmddata=cmddata<<16;
 IOSET1=cmddata;
 IOSET0=0x20000000;
 delay_lcd();
 IOCLR0=0x20000000;
 delay_lcd();
return;
}
void lcddata(unsigned int outdata)
{
 IOCLR1=0x00ff0000;
 IOSET0=0x10000000;
 outdata=outdata<<16;
 IOSET1=outdata;
 IOSET0=0x20000000;
 delay_lcd();
 IOCLR0=0x20000000;
 delay_lcd();
return;
}
void delay_lcd(void)
{
int j;
for(j=0;j<10000;j++);
return;
}

GLCD


Simple LPC2148 GPIO Programming examples Using timers of LPC2148 to generate delay

Example-/* TOGGLE LEDS FROM P0.0 TO P0.15 WITH EXACT DELAY OF 3SEC */ Fosc=60 Mhz
#include<lpc21xx.h> 
void delay(void);
int main()
{ VPBDIV=0X02; //30MHZ// PINSEL0=0X00000000; IODIR0=0X0000FFFF; IOCLR0=0X0000FFFF;
while(1)
{
IOSET0=0X0000FFFF;
delay();
IOCLR0=0X0000FFFF;
delay();
}
}
void delay(void)
{
T0PR=29999;
T0MR0=3000;
T0TC=0x00000000;
T0TCR=0X01; //START TIMER// while(T0TC !=T0MR0); //1 SEC// T0TCR=0X02; //STOP TIMER/ }
Example:-/* TOGGLE LEDS FROM P0.0 TO P0.7 WITH EXACT DELAY OF 2 SEC BY USING T0MR3.TOGGLE LEDS FROM P0.15 TO P0.23 WITH EXACT DELAY OF 5 SEC BY USING T1MR2. */(Fosc=60Mhz)
#include<lpc21xx.h>
void delay1(void);
void delay2(void);
int main()
{
VPBDIV=0X02;//30MHZ//PINSEL0=0X00000000;
IODIR0=0X00FF00FF;
IOCLR0=0X00FF00FF;
while(1)
{IOSET0=0X00FF00FF;
delay1();
IOCLR0=0X00FF00FF;
delay2();
}
}
void delay1(void)
{
T0PR=29999;
T0MR3=2000;
T0TC=0x00000000;
T0TCR=0X01; //START TIMER//while(T0TC !=T0MR3); //2 SEC//T0TCR=0X02; //STOP TIMER/}
void delay2(void)
{
T1PR=29999;
T1MR2=5000;
T1TC=0x00000000;
T1TCR=0X01; //START TIMER//while(T1TC !=T1MR2); //5 SEC//T1TCR=0X02; //STOP TIMER//}

UART0

Features

  • 16 byte Receive and Transmit FIFOs
  • Register locations conform to ‘550 industry standard.
  • Receiver FIFO trigger points at 1, 4, 8, and 14 bytes.
  • Built-in fractional baud rate generator with auto-bauding capabilities.
  • Mechanism that enables software and hardware flow control implementation.

Pin description

Pin  Type     Description
RXD0InputSerial Input: Serial receive data.
TXD0OutputSerial Output: Serial transmit data.

UART1

Features

  • UART1 is identical to UART0, with the addition of a modem interface.
  • 16 byte Receive and Transmit FIFOs.
  • Register locations conform to ‘550 industry standard.
  • Receiver FIFO trigger points at 1, 4, 8, and 14 bytes.
  • Built-in fractional baud rate generator with autobauding capabilities.
  • Mechanism that enables software and hardware flow control implementation.
  • Standard modem interface signals included with flow control (auto-CTS/RTS) fully
  • supported in hardware (LPC2144/6/8 only).

Pin description

Pin  Type     Description
RXD1InputSerial Input: Serial receive data.
TXD1OutputSerial Output: Serial transmit data.
CTS1InputClear To Send
DCD1InputData Carrier Detect
DSR1InputData Set Ready
DTR1OutputData Terminal Ready
RI1InputRing Indicator
RTS1OutputRequest To Send

UART0

Block Diagram

UART_Block_Diagram.PNG

UART Registers and Programming Steps for UART

U0FCR (FIFO Control Register)
  • 8-BIT Byte Addressable register
  • This reg is used to enable TX & RX FIFO functionalities
  • U0FCR=0x07 is like SCON reg
U0FCRFIFO Control Register-----TX FIFO ResetRX FIFO ResetFIFO Enable
U0LCR (Line Control Register)
  • 8-BIT byte addressable register
UART0 Line Control Register (U0LCR - address 0xE000 C00C) bit description 
BitSymbolValueDescriptionReset Value
1:0


 
Word Length Select


 
005 bit character length0


 
016 bit character length
107 bit character length
118 bit character length
2
 
Stop Bit Select
 
01 stop bit0
 
12 stop bits (1.5 if U0LCR[1:0]==00)
3
 
Parity Enable
 
0Disable parity generation and checking0
 
1Enable parity generation and checking
5:4


 
Parity Select


 
00Odd parity. Number of 1s In the transmitted character and the attached parity bit will be odd.0


 
01Even Parity. Number of is in the transmitted character and the attached parity bit will be even.
10Forced "1" stick parity.
11Forced "0" stick parity.
6
 
Break Control
 
0Disable break transmission0
 
1Enable break transmission. Output pin UARTO TXD Is forced to logic 0 when UOLCR[6] Is active high. 
7
 
Divisor Latch Access Bit (DLAB)
 
0Disable access to Divisor Latch0
1Enable access to Divisor Latch
DLAB (Divisor Latch Buffer)
One high-low pulse across DLAB bit indicates baud rate is successfully loaded.
  • DLAB=1  baud rate is loading
  • DLAB=0  After loading baud rate DLAB must be zero.
Baud Rate
U0LCR=0x83 ;//8 bits character length,No parity,1 stop bit,9600 Baud rateU0LCR=0x03
U0LSR (Line Status Register)
  • 8-bit byte addressable register
  • Consists of different flag bits, TI interrupt & RI interrupt flag bit
UART0 Line Status Register
BitSymbolValueDescriptionReset value
0Receiver Data Ready (RDR) U0LSR0 is set when the U0RBR holds an unread character and is cleared when the UART0 RBR FIFO is empty. 0
0U0RBR is empty.
1U0RBR contains valid data.
1

 
Overrun Error (OE)

 
 The overrun error condition is set as soon as it occurs. An U0LSR read clears U0LSR1. U0LSR1 is set when UART0 RSR has a new character assembled and the UART0 RBR FIFO is full. In this case, the UART0 RBR FIFO will not be overwritten and the character in the UART0 RSR will be lost. 0

 
0Overrun error status is inactive.
1Overrun error status is active.
2
 
Parity Error
 
 
When the parity bit of a received character is in the wrong state, a parity error occurs. An U0LSR read clears U0LSR[2]. Time of parity error detection is dependent on U0FCR(0).
Note: A parity error is associated with the character at the top of the UART0 RBR FIFO.
0
 
0Parity error status is Inactive.
3

 
Framing Error (FE)

 
 
When the stop bit of a received character is a logic 0. a framing error occurs. 0 An U0LSR read dears U0LSR[3]. The time of the framing error detection is dependent on U0FCR0. Upon detection of a framing error, the Rx will attempt to resynchronize to the data and assume that the bad stop bit is actually an early start bit. However, it cannot be assumed that the next received byte will be correct even if there is no Framing Error.
Note: A framing error is associated with the character at the top of the UART0 RBR FIFO.
0

 
0Framing error status is inactive. 
1Framing error status is active. 
4

 
Break Interrupt (BI)

 
 
When RXD0 is held in the spacing state (all 0's) for one full character transmission (start, data, parity, stop), a break interrupt occurs. Once the break condition has been detected, the receiver goes idle until RXD0 goes to marking state (all 1s). An U0LSR read clears this status bit. The time of break detection is dependent on U0FCR(0).
Note: The break interrupt is associated with the character at the top of the UART0 RBR FIFO.
0

 
0Break interrupt status is inactive. 
1Break interrupt status is active. 
5

 
Transmitter Holding Register Empty (THRE)

 
 THRE is set immediately upon detection of an empty UART0 THR and is 1
cleared on a U0THR write. 
1

 
0U0THR contains valid data. 
1U0THR is empty.
6

 
Transmitter Empty (TEMT) 

 
 TEMT is set when both U0THR and U0TSR are empty; TEMT is cleared when either the U0TSR or the U0THR contain valid data.1

 
0U0THR and/or the U0TSR contains valid data. 
1U0THR and the U0TSR are empty. 
7

 
Error in RX FIFO (RXFE) 

 
 UOLSR(7) is set when a character with a Rx error such as framing error, parity error or break interrupt, is loaded into the U0RBR. This bit is cleared when the U0LSR register is read and there are no subsequent errors in the UART0 FIFO.0
 
0U0RBR contains no UART0 RX errors or U0FCR[0]=0.
1UART0 RBR contains at least one UART0 RX error.
6th bit of LSR is TI flag bit
While(!(U0LSR&0x40));//Monitoring TI bit syntax
0th bit of LSR is RI flag bit
While(!(U0LSR&0x10));//Monitoring RI bit syntax
DLR (Divisor Latch Register)
  • DLR is 16-bit register
  • Used to load baud rate
  • As the baud rate is 8-bit value, divide DLR into two parts DLM & DLL (8-bit each)
For 9600 baud rate
U0DLL=0x63;     //(Pclk=12Mhz)
U0DLM=0x00
U0DLL:U0DLM=[Pclk/16*Desired Baud rate]
U0THR (Transmit Hold Register)
  • 8-bit byte addressable reg
  • Data can be loading to U0THR, whenever transmitting data
U0THR=‘A’   //THR buffer register is used only for transmitting
U0RBR (UART0 Receive Buffer Register)
  • 8-bit byte addressable reg
  • Data can be loading into U0RBR, whenever receiving data.
a = U0RBR   //RBR buffer register is used only for transmitting

Interfacing Diagram of LPC2148 with PC

Serial-Communication-between-LPC2148-and-PC.png

Algorithm

1) Start
2) Initialise UART0 serial interface using following instruction
PINSEL0=0X0000 0005;//Enable P0.0-TxD0,P0.1-RxD0
U0LCR=0X83;  //8-BIT Character lenth,NO parity,1 stop bit, DLAB=1
U0DLL=97; //Baud rate=9600@PCLK=15Mhz
U0LCR=0X03;//DLAB=0
3) LPC2148 will receive characters transmitted by PC
4) LPC2148 will transmit the characters received back to PC
3) Transmit different AT commands through UART module using instruction
while(!(U0LSR&0X20));//Monitor TI flag
4) If transmission buffer is Empty,Transmit single character at a time 
U0THR=ch;
5) Provide delay while transmitting each command
6) To transmit a single character use PUTCH function & to transmit a string use PUTS function 
7) END

Embedded C program for Serial Transmission and Reception

#include<lpc21xx.h>   //Includes LPC2148 register definitions

void Uart0Init (void)      // Initialize Serial Interface       {                   
    PINSEL0 = 0x00000005;           //Enable RxD0 and TxD0                         U0LCR = 0x83;                   // 8 bits, no Parity, 1 Stop bit                U0DLL = 97;                     // 9600 Baud Rate @ 15MHz PCLK             U0LCR = 0x03;       // DLAB = 0  }
   
void Uart0PutCh (unsigned char ch)  // Write character to Serial Port   {                    
    U0THR = ch;
  while (!(U0LSR & 0x20));
}

void  Uart0PutS(unsigned char *str)  //A function to send a string on UART0{  
while(*str)
{  
     Uart0PutCh(*str++);     
}
}
unsigned char Uart0GetCh (void)  // Read character from Serial Port   {            
 while (!(U0LSR & 0x01));
 return (U0RBR);
}
int main()
{
unsigned char a;
Uart0Init();
while(1)
{
a=Uart0GetCh();
Uart0PutCh(a);
}
}