1: /* 2: * LCD interface example 3: * Uses routines from delay.c 4: * This code will interface to a standard LCD controller 5: * like the Hitachi HD44780. It uses it in 4 or 8 bit mode 6: * 7: */ 8: 9: #include 10: #include "lcd.h" 11: #include "delay.h" 12: 13: 14: static bit fourbit; // four or eight bit mode? 15: 16: #ifdef CHECKBUSY 17: 18: unsigned char 19: lcd_read_cmd_nowait(void) 20: { 21: unsigned char c, readc; 22: 23: LCD_DATA_TRIS = INPUT_DATA; 24: 25: LCD_RW = 1; // Read LCD 26: asm("nop"); // short propagation delay 27: asm("nop"); // short propagation delay 28: 29: if (fourbit) 30: { 31: LCD_STROBE_READ(readc); // Read high nibble 32: // Move 4 bits to high nibble while zeroing low nibble 33: c = ( ( readc << 4 ) & 0xF0 ); 34: LCD_STROBE_READ(readc); // Read low nibble 35: c |= ( readc & 0x0F ); // Or in 4 more bits to low nibble 36: } 37: else 38: { 39: LCD_STROBE_READ(readc); 40: c = readc; 41: } 42: LCD_RW = 0; // Return to default mode of writing LCD 43: LCD_DATA_TRIS = OUTPUT_DATA; // Return to default mode of writing LCD 44: 45: return(c); 46: } 47: 48: void 49: lcd_check_busy(void) // Return when the LCD is no longer busy, or we've waiting long enough! 50: { 51: // To avoid hanging forever in event there's a bad or 52: // missing LCD on hardware. Will just run SLOW, but still run. 53: unsigned int retry; 54: unsigned char c; 55: 56: for (retry=1000; retry-- > 0; ) { 57: c = lcd_read_cmd_nowait(); 58: if (0==(c&0x80)) break; // Check busy bit. If zero, no longer busy 59: } 60: } 61: 62: #endif 63: 64: /* send a command to the LCD */ 65: void 66: lcd_cmd(unsigned char c) 67: { 68: LCD_WAIT; // may check LCD busy flag, or just delay a little, depending on lcd.h 69: 70: if (fourbit) 71: { 72: LCD_DATA = ( ( c >> 4 ) & 0x0F ); 73: LCD_STROBE(); 74: LCD_DATA = ( c & 0x0F ); 75: LCD_STROBE(); 76: } 77: else 78: { 79: LCD_DATA = c; 80: LCD_STROBE(); 81: } 82: } 83: 84: /* send data to the LCD */ 85: void 86: lcd_data(unsigned char c) 87: { 88: LCD_WAIT; // may check LCD busy flag, or just delay a little, depending on lcd.h 89: 90: LCD_DATA = 0; 91: LCD_RS = 1; 92: if (fourbit) 93: { 94: LCD_DATA |= ( ( c >> 4 ) & 0x0F ); 95: LCD_STROBE(); 96: LCD_DATA &= 0xF0; 97: LCD_DATA |= ( c & 0x0F ); 98: LCD_STROBE(); 99: } 100: else 101: { 102: LCD_DATA = c; 103: LCD_STROBE(); 104: } 105: LCD_RS = 0; 106: } 107: 108: /* write a string of chars to the LCD */ 109: 110: void 111: lcd_puts(const char * s) 112: { 113: while(*s) 114: lcd_data(*s++); 115: } 116: 117: /* initialize the LCD */ 118: void 119: lcd_init(unsigned char mode) 120: { 121: char init_value; 122: 123: fourbit = 0; 124: if (mode == FOURBIT_MODE){ 125: fourbit = 1; 126: init_value = 0x3; 127: }else{ 128: init_value = 0x3F; 129: } 130: LCD_RS = 0; 131: LCD_EN = 0; 132: LCD_RW = 0; 133: LCD_RS_TRIS = OUTPUT_PIN; 134: LCD_EN_TRIS = OUTPUT_PIN; 135: LCD_RW_TRIS = OUTPUT_PIN; 136: LCD_DATA_TRIS = OUTPUT_DATA; 137: DelayMs(15); 138: LCD_DATA = init_value; 139: LCD_STROBE(); 140: DelayMs(5); 141: LCD_DATA = init_value; 142: LCD_STROBE(); 143: DelayUs(200); 144: LCD_DATA = init_value; 145: LCD_STROBE(); 146: 147: if (fourbit){ 148: LCD_WAIT; //may check LCD busy flag, or just delay a little, depending on lcd.h 149: LCD_DATA = 0x2; // Set 4-bit mode 150: LCD_STROBE(); 151: 152: lcd_cmd(0x28); // Function Set 153: }else{ 154: lcd_cmd(0x38); 155: } 156: lcd_cmd(0xF); //Display On, Cursor On, Cursor Blink 157: lcd_cmd(0x1); //Display Clear 158: lcd_cmd(0x6); //Entry Mode 159: lcd_cmd(0x80); //Initialize DDRAM address to zero 160: } 161: 162: 163: