This blog discuss about my research work and projects related to artificial intelligence, Internet of things, Embedded systems,Data science, Machine learning and deep learning
The graphical LCD used in this experiment is Winstar’s WDG0151 -TMI module, which is a 128×64 pixel monochromatic display. It uses two Neotic display controller chips: NT7108C and NT7107C, which are compatible with Samsung KS0108B and KS0107B controllers . The KS0108B (or NT7108C) is a dot matrix LCD segment driver with 64 channel output, and therefore, the WDG0151 module contains two sets of it to drive 128 segments. On the other hand, the KS0107B (or NT7107C) is a 64 -channel common driver which generates the timing signal to control the two KS0108B segment drivers. The KS0108B and KS0107B are very popular controllers and have made their way into many graphical LCDs. The internal block diagram of the
WDG0151 GLCD module is shown below.
The NT1707C drives the 64 display lines, COM1 – COM64. The first NT7108C drives the left half segments (SEG1 to SEG64) and the second one drives the right half segments (SEG65 to SEG128) of the display. The two halves of the display can be individually accessed through th e chip select pins (CS1 and CS2) of the two NT7108C drivers. Each half consists of 8 horizontal pages (0 -7) which are 8 bits (1 byte) high. This is illustrated in the drawing below.
Starting from page 0 on the left half (/CS1 = 0) if you transmit one data byte, it will appear on the first column of page 0. If you repeat this 64 times, then switch to the second half, and repeat until 128th position is reached, the first 8 display lines will be plotted. The next 8 lines can be plotted similarly by switching to page address 1.The total amount of bytes needed for a complete display frame (128×64 pixels) is, therefore, 2 * 64 pixels * 8 bits = 1024 bytes.
Source Code:
#include <LPC214X.H>
#define CS2 0
#define CS1 1
#define RS 4
#define RW 5
#define EN 6
#define RST 7
extern const char MY_LOGO[];
unsigned char D0;
unsigned char CMD[] = {0x3e,0xc0,0xb8,0x40,0x3f};
unsigned char i;
void GLCD_Init(unsigned long *, unsigned char);
void GLCD_Page(unsigned char);
void GLCD_Cmd (unsigned long *, unsigned char, unsigned char);
void GLCD_Data (unsigned long *, unsigned char, unsigned char);
A display that consists of two polarizing transparent panels and a liquid crystal surface
sandwiched in between. An electric current passed through the liquid causes the crystal to align so that
light cannot pass through them. The LCD has ability to display numbers, characters and graphics. A
sample photo of the LCD module is shown in Figure.
LCD Pin Description:
The LCD we used in the module has 16 pins. The functions of each pin is
RS (Register select):
There are two very important registers inside the LCD
1. Command code register
2. Data register
The RS pin is used for selection of this registers. If RS = 0, Instruction command code register is selected, allowing the user to send a command. If RS= 1 the data register is
selected, allowing the user to send data to be displayed on the LCD.
R/W (Read/ Write):
R/W input allows the user to write information to the LCD or write information from it.
R/W = 1 ; When reading
R/W = 0 ; When Writing
E (Enable):
The enable pin is used by the LCD to latch information presented to its data pins.When data is supplied to data pins, a high to low pulse must be applied to this pin in order for the LCD to latch in the data present at the data pins. This pulse must be a minimum of 450 ns wide.
D0 – D7 (Data pins):
The 8 bit data pins, D0 – D7, are used to send information to the LCD or read the contents of the
LCD‟s internal registers.
Program code
#include <lpc214x.h>
void delay_ms(unsigned char time)
{
unsigned int i, j;
for (j=0; j<time; j++)
for(i=0; i<8002; i++);
}
void LCD_command(unsigned char command)
{
IOCLR0 = 0xFF<<16;// Clear LCD Data lines
IOCLR1=1<<16;// RS=0 for command
IOCLR1=1<<17;// RW=0 for write
IOSET0=command<<16;// put command on data line
IOSET1=(1<<18);// en=1
delay_ms(10) ;// delay
IOCLR1=(1<<18);// en=0
}
LCD_data(unsigned char data)
{
IOCLR0 = 0xFF<<16;// Clear LCD Data lines
IOSET1=1<<16;// RS=1 for data
IOCLR1=1<<17;// RW=0 for write
IOSET0= data<<16; // put command on data line
IOSET1=(1<<18);//en=1
delay_ms(10) ;//delay
IOCLR1=(1<<18);//en=0
}
LCD_init()
{
LCD_command(0x38);//8bit mode and 5x8 dotes (function set)
delay_ms(10) ;// delay
LCD_command(0x0c);//display on, cursor off, cursor char blinking off(display on/off)
delay_ms(10) ;// delay
LCD_command(0x06); //cursor increament and display shift(entry mode set)
delay_ms(10) ;// delay
LCD_command(0x01); //clear lcd(clear command)
delay_ms(10) ;// delay
LCD_command(0x80); //set cursor to 0th location1st lne
}
LCD_write_string(unsigned char *string)
{
while(*string)//Check for End of String
LCD_data(*string++); //sending data on LCD byte by byte
}
int main(void)
{
PINSEL1 = 0x00;//Configure PORT0 as GPIO
PINSEL2 = 0X00;//Configure PORT1 as GPIO
IODIR1= 0x07<<16;//Configure P1.18, P1.17, P1.16 as output
IODIR0=0xFF<<16; //Configure P0.23 - P0.16 as output
UART – Universal Asynchronous Receiver Transmitter (UART0 and UART1)
UART0 has lines TXD, RXD and Gnd lines for interfacing simple serial port.
UART1 has lines apart from the above, control lines for interfacing Modem also. Now, we are going to see only the registers available in UART0
UART0 is used to send the byte of data serially and receive the byte of the data serially.
At the time of receiving, it receives the bits seri ally and assembles as parallel 8 bit data and it places in the receiver buffer register U0RBR. It is the content of the top of the FIFO buffer registers. At the time of transmitting, the user is supposed to place the 8 bit data in Transmit Hold Register Namely U0THR.
In serial communication, the serial data is sent in the same rate at which the receiving system also receives. This is called baud rate (bits per second). For example, 9600 baud means 9600 bits per second. The internal clock is divided by 16 bit no. to arrive at the required baud rate.
The Most Significant 8 bits of the divider value are stored is called U0DLM. The Least Significant 8 bits of
the divider value are stored in the register called U0DLL. At the time of writing in these registers only, DLAB bit in the U0LCR register (Line Control Register) is to be made 1. Whenever, the U0THR register is empty, the next byte of data can be sent to send it out serially. Similarly, whenever, a byte of data is received, it is placed in U0RBR. As soon as it happen, interrupt may be raised to inform the user. But interrupts are to be enabled before the use.
There is an interrupt enable register namely U0IER. By writing proper bits in the register, the above events will raise the interrupt. There is another register U0IIR, which is used to find what are all the interrupts pending. The register FIFO control register U0FCR is used to reset TX FIFO (Transmit First In First Out register set) and RX FIFO (Receive First In First Out) and to enable them.
The register U0LCR, line control register is used to write serial protocol parameters namely, the word length of the data, no. of stop bits, parity enable, parity select, Break control. The 7th bit in this register namely DLAB is used to enter the 16 bit divisor data. Line Status register U0LSR is the status register to know whether data has been received, data can be sent for transmission, to find out errors. There is another register U0TER which is used to enable the serial transmitter
PROGRAMLOGIC:
*Configure UART of ARM7 in 9600 baud rate.
* Program loop is created to send given string serially through transmitter pin of UART.
* Hyper terminal of PC is configured in 9600 baud rate in COM port 1
* Data transmitted through UART is received by receiver pin of COM port1 of PC.
* Received string is displayed in hyper terminal
PROGRAM CODE
#include <LPC214x.H>
#define PCLK 30000000 // PCLK for configuration baudrate
void UART0_Init(unsigned int baudrate);
void UART0_PutC(char c);
void UART0_PutS(char *p);
unsigned int getchar (void);
int main(void)
{
VPBDIV = 0x02; //Divide Pclk by two
UART0_Init(9600);
while(1)
{
UART0_PutS("\f*** TRENDY CODING ***\n\n\r");
}
}
unsigned int getchar (void) /* Read character from Serial Port */
{
while (!(U0LSR & 0x01));
return (U0RBR);
}
void UART0_Init(unsigned int baudrate)
{
unsigned short BAUD_REG;
BAUD_REG = PCLK/(16*baudrate); // Calculate for U0DL value
PINSEL0|= 0x00000005; // Enable rx,tx
U0LCR = 0x00000083; // 8 bit data,1 stop bit,no parity bit
U0DLL = BAUD_REG & 0xFF; // U0DL for low by te
U0DLM = (BAUD_REG>>8); // U0DL for high byte
U0LCR = 0x00000003; // DLAB =0
}
void UART0_PutC(char c)
{
while(!(U0LSR & 0x20)); // Wait until UART0 ready to send character
U0THR = c; // Send character
}
void UART0_PutS(char *p)
{
while(*p) // Point to character
{
UART0_PutC(*p++); // Send character then point to next character
There are 2 nos. of 32 bit timers in this Microcontroller. Timer is basically a counter. For timer, internal clock is given as input. Internally, PCLK, Peripheral clock is given as the input pulses.
Timer0 registers
TC0 – Timer Counter Register (32 bit register). For every clock pulse, this register is incremented. Before the clock pulse is given to TCO, the clock pulses are given to the Prescale Counter namely
PC0 – 32 bit register. Along with PC0, there is another register namely Prescale Register PR0 – 32 bit register.
The PC0 gives one output pulse for each prescale register value. For example, if the PR0 has the value of decimal 10, then the PC0 gives one output pulse fo r every 10 input clock pulses. The Prescale Counter output is given as the clock pulse to Timer Counter register TC0. In this way, 32 bit Prescale divider is included in the timer operation.
TCR0 – Timer Control Register. This register is used to reset the counter and disable/enable the Timer
Counter Register TC0.
T0MR0 – Match0 Register. It is a 32 bit register. The 32 bit content entered is compared with the content of Timer/Counter Register TC0 continuously. When the match occurs, the following functions can be actuated.
1. If the interrupt enable bit is made 1, interrupt flag bit for MR0 is made 1 in T0IR register.
2. The Timer/Counter register can be made to reset.
3. The Timer/Counter register can be disabled.
4. In the corresponding pin MAT0.0 for MR0 , output can be generated.
The first 3 functions can be actuated by writing control bits in MCR register – Match Control Register.
Similar to T0MR0, there are T0MR1, T0MR2, T0MR3 match registers. They can be also used for comparing with the contents of Timer/Counter (TC) register. On match, the above functions for the corresponding match register can be actuated.
T0IR – It is an 8 bit interrupt register. For every match, corresponding bit in this interrupt register is set. On writing again the same bit in t he Interrupt Service Routine, the corresponding bit will be cleared. Similar to match registers, there are 4 capture registers namely T0CR0, T0CR1, T0CR2 and
T0CR3. The content of Timer/Counter (TC) register value is loaded into T0CR0, when an event on physical pin CAP0.0, one particular physical input.
T0CCR is a 32 bit register which controls which edges of the capture inputs are used to load the Capture registers and whether or not an interrupt is generated when a capture takes place. In order to use the timer as counter, T0CTCR register is used. It is used to change to counter mode and to determine in which pin, physical count input pulses is given.
PROGRAMLOGIC:
* Configure 8 pins of port1 from P1.16 to P1.23as output pins by writing value ‘1’ to these pins
* Connect 8 LEDS in output pins.
*Timer 0 of ARM7 is configure to produce delay of 0.5 Second
* Program loop is created to toggle LEDs connected in PORT1 for every 0.5 sec.
Program code
#include <LPC214x.h>
#define DELAY_MS 1000 //0.5 Second(s) Delay
#define PRESCALE 60000 //60000 PCLK clock cycles to
increment TC by 1
void Timer0_Init(void);
void Timer0_Run(void);
int main(void)
{
VPBDIV = 0x01; //PCLK=60Mhz
IO1DIR = 0x00FF0000; //P1.16 to P1.23 are output
Timer0_Init(); //Initialize Timer0
while(1)
{
Timer0_Run();
}
}
void Timer0_Init(void)
{
/*Assuming that PLL0 has been setup with CCLK = 60Mhz and
PCLK also = 60Mhz.*/
T0CTCR = 0x0;
T0PR = PRESCALE-1; //(Value in Decimal!) - Increment T0TC at
every 60000 clock cycles
//Count begins from zero hence subtracting 1
//60000 clock cycles @60Mhz = 1 mS
T0MR0 = DELAY_MS-1; //(Value in Decimal!) Zero Indexed Count
- hence subtracting 1
T0MCR = 3; //Set bit0 & bit1 to High which is to :
Interrupt & Reset TC on MR0
T0TCR = 0x02; //Reset Timer
T0TCR = 0x01; //Enable timer
}
void Timer0_Run(void)
{
unsigned char regVal;
if(T0IR) //Polling the Interrupt Flag
{
regVal = T0IR;//R
ead current IR value
IO1PIN ^= 0x00FF0000; // Toggle LED pins in Port 1
T0IR = regVal; // Write back to IR to clear Interrupt Flag