/* A demonstration of LCD operation in 8 and 4-bit modes. controller is P89C668HBA, compiler is SDCC */ #define BIT8 //for 8-bit mode. Comment this line for 4-bit mode #define EN P2_7 #define RS P2_6 #define BL P2_5 #define CMD 0 #define DTA 1 #define CLEAR 0 #define SET 1 #define ON 0 #define OFF 1 #define GREEN_LED P1_4 #define RED_LED P1_0 __sbit __at (0x90) P1_0; __sbit __at (0x94) P1_4; __sbit __at (0x8C) TR0; __sbit __at (0x8D) TF0; __sbit __at (0xA5) P2_5; __sbit __at (0xA6) P2_6; __sbit __at (0xA7) P2_7; __sfr __at (0x8B) TH0; __sfr __at (0x8A) TL0; __sfr __at (0x89) TMOD; /* #define BIT8 /\* a default choice of 8-bit LCD operation; Comment this */ /* * line for 4-bit application.*\/ */ void delay_millisec(unsigned int delay) { /* A subroutine for generating 1ms delay */ TMOD |= 0x01; /* timer 0; mode 1 */ TH0 = 0xF4; TL0 = 0x03; /* with 18.423MHz crystal; delay = 0.326*3068 * us--approximatly 1ms */ for ( ; delay != 0; delay-- ) { TR0 = SET; /* start timer */ while(TF0 == CLEAR) ; /* wait for timer overflow */ TF0 = CLEAR; /* clear flags */ } TR0 = CLEAR; /* stop timer */ } #ifdef BIT8 /* 8-bit mode specific functions */ #define DATA P0 __sfr __at (0x80) P0; void write_to_lcd( bit rs, unsigned char byte) { /* A function to write to LCD in 8-bit mode */ RS = rs; /* select the register:- CMD command and DTA data */ EN = SET; DATA = byte; /* put data on data bus */ EN = CLEAR; /* A 1 to 0 transition on EN validates data on * data line */ delay_millisec(2); /* ramdom wait till data is processed by * LCD */ } void init_lcd() { /* 8-bit intialization process as defined in the OLIMEX * datasheets */ delay_millisec(20); /* delay greater than 15ms */ write_to_lcd( CMD, 0x30); /* function set command */ delay_millisec(5); /* delay greater than 4.1 ms */ write_to_lcd( CMD, 0x30); /* function set command */ delay_millisec(1); /* delay greater than 100us */ write_to_lcd( CMD, 0x30); /* function set command */ /* LCD is initialized here */ write_to_lcd( CMD, 0x3C); /* function set command:- 1/16 duty * 5x10 dots */ write_to_lcd( CMD, 0x08); /* display off */ write_to_lcd( CMD, 0x01); /* clear display */ write_to_lcd( CMD, 0x06); /* entry mode:- display ON,shift * OFF */ write_to_lcd( CMD, 0x0F); /* display ON, cursor ON, blink * ON */ } #endif #ifndef BIT8 /* 4-bit mode specific functions */ #undef BIT8 /* upper nibble of LCD data line */ #define D7 P0_7 #define D6 P0_6 #define D5 P0_5 #define D4 P0_4 __sbit __at (0x87) P0_7; __sbit __at (0x86) P0_6; __sbit __at (0x85) P0_5; __sbit __at (0x84) P0_4; void write_4bit_to_lcd( bit rs, unsigned char byte) { /* A function to write to LCD in 4-bit mode */ RS = rs; /* select the register:- CMD command and DTA data */ EN = SET; /* put the nibble on the data bus */ D7 = (byte & 0x80) ? SET: CLEAR; D6 = (byte & 0x40) ? SET: CLEAR; D5 = (byte & 0x20) ? SET: CLEAR; D4 = (byte & 0x10) ? SET: CLEAR; EN = CLEAR; /* A 1 to 0 transition on EN validates data on * data line */ delay_millisec(5); /* ramdom wait till data is processed by * LCD */ } void write_to_lcd(bit rs, unsigned char byte) { /* A function to write 8-bit data on 4-bit LCD */ write_4bit_to_lcd(rs, (byte & 0xF0) ); /* write the upper * nibble first */ write_4bit_to_lcd(rs, (byte << 4) ); /* write the lower * nibble */ } void init_lcd() { /* 4-bit intialization process as defined in the OLIMEX * datasheets */ delay_millisec(20); /* delay greater than 15ms */ write_4bit_to_lcd( CMD, 0x30); /* function set command */ delay_millisec(5); /* delay greater than 4.1 ms */ write_4bit_to_lcd( CMD, 0x30); /* function set command */ delay_millisec(1); /* delay greater than 100us */ write_4bit_to_lcd( CMD, 0x30); /* function set command */ /* module is initialized */ write_4bit_to_lcd( CMD, 0x20); /* function sets interface to * 4-bit */ write_to_lcd( CMD, 0x28); /* function set command:- 1/16 * duty 5x10 dots */ write_to_lcd( CMD, 0x08); /* display off */ write_to_lcd( CMD, 0x01); /* clear display */ write_to_lcd( CMD, 0x06); /* entry mode:- display * ON,shift OFF */ write_to_lcd( CMD, 0x0F); /* display ON, cursor ON, blink * ON */ } #endif void print_on_lcd( char *str ) { /* A function to display a string on LCD */ unsigned char ch = 0; write_to_lcd( CMD, 0x01); /* clear display */ write_to_lcd( CMD, 0x02); /* return home */ write_to_lcd( CMD, 0x80 ); /* place cursor at first row, first * column */ while ( (str[ch] != 0) && (ch < 32) ) { /* LCD can display a * maximum of 32 * characters */ if (ch == 16) write_to_lcd( CMD, 0xC0); /* move the cursor * to line 2 */ write_to_lcd( DTA, str[ch] ); ch++; } } main() { init_lcd(); #ifdef BIT8 print_on_lcd("testing LCD 8 bit mode"); #endif #ifndef BIT8 print_on_lcd("LCD 4-bit mode test successful!!!!"); #endif while(1) { BL ^= 1; /* toggle LCD backlight */ RED_LED ^= 1; GREEN_LED ^= 1; delay_millisec(60); } }