/***************************************************************************/ /* Lcd.c LCD interface routines */ /* Version : 2.1. for PIC16F87x */ /* */ /* J. Winpenny 1/8/2000 */ /* */ /* */ /* Mode : HD44780 type LCD */ /* */ /* */ /* Notes : Updated version */ /* to allow greater adaptability to different displays */ /* */ /***************************************************************************/ #include /* Definitions for the LCD interface */ #define LCD_SEL 3 /* Port A bit 3 ( Enables LCD ) */ #define LCD_WR 2 /* Port A bit 2 ( Logic 0 = Write ) */ #define LCD_RS 0 /* Port A bit 1 ( Register select ) */ #define LCD_DATA PORTB /* The port the lcd data bus is connected to */ #define LCD_CONTROL PORTA /* The port the lcd control bus is connected to */ #define BUSY_BIT 7 #define BUSY_MASK 0x80 #define LCD_DATA_4 4 /* LCD BIT 0 */ #define LCD_DATA_5 5 /* LCD BIT 1 */ #define LCD_DATA_6 6 /* LCD BIT 2 */ #define LCD_DATA_7 7 /* LCD BIT 3 */ /************************************************************/ /* LCD Commands ( Refer to LCD Data Sheet ) */ /* Standard command should work with most common devices */ /************************************************************/ #define clear_lcd 0x01 /* Clear Display */ #define return_home 0x02 /* Cursor to Home position */ #define entry_mode 0x06 /* Normal entry mode */ #define entry_mode_shift 0x07 /* - with shift */ #define system_set_8_bit 0x38 /* 8 bit data mode 2 line ( 5x7 font ) */ #define system_set_4_bit 0x28 /* 4 bit data mode 2 line ( 5x7 font ) */ #define display_on 0x0c /* Switch ON Display */ #define display_off 0x08 /* Cursor plus blink */ #define set_dd_line1 0x80 /* Line 1 position 1 */ #define set_dd_line2 0xC0 /* Line 2 position 1 */ #define set_dd_ram 0x80 /* Line 1 position 1 */ #define write_data 0x00 /* With rs = 1 */ #define cursor_on 0x0E /* Switch Cursor ON */ #define cursor_off 0x0C /* Switch Cursor OFF */ char ModeFlags; char LCD_gp; /***********************************/ /* Setup the lcd device */ /***********************************/ void LCDSetup(void) { /* Reset the LCD */ ModeFlags = 0; /* Default to Function Mode */ Write_8_Bit( system_set_4_bit ); /* This sequence resets the LCD */ delay_ms(5); Write_8_Bit( system_set_4_bit ); delay_ms(1); Write_8_Bit( system_set_4_bit ); delay_ms(1); Write_4_Bit( system_set_4_bit ); // WaitBusyFlag(); Write_4_Bit( display_on ); Write_4_Bit( clear_lcd ); Write_4_Bit( entry_mode ); Write_4_Bit( set_dd_ram ); ModeFlags = 1; /* Data Mode */ } /***********************************/ /* Test LCD Busy flag */ /***********************************/ void WaitBusyFlag(void) { set_bit( STATUS, RP0 ); // Register Page 1 TRISB = ( PortBConfig | 0xf0 ); // Make LCD port input clear_bit( STATUS, RP0 ); // Register page 0 set_bit( LCD_CONTROL, LCD_WR ); // Read mode set_bit( LCD_CONTROL, LCD_SEL); // Select LCD // Wait for LCD to respond while( ( LCD_DATA & BUSY_MASK ) != 0 ) { nop(); } clear_bit( LCD_CONTROL, LCD_SEL ); // de-select LCD clear_bit( LCD_CONTROL, LCD_WR ); // Write mode // Reset Port B 4,7 to Output set_bit( STATUS, RP0 ); // Register Page 1 TRISB = PortBConfig; // clear_bit( STATUS, RP0 ); // Register page 0 } /***********************************/ /* Put LCD in Function Mode */ /***********************************/ void FunctionMode(void) { clear_bit( ModeFlags, 0 ); /* Save Mode */ clear_bit( LCD_CONTROL, LCD_RS ); Delay(); } /***********************************/ /* Put LCD in Data Mode */ /***********************************/ void DataMode(void) { set_bit( ModeFlags, 0 ); /* Save Mode */ set_bit( LCD_CONTROL, LCD_RS ); Delay(); } /***********************************/ /* Write a single byte to the LCD */ /* 8 Bit Mode */ /***********************************/ void Write_8_Bit( char dh ) { //******************************************************* // NOTE: THIS WON'T WORK IF CONTROL AND DATA ON SAME PORT //******************************************************* clear_bit( LCD_CONTROL, LCD_WR ); /* Write mode */ clear_bit( LCD_CONTROL, LCD_RS ); /* Function mode */ clear_bit( LCD_CONTROL, LCD_SEL); //LCD_CONTROL = 0; delay_ms(1); // May affect control lines ! LCD_DATA = dh; /* Setup data */ clear_wdt(); set_bit( LCD_CONTROL, LCD_SEL ); /* Select LCD */ Delay(); clear_bit( LCD_CONTROL, LCD_SEL ); /* de-select LCD */ Delay(); clear_wdt(); } /***********************************/ /* Write a single byte to the LCD */ /* 4 Bit Mode */ /***********************************/ void Write_4_Bit(char dl ) { //******************************************************* // NOTE: THIS WON'T WORK IF CONTROL AND DATA ON SAME PORT //******************************************************* char e; e = dl; /* Save lower 4 bits */ /*********************************** Output Upper 8 bits ******************************/ clear_bit( LCD_CONTROL, LCD_WR ); /* Write mode */ if ( ( ModeFlags & 0x01 ) == 0 ) clear_bit( LCD_CONTROL, LCD_RS ); /* Function mode */ else set_bit( LCD_CONTROL, LCD_RS ); /* Data mode */ clear_bit( LCD_CONTROL, LCD_SEL); LCD_DATA = dl; /* Setup data */ set_bit( LCD_CONTROL, LCD_SEL); /* Select LCD */ Delay(); clear_bit( LCD_CONTROL, LCD_SEL ); /* de-select LCD */ dl = e; /* Restore lower 4 bits */ dl <<= 4; /*********************************** Output Lower 8 bits ******************************/ clear_bit( LCD_CONTROL, LCD_WR ); /* Write mode */ if ( ( ModeFlags & 0x01 ) == 0 ) clear_bit( LCD_CONTROL, LCD_RS ); /* Function mode */ else set_bit( LCD_CONTROL, LCD_RS ); /* Data mode */ clear_bit( LCD_CONTROL, LCD_SEL); LCD_DATA = dl; /* Setup data */ set_bit( LCD_CONTROL, LCD_SEL); /* Select LCD */ Delay(); clear_bit( LCD_CONTROL, LCD_SEL ); /* de-select LCD */ Delay(); } /***********************************/ /* LCD timing delay */ /* Adjust for your LCD */ /***********************************/ void Delay(void) { delay_ms(2); clear_wdt(); } /***********************************/ /* Clear LCD Screen */ /***********************************/ void Clear(void) { FunctionMode(); Write_4_Bit(clear_lcd); DataMode(); } /***********************************/ /* Set the cursor position */ /***********************************/ void SetPos(char Pos) { FunctionMode(); Write_4_Bit( Pos ); DataMode(); } /***********************************/ /* Set Position to line 1 */ /***********************************/ void Line1(void) { FunctionMode(); Write_4_Bit( set_dd_line1 ); DataMode(); } /***********************************/ /* Set Position to line 2 */ /***********************************/ void Line2(void) { FunctionMode(); Write_4_Bit( set_dd_line2 ); DataMode(); } /*******************************************/ /* Clear Line 1 */ /*******************************************/ void ClearLine1(void) { Line1(); for( LCD_gp = 0; LCD_gp < 16; LCD_gp++ ) { Write_4_Bit(' '); } Line1(); } /*******************************************/ /* Clear Line 2 */ /*******************************************/ void ClearLine2(void) { Line2(); for( LCD_gp = 0; LCD_gp < 16; LCD_gp++ ) { Write_4_Bit(' '); } Line2(); } /*******************************************/ /* Write a const string to the LCD */ /*******************************************/ void WriteString( const char *lcdptr ) { char pi; char ch; pi = 0; // Check for end of string while( lcdptr[pi] != 0 ) { ch = lcdptr[pi++]; Write_4_Bit( ch );// Display on LCD } }