| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				| Flexible LCD driver |  
				|  Posted: Thu Oct 06, 2005 8:42 pm |   |  
				| 
 |  
				| This post has the code for the 16x2 LCD driver. 
 The 20x4 LCD driver is at the following link:
 http://www.ccsinfo.com/forum/viewtopic.php?t=28268
 The 16x1 LCD driver is at the following link:
 http://www.ccsinfo.com/forum/viewtopic.php?t=30964
 
 ------------
 Flexible driver for a 16x2 LCD:
 This is an adaptation of the CCS LCD driver.    This isn't intended to
 replace the CCS driver or Mark's driver.   It's just another option
 that I decided to put out there.
 
 Advantages:
 
 1.  This driver allows you to simply specify the LCD pins at the top of
 the file.  This would be useful if your board doesn't fit the CCS driver,
 and you don't want to spend the time to figure out how to modify the
 CCS driver.
 
 2. You can put the LCD pins on several different ports.  Also, the data
 bus pins don't have to be in numerical order or on the same port.
 
 
 Disadvantages or Limitations:
 
 1.  This driver requires CCS "standard i/o" mode (The default mode
 of the compiler).   If you want to use fast i/o mode, then use the CCS
 driver or Mark's driver:
 http://www.ccsinfo.com/forum/viewtopic.php?t=20182
 
 2.  This driver uses about 50% more ROM than the CCS driver.
 That's because it does individual pin i/o rather than byte-wide i/o,
 and because it uses standard i/o mode.
 
 
 Why use it ?
 
 1.  If you decide to add LCD support to a board and the only available
 pins are spread out over several ports, then this driver can help you.
 
 2.  If you're a newbie and your board isn't configured to use the
 CCS driver, and you don't know how to modify it or Mark's driver,
 then this driver can get you up running quickly.
 
 Choosing i/o pins:
 1.   You must make sure that you choose i/o pins for the data bus
 signals and output pins for the 3 control signals.   On some PICs,
 certain pins are input-only.    Make sure that if you use Pin A4,
 that you put a pull-up resistor on it.     Also,  if you're using an
 analog or a comparator pin, make sure that you use the proper
 CCS function to configure it as a normal i/o pin.
 
 
  	  | Code: |  	  | // flex_lcd.c
 
 // These pins are for the Microchip PicDem2-Plus board,
 // which is what I used to test the driver.  Change these
 // pins to fit your own board.
 
 #define LCD_DB4   PIN_D0
 #define LCD_DB5   PIN_D1
 #define LCD_DB6   PIN_D2
 #define LCD_DB7   PIN_D3
 
 #define LCD_E     PIN_A1
 #define LCD_RS    PIN_A3
 #define LCD_RW    PIN_A2
 
 // If you only want a 6-pin interface to your LCD, then
 // connect the R/W pin on the LCD to ground, and comment
 // out the following line.
 
 #define USE_LCD_RW   1
 
 //========================================
 
 #define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
 #define lcd_line_two 0x40 // LCD RAM address for the 2nd line
 
 
 int8 const LCD_INIT_STRING[4] =
 {
 0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
 0xc,                    // Display on
 1,                      // Clear display
 6                       // Increment cursor
 };
 
 
 //-------------------------------------
 void lcd_send_nibble(int8 nibble)
 {
 // Note:  !! converts an integer expression
 // to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));
 output_bit(LCD_DB7, !!(nibble & 8));
 
 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
 }
 
 //-----------------------------------
 // This sub-routine is only called by lcd_read_byte().
 // It's not a stand-alone routine.  For example, the
 // R/W signal is set high by lcd_read_byte() before
 // this routine is called.
 
 #ifdef USE_LCD_RW
 int8 lcd_read_nibble(void)
 {
 int8 retval;
 // Create bit variables so that we can easily set
 // individual bits in the retval variable.
 #bit retval_0 = retval.0
 #bit retval_1 = retval.1
 #bit retval_2 = retval.2
 #bit retval_3 = retval.3
 
 retval = 0;
 
 output_high(LCD_E);
 delay_cycles(1);
 
 retval_0 = input(LCD_DB4);
 retval_1 = input(LCD_DB5);
 retval_2 = input(LCD_DB6);
 retval_3 = input(LCD_DB7);
 
 output_low(LCD_E);
 
 return(retval);
 }
 #endif
 
 //---------------------------------------
 // Read a byte from the LCD and return it.
 
 #ifdef USE_LCD_RW
 int8 lcd_read_byte(void)
 {
 int8 low;
 int8 high;
 
 output_high(LCD_RW);
 delay_cycles(1);
 
 high = lcd_read_nibble();
 
 low = lcd_read_nibble();
 
 return( (high<<4) | low);
 }
 #endif
 
 //----------------------------------------
 // Send a byte to the LCD.
 void lcd_send_byte(int8 address, int8 n)
 {
 output_low(LCD_RS);
 
 #ifdef USE_LCD_RW
 while(bit_test(lcd_read_byte(),7)) ;
 #else
 delay_us(60);
 #endif
 
 if(address)
 output_high(LCD_RS);
 else
 output_low(LCD_RS);
 
 delay_cycles(1);
 
 #ifdef USE_LCD_RW
 output_low(LCD_RW);
 delay_cycles(1);
 #endif
 
 output_low(LCD_E);
 
 lcd_send_nibble(n >> 4);
 lcd_send_nibble(n & 0xf);
 }
 
 //----------------------------
 void lcd_init(void)
 {
 int8 i;
 
 output_low(LCD_RS);
 
 #ifdef USE_LCD_RW
 output_low(LCD_RW);
 #endif
 
 output_low(LCD_E);
 
 delay_ms(15);
 
 for(i=0 ;i < 3; i++)
 {
 lcd_send_nibble(0x03);
 delay_ms(5);
 }
 
 lcd_send_nibble(0x02);
 
 for(i=0; i < sizeof(LCD_INIT_STRING); i++)
 {
 lcd_send_byte(0, LCD_INIT_STRING[i]);
 
 // If the R/W signal is not used, then
 // the busy bit can't be polled.  One of
 // the init commands takes longer than
 // the hard-coded delay of 60 us, so in
 // that case, lets just do a 5 ms delay
 // after all four of them.
 #ifndef USE_LCD_RW
 delay_ms(5);
 #endif
 }
 
 }
 
 //----------------------------
 
 void lcd_gotoxy(int8 x, int8 y)
 {
 int8 address;
 
 if(y != 1)
 address = lcd_line_two;
 else
 address=0;
 
 address += x-1;
 lcd_send_byte(0, 0x80 | address);
 }
 
 //-----------------------------
 void lcd_putc(char c)
 {
 switch(c)
 {
 case '\f':
 lcd_send_byte(0,1);
 delay_ms(2);
 break;
 
 case '\n':
 lcd_gotoxy(1,2);
 break;
 
 case '\b':
 lcd_send_byte(0,0x10);
 break;
 
 default:
 lcd_send_byte(1,c);
 break;
 }
 }
 
 //------------------------------
 #ifdef USE_LCD_RW
 char lcd_getc(int8 x, int8 y)
 {
 char value;
 
 lcd_gotoxy(x,y);
 
 // Wait until busy flag is low.
 while(bit_test(lcd_read_byte(),7));
 
 output_high(LCD_RS);
 value = lcd_read_byte();
 output_low(lcd_RS);
 
 return(value);
 }
 #endif
 | 
 
 Here's a test program for the Flex driver:
 
  	  | Code: |  	  | #include <16F877.H>
 #fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
 #use delay(clock = 4000000)
 
 #include "flex_lcd.c"
 
 //==========================
 void main()
 {
 lcd_init();  // Always call this first.
 
 lcd_putc("\fHello World\n");
 lcd_putc("Line Number 2");
 
 while(1);
 }
 
 | 
 
 Note:
 If you have the new "Rohs Update" version of the Microchip PicDem2-Plus
 board, you will need to make some changes to make it work with the
 Flex driver.  That's because the new version of the board has an LCD
 power on/off control pin.  Also, the LCD busy bit doesn't work, so you
 must configure the driver so it doesn't use the R/W pin.
 See the following post for the required changes:
 http://www.ccsinfo.com/forum/viewtopic.php?t=24661&start=51
 
 -----------
 1.Edited to add a link to the 20x4 driver.
 2. Edited to add a test program for the Flex driver, and a link to the 16x1
 driver. Also added a note about the "Rohs update" PicDem2-Plus board.
 
 
 Last edited by PCM programmer on Sun Aug 26, 2007 3:20 pm; edited 3 times in total
 |  |  
		|  |  
		| jruibarroso 
 
 
 Joined: 07 Jan 2006
 Posts: 64
 Location: Braga
 
 
			        
 
 | 
			
				|  |  
				|  Posted: Tue Jan 24, 2006 8:37 am |   |  
				| 
 |  
				| hi, I'm actually using this driver you posted and works really fine. I wonder if you can add the necessary code to work on 4 lines LCDs, thank you
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Jan 24, 2006 8:22 pm |   |  
				| 
 |  
				| I don't have a 4-line LCD to test.   But I can modify the driver so that it will very likely work with a 4-line LCD.   Because I can't test it, I don't
 want to post it here (yet).   So I'll send it to you in a PM on Wednesday.
 Look for it in your PM inbox
 ------------
 
 Update:
 I later created a tested, working 20x4 flexible LCD driver.
 It's posted in the CCS Code Library at the following link:
 http://www.ccsinfo.com/forum/viewtopic.php?t=28268
 
 
 
 ------
 Edited to add a link to the 20x4 driver.
 
 Last edited by PCM programmer on Wed Jan 31, 2007 1:08 pm; edited 1 time in total
 |  |  
		|  |  
		| The Puma 
 
 
 Joined: 23 Apr 2004
 Posts: 227
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Jan 25, 2006 3:55 pm |   |  
				| 
 |  
				|  	  | PCM programmer wrote: |  	  | I don't have a 4-line LCD to test.   But I can modify the driver so that it will very likely work with a 4-line LCD.   Because I can't test it, I don't
 want to post it here (yet).   So I'll send it to you in a PM on Wednesday.
 Look for it in your PM inbox
 | 
 Can you send me also this driver please
 |  |  
		|  |  
		| specialk 
 
 
 Joined: 12 Nov 2005
 Posts: 27
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Jan 25, 2006 6:53 pm |   |  
				| 
 |  
				| Just change this: 
  	  | Code: |  	  | void lcd_gotoxy(int8 x, int8 y) {
 int8 address;
 
 if(y != 1)
 address = lcd_line_two;
 else
 address=0;
 
 address += x-1;
 lcd_send_byte(0, 0x80 | address);
 }
 | 
 to this:
 
  	  | Code: |  	  | void lcd_gotoxy( BYTE x, BYTE y) { BYTE address;
 
 switch(y) {
 case 1 : address=0x80;break;
 case 2 : address=0xc0;break;
 case 3 : address=0x94;break;
 case 4 : address=0xd4;break;
 }
 address+=x-1;
 lcd_send_byte(0,address);
 }
 | 
 
 -special [k]
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Jan 25, 2006 7:29 pm |   |  
				| 
 |  
				| That's not sufficient.   The LCD420.C file has a "lcdline" variable which must be added to my driver, and the "case '\n'" statement
 must be modified to increment that variable.   Also, CCS doesn't
 initialize "lcdline" to 1, so that should be done.
 
 As I said, I did not post the modified driver because I haven't tested it
 in hardware.
 
 I'm not going to PM any more copies of the modified driver.
 The two people who requested it have not even looked in their PM
 boxes yet.
 
 If you want to post a driver for them, go ahead.
 |  |  
		|  |  
		| The Puma 
 
 
 Joined: 23 Apr 2004
 Posts: 227
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jan 26, 2006 10:45 am |   |  
				| 
 |  
				| @PCM programmer 
 Thx PCM for the driver,
 i will post the result later this week
 |  |  
		|  |  
		| sonicdeejay 
 
 
 Joined: 20 Dec 2005
 Posts: 112
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 03, 2006 8:24 am |   |  
				| 
 |  
				| dear PCM programmer, 
 will the driver works on 2x20 matrix with Hitachi's LCD HD44780 module???
 
 
 
 this code has to be insert in my main program  or  call as #include(flexlcd.c) ????
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 03, 2006 9:50 am |   |  
				| 
 |  
				|  	  | Quote: |  	  | will the driver works on 2x20 matrix with Hitachi's LCD HD44780 module??? | 
 It should work.
 
 
 
  	  | Quote: |  	  | this code has to be insert in my main program or call as #include(flexlcd.c) ???? | 
 Yes, use #include.
 |  |  
		|  |  
		| sonicdeejay 
 
 
 Joined: 20 Dec 2005
 Posts: 112
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 03, 2006 12:57 pm |   |  
				| 
 |  
				| Since my PIC18F2525 is used port B for LCD,I change this in the driver code,,, 
 
 
  	  | Code: |  	  | #define LCD_DB4   PIN_B0 #define LCD_DB5  PIN_B1
 #define LCD_DB6  PIN_B2
 #define LCD_DB7  PIN_B3
 
 #define LCD_E     PIN_A1
 #define LCD_RS    PIN_A3
 #define LCD_RW    PIN_A2
 | 
 
 
 
 and when I run this driver in my following sample code....
 
 
  	  | Code: |  	  | #include <18F2525.h> 
 #include <flex_lcd.c>
 
 
 #device ICD=TRUE
 #device ADC=10
 #fuses HS,NOWDT,NOPROTECT,NOLVP
 #use delay(clock=16000000) // 16Mhz Crystal is Used
 #use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)  // RS232 Configuration
 
 
 
 #include <stdlib.h>
 
 
 void main()
 
 {
 
 
 
 lcd_init();
 
 while(1)
 {
 output_high(PIN_A1);
 delay_ms(1000);
 output_low(PIN_A1);
 
 printf(lcd_putc, "Hello World.");
 
 
 delay_ms(1000);
 }
 }
 | 
 
 
 
 I have this compile error...
 
 
 
  	  | Code: |  	  | delay_us(60);  and error message is" unidentified indentifier delay_us" | 
 
 help me...
 
 sonic
 |  |  
		|  |  
		| The Puma 
 
 
 Joined: 23 Apr 2004
 Posts: 227
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 03, 2006 1:15 pm |   |  
				| 
 |  
				| Can this driver also used for 4x20 lcd's? 
 My evaulation board has the following connection
 enable - RB1
 rs - RB2
 RW - RB3
 D4 - RB4
 D5 - RB5
 D6 - RB6
 D7 - RB7
 
 But i must connect D6 and D7 to another poort pin
 
 This pins did not work together with the ICD2 programmer debugger
 This programmer use also port rb 6 and rb7
 
 Can this lcd driver used for this configuration?
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Feb 03, 2006 1:50 pm |   |  
				| 
 |  
				|  	  | Quote: |  	  | Can this driver also used for 4x20 lcd's? | 
 Didn't I send you the 4x20 driver in a PM ?
 Yes, I sure did.  Here is your reply to me after getting it.
 
  	  | Quote: |  	  | Thx PCM for the driver, i will post the result later this week
 | 
 
 
  	  | Quote: |  	  | Can this lcd driver used for this configuration?
 | 
 Did you read the notes given with the driver ?   The whole
 purpose of this driver is to allow using almost any pin.
 
 If you don't understand this driver, then please use the driver
 provided by CCS.   Use some driver that you understand.
 |  |  
		|  |  
		| Mark 
 
 
 Joined: 07 Sep 2003
 Posts: 2838
 Location: Atlanta, GA
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Sat Feb 04, 2006 12:12 am |   |  
				| 
 |  
				|  	  | sonicdeejay wrote: |  	  | Since my PIC18F2525 is used port B for LCD,I change this in the driver code,,, 
 
 
  	  | Code: |  	  | #define LCD_DB4   PIN_B0 #define LCD_DB5  PIN_B1
 #define LCD_DB6  PIN_B2
 #define LCD_DB7  PIN_B3
 
 #define LCD_E     PIN_A1
 #define LCD_RS    PIN_A3
 #define LCD_RW    PIN_A2
 | 
 
 
 
 and when I run this driver in my following sample code....
 
 
  	  | Code: |  	  | #include <18F2525.h> 
 #include <flex_lcd.c>
 
 
 #device ICD=TRUE
 #device ADC=10
 #fuses HS,NOWDT,NOPROTECT,NOLVP
 #use delay(clock=16000000) // 16Mhz Crystal is Used
 #use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)  // RS232 Configuration
 
 
 
 #include <stdlib.h>
 
 
 void main()
 
 {
 
 
 
 lcd_init();
 
 while(1)
 {
 output_high(PIN_A1);
 delay_ms(1000);
 output_low(PIN_A1);
 
 printf(lcd_putc, "Hello World.");
 
 
 delay_ms(1000);
 }
 }
 | 
 
 
 
 I have this compile error...
 
 
 
  	  | Code: |  	  | delay_us(60);  and error message is" unidentified indentifier delay_us" | 
 
 help me...
 
 sonic
 | 
 
 Put the #include's after the #use RS232.  You have them before the #use delay statement which is causing the problem.
 |  |  
		|  |  
		| The Puma 
 
 
 Joined: 23 Apr 2004
 Posts: 227
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Feb 04, 2006 4:02 am |   |  
				| 
 |  
				| Driver works now for 20x4 lcd 
 But there are some things with the gotoxy command
 
 Can you Update this driver with the following things if possible
 Cursor Blink, Custum caracter And more ....
 |  |  
		|  |  
		| The Puma 
 
 
 Joined: 23 Apr 2004
 Posts: 227
 Location: The Netherlands
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Feb 05, 2006 6:35 am |   |  
				| 
 |  
				| I have modified the driver 
 It use not blink, cursor and custum chars
 Any comments and modifications are welcome
 
 ////////////////////////////////////////////////////////////////////////////
 ////                        FLEX_LCD420.C                               ////
 ////            Driver for common 4x20 LCD modules                      ////
 ////                                                                    ////
 ////  lcd_init()   Must be called before any other function.            ////
 ////                                                                    ////
 ////  lcd_putc(c)  Will display c on the next position of the LCD.      ////
 ////                     The following have special meaning:            ////
 ////                      \f  Clear display                             ////
 ////                      \n  Go to start of second line                ////
 ////                      \b  Move back one position                    ////
 ////							  \c  Cursor on											////
 ////							  \d  Blink character                           ////
 ////							  \1  Custom character DegC                     ////
 ////                                                                    ////
 ////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)     ////
 ////                                                                    ////
 ////  lcd_getc(x,y)   Returns character at position x,y on LCD          ////
 ////                                                                    ////
 ////////////////////////////////////////////////////////////////////////////
 ////        (C) Copyright 1996,1997 Custom Computer Services            ////
 //// This source code may only be used by licensed users of the CCS C   ////
 //// compiler.  This source code may only be distributed to other       ////
 //// licensed users of the CCS C compiler.  No other use, reproduction  ////
 //// or distribution is permitted without written permission.           ////
 //// Derivative programs created using this software in object code     ////
 //// form are not restricted in any way.                                ////
 ////////////////////////////////////////////////////////////////////////////
 
 // These pins are for the PIC development board:
 //     B1  enable
 //     B2  rs
 //     B3  rw
 //     B4  D4
 //     B5  D5
 //     E1  D6
 //     E0  D7
 
 #define LCD_E		PIN_B1
 #define LCD_RS		PIN_B2
 #define LCD_RW		PIN_B3
 #define LCD_DB4	PIN_B4
 #define LCD_DB5	PIN_B5
 #define LCD_DB6	PIN_E1
 #define LCD_DB7	PIN_E0
 
 // Clear and home
 #define LCD_CLR_DISP					0x01	// Clear screen, home cursor, unshift display
 #define LCD_RETURN_HOME				0x02	// Home cursor, unshift display
 
 // Set entry mode: display shift on/off, dec/inc cursor move direction
 #define LCD_ENTRY_DEC            0x04	// Display shift off, dec cursor move dir
 #define LCD_ENTRY_DEC_SHIFT      0x05  // Display shift on,  dec cursor move dir
 #define LCD_ENTRY_INC	         0x06  // Display shift off, inc cursor move dir
 #define LCD_ENTRY_INC_SHIFT      0x07  // Display shift on,  inc cursor move dir
 
 // Display on/off, cursor on/off, blinking char at cursor position
 #define LCD_DISP_OFF             0x08  // Display off
 #define LCD_DISP_ON              0x0C  // Display on, cursor off
 #define LCD_DISP_ON_BLINK        0x0D  // Display on, cursor off, blink char
 #define LCD_DISP_ON_CURSOR       0x0E  // Display on, cursor on
 #define LCD_DISP_ON_CURSOR_BLINK 0x0F  // Display on, cursor on,  blink char
 
 // Move cursor/shift display
 #define LCD_MOVE_CURSOR_LEFT     0x10  // Move cursor left  (decrement)
 #define LCD_MOVE_CURSOR_RIGHT    0x14  // Move cursor right (increment)
 #define LCD_MOVE_DISP_LEFT       0x18  // Shift display left
 #define LCD_MOVE_DISP_RIGHT      0x1C  // Shift display right
 
 // Function set: set interface data length and number of display lines
 #define LCD_FUNCTION_4BIT_1LINE  0x20  // 4-bit interface, single line, 5x7 dots
 #define LCD_FUNCTION_4BIT_2LINES 0x28  // 4-bit interface, dual line,   5x7 dots
 #define LCD_FUNCTION_8BIT_1LINE  0x30  // 8-bit interface, single line, 5x7 dots
 #define LCD_FUNCTION_8BIT_2LINES 0x38  // 8-bit interface, dual line,   5x7 dots
 
 #define LCD_CGRAM_BASE_ADDR		0x40	// Set the CGRAM address
 #define LCD_DDRAM_BASE_ADDR		0x80	// Set the DDRAM address
 
 // Address positions
 #define LCD_LINE_1					0x80	// Position of start of line 1
 #define LCD_LINE_2					0xC0	// Position of start of line 2
 #define LCD_LINE_3					0x94	// Position of start of line 3
 #define LCD_LINE_4					0xD4	// Position of start of line 4
 
 #define LCD_DEGREE_CHAR				0x00  // Ascii 00
 
 #define lcd_type 2							// 0=5x7, 1=5x10, 2=2 lines
 
 BYTE const LCD_INIT_STRING[4] = {
 LCD_FUNCTION_4BIT_2LINES | (lcd_type << 2),  // Set mode: 4-bit, 2 lines, 5x7 dots
 LCD_DISP_ON,
 LCD_CLR_DISP,
 LCD_ENTRY_INC };
 
 BYTE const LCD_CUSTOM_CHARS[] = {
 0x1C,0x14,0x1C,0x00,0x00,0x00,0x00,0x00,		// DegC
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,		// Not used
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,		// Not used
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,		// Not used
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,		// Not used
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,		// Not used
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,		// Not used
 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F };	// Not used
 
 BYTE lcd_line;
 
 BYTE lcd_read_nibble() {
 BYTE retval;
 
 #bit retval_0 = retval.0
 #bit retval_1 = retval.1
 #bit retval_2 = retval.2
 #bit retval_3 = retval.3
 retval = 0;
 output_high(LCD_E);
 delay_cycles(1);
 retval_0 = input(LCD_DB4);
 retval_1 = input(LCD_DB5);
 retval_2 = input(LCD_DB6);
 retval_3 = input(LCD_DB7);
 output_low(LCD_E);
 return(retval);
 }
 
 BYTE lcd_read_byte() {
 BYTE low,high;
 
 output_high(LCD_RW);
 delay_cycles(1);
 high = lcd_read_nibble();
 low = lcd_read_nibble();
 return((high << 4) | low);
 }
 
 void lcd_send_nibble( BYTE n ) {
 output_bit(LCD_DB4, !!(n & 1));
 output_bit(LCD_DB5, !!(n & 2));
 output_bit(LCD_DB6, !!(n & 4));
 output_bit(LCD_DB7, !!(n & 8));
 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
 }
 
 void lcd_send_byte( BYTE address, BYTE n ) {
 output_low(LCD_RS);
 while (bit_test(lcd_read_byte(),7));  // wait until busy flag is low
 if (address)
 output_high(LCD_RS);
 else
 output_low(LCD_RS);
 delay_cycles(1);
 output_low(LCD_RW);
 delay_cycles(1);
 output_low(LCD_E);
 lcd_send_nibble(n >> 4);
 lcd_send_nibble(n & 0xf);
 }
 
 void lcd_init() {
 BYTE i;
 
 lcd_line = 1;
 output_low(LCD_RS);
 output_low(LCD_RW);
 output_low(LCD_E);
 delay_ms(15);
 for (i=1;i<=3;++i) {
 lcd_send_nibble(3);
 delay_ms(5);
 }
 lcd_send_nibble(2);
 for (i=0;i<=sizeof(LCD_INIT_STRING);++i)
 lcd_send_byte(0, LCD_INIT_STRING[i]);
 }
 
 void lcd_init_custom_chars() {
 BYTE i;
 
 lcd_send_byte(0,LCD_CGRAM_BASE_ADDR);
 for (i=0;i<64;i++) {
 lcd_send_byte(1,LCD_CUSTOM_CHARS[i]);
 delay_ms(2);
 }
 }
 
 void lcd_gotoxy( BYTE x, BYTE y ) {
 BYTE address;
 
 switch(y) {
 case 1 : address=LCD_LINE_1; break;
 case 2 : address=LCD_LINE_2; break;
 case 3 : address=LCD_LINE_3; break;
 case 4 : address=LCD_LINE_4; break;
 }
 address+=x-1;
 lcd_send_byte(0,0x80 | address);
 }
 
 void lcd_putc( char c ) {
 switch(c) {
 case '\f'	: lcd_send_byte(0,LCD_CLR_DISP);
 lcd_line=1;
 delay_ms(2); break;
 case '\n'	: lcd_gotoxy(1,++lcd_line); break;
 case '\b'	: lcd_send_byte(0,LCD_MOVE_CURSOR_LEFT); break;
 case '\c'	: lcd_send_byte(0,LCD_DISP_ON_CURSOR); break;
 case '\d'	: lcd_send_byte(0,LCD_DISP_ON_BLINK); break;
 case '\1'	: lcd_send_byte(1,LCD_DEGREE_CHAR); break;
 default		: lcd_send_byte(1,c); break;
 }
 }
 
 char lcd_getc( BYTE x, BYTE y ) {
 char value;
 
 lcd_gotoxy(x,y);
 while (bit_test(lcd_read_byte(),7));  // wait until busy flag is low
 output_high(LCD_RS);
 value = lcd_read_byte();
 output_low(LCD_RS);
 return(value);
 }
 |  |  
		|  |  
		|  |  
  
	| 
 
 | You cannot post new topics in this forum You cannot reply to topics in this forum
 You cannot edit your posts in this forum
 You cannot delete your posts in this forum
 You cannot vote in polls in this forum
 
 |  
 Powered by phpBB © 2001, 2005 phpBB Group
 
 |