You also have to init the display differently
see page 10 and 11 for example code to init and send data:
http://www.newhavendisplay.com/specs/NHD-0208AZ-FL-GBW.pdfNote though that technically the 4bit code works, but it's not great.
What I mean is that they still use a full 8 bit port as a variable, so if you have only 4 of the 8 pins of that port connected to the LCD, the code would overwrite the data on the other 4 pins instead of just modifying only the pins connected to lcd.
You can change the code to get individual bits and put them on pins for example something like this
// in a header file h file
#define LCD_RS PORTEbits.RE0
#define LCD_RW PORTEbits.RE1
#define LCD_EN PORTEbits.RE2
// for 4 bit mode (can be on different ports)
#define LCD_DATA0 PORTAbits.RA4
#define LCD_DATA1 PORTAbits.RA5
#define LCD_DATA2 PORTAbits.RA6
#define LCD_DATA3 PORTAbits.RA7
// second lcd_en = 1 is just a delay, to keep LCD_EN =1 for 500ns when clock is 16Mhz
// may want to change this to a function to add a proper delay if running at different frequencies
#define LCD_STROBE() ((LCD_EN = 1),(LCD_EN = 1), (LCD_EN=0))
// in a c file :
// moves the 4bit values into the 4 individual pins (when lcd in 4bit mode) - not the most efficient but it does the job
void lcd_bits(unsigned char data) {
LCD_DATA0 = data & 1;
LCD_DATA1 = (data >> 1) & 1;
LCD_DATA2 = (data >> 2) & 1;
LCD_DATA3 = (data >> 3) & 1;
}
void lcd_write_4bit(unsigned char c) {
LCD_RS = 1;
LCD_RW = 0;
lcd_bits(c >> 4);
LCD_STROBE();
lcd_bits(c );
LCD_STROBE();
LCD_RS = 0;
delay_50us(); // custom delay function i wrote for 16 mhz, you can use your own or you can wait until lcd says it's no longer busy.
}
may find more useful data in controller datasheet (these displays use various chips that clone a hitachi chip,
so command set is same, timings more or less same, but it's good idea to be conservative)
Link:
http://www.newhavendisplay.com/app_notes/ST7066U.pdfSee pages 23-28 for detailed 4bit and 8 bit initialization and sending data info.