1
TFTs / White Screen 2.4 TFT with 8 bit AVR
« on: February 16, 2017, 09:01:30 PM »
Hello All!
I’ve been trying to make the LCD work for over a month now. When I run the code, I can see the screen is being initialized but nothing is drawn to the screen. All I see is a white screen. How can I make it display colors or anything?
Also, I’m an experienced Java developer but I’m also new to C and embedded development so excuse me if my code is not optimized.
Moreover, I’ve looked at similar support requests in this site but they tend to be about ARM processors which I’m NOT using.
Wiring Diagram:

The yellow triangles mean 3.2 volts. And the red triangles mean 5 volts.
Power Source Schematic

This is what it’s used to power the project. The 5 volts come from the avr programmer connected to my computer through the usb port. The 3.2 volts come from the voltage divider that I placed on the breadboard. Pretty simple.
Bill or Parts:
LCD NHD-2.4-240320 CF-CTXI#-F 01/16 (http://www.newhavendisplay.com/nhd24240320cfctxif-p-8176.html)
AVR atmega644p (http://www.atmel.com/devices/atmega644p.aspx)
AVR Programmer (www.sparkfun.com/products/9825)
3.9-kohm Resistor
2.2-kohm Resistor
Miscellaneous:
NHD-FFC40 40 Pin LCD Connector (http://www.newhavendisplay.com/nhdffc40-p-1155.html)
A 30 Rows Breadboard
A 63 Rows Breadboard
Many Jumper wires
Software:
Atmel Studio 7
AVR dude
Pin Out:
MCU LCD
Pin Name Pin Name
22 PC0 22 DB8
26 PC4 23 DB9
23 PC1 24 DB10
27 PC5 25 DB11
24 PC2 26 DB12
28 PC6 27 DB13
25 PC3 28 DB14
29 PC7 29 DB15
These pins are easier to manipulate on the breadboard when connected like this. It is a bit harder to read, I know.
20 PD6 11 D/C
14 PD0 12 /WR
15 PD1 13 /RD
16 PD2 30 /RES
Power Source with LCD
Pin Name
1 GND
7 VDD
8 IOVDD
10 /CS tie to GND
31 IM0 VDD
33 GND
34 LED-K1 Backlight Cathode (Ground)
35 LED-K2 Backlight Cathode (Ground)
36 LED-K3 Backlight Cathode (Ground)
37 LED-K4 Backlight Cathode (Ground)
38 LED-A Backlight Anode (3.1V)
39 GND Ground
Code:
I’ve been trying to make the LCD work for over a month now. When I run the code, I can see the screen is being initialized but nothing is drawn to the screen. All I see is a white screen. How can I make it display colors or anything?
Also, I’m an experienced Java developer but I’m also new to C and embedded development so excuse me if my code is not optimized.
Moreover, I’ve looked at similar support requests in this site but they tend to be about ARM processors which I’m NOT using.
Wiring Diagram:

The yellow triangles mean 3.2 volts. And the red triangles mean 5 volts.
Power Source Schematic

This is what it’s used to power the project. The 5 volts come from the avr programmer connected to my computer through the usb port. The 3.2 volts come from the voltage divider that I placed on the breadboard. Pretty simple.
Bill or Parts:
LCD NHD-2.4-240320 CF-CTXI#-F 01/16 (http://www.newhavendisplay.com/nhd24240320cfctxif-p-8176.html)
AVR atmega644p (http://www.atmel.com/devices/atmega644p.aspx)
AVR Programmer (www.sparkfun.com/products/9825)
3.9-kohm Resistor
2.2-kohm Resistor
Miscellaneous:
NHD-FFC40 40 Pin LCD Connector (http://www.newhavendisplay.com/nhdffc40-p-1155.html)
A 30 Rows Breadboard
A 63 Rows Breadboard
Many Jumper wires
Software:
Atmel Studio 7
AVR dude
Pin Out:
MCU LCD
Pin Name Pin Name
22 PC0 22 DB8
26 PC4 23 DB9
23 PC1 24 DB10
27 PC5 25 DB11
24 PC2 26 DB12
28 PC6 27 DB13
25 PC3 28 DB14
29 PC7 29 DB15
These pins are easier to manipulate on the breadboard when connected like this. It is a bit harder to read, I know.
20 PD6 11 D/C
14 PD0 12 /WR
15 PD1 13 /RD
16 PD2 30 /RES
Power Source with LCD
Pin Name
1 GND
7 VDD
8 IOVDD
10 /CS tie to GND
31 IM0 VDD
33 GND
34 LED-K1 Backlight Cathode (Ground)
35 LED-K2 Backlight Cathode (Ground)
36 LED-K3 Backlight Cathode (Ground)
37 LED-K4 Backlight Cathode (Ground)
38 LED-A Backlight Anode (3.1V)
39 GND Ground
Code:
Code: [Select]
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
// LCD interface (should agree with the diagram above)
// make sure that the LCD RW pin is connected to GND
#define lcd_C7_port PORTC // lcd D7 connection
#define lcd_C7_bit PORTC7
#define lcd_C7_ddr DDRC
#define lcd_C6_port PORTC // lcd D6 connection
#define lcd_C6_bit PORTC6
#define lcd_C6_ddr DDRC
#define lcd_C5_port PORTC // lcd D5 connection
#define lcd_C5_bit PORTC5
#define lcd_C5_ddr DDRC
#define lcd_C4_port PORTC // lcd D4 connection
#define lcd_C4_bit PORTC4
#define lcd_C4_ddr DDRC
#define lcd_C3_port PORTC // lcd D3 connection
#define lcd_C3_bit PORTC3
#define lcd_C3_ddr DDRC
#define lcd_C2_port PORTC // lcd D2 connection
#define lcd_C2_bit PORTC2
#define lcd_C2_ddr DDRC
#define lcd_C1_port PORTC // lcd D1 connection
#define lcd_C1_bit PORTC1
#define lcd_C1_ddr DDRC
#define lcd_C0_port PORTC // lcd D0 connection
#define lcd_C0_bit PORTC0
#define lcd_C0_ddr DDRC
#define lcd_RS_port PORTD // lcd Register Select pin
#define lcd_RS_bit PORTD6
#define lcd_RS_ddr DDRD
#define lcd_WR_port PORTD // lcd Write pin
#define lcd_WR_bit PORTD0
#define lcd_WR_ddr DDRD
#define lcd_RD_port PORTD // lcd Read pin
#define lcd_RD_bit PORTD1
#define lcd_RD_ddr DDRD
#define lcd_RES_port PORTD // lcd Reset pin
#define lcd_RES_bit PORTD2
#define lcd_RES_ddr DDRD
// Function Prototypes
void lcd_write_8(uint8_t);
void lcd_write_command_8d(uint8_t);
void lcd_write_data_8d(uint8_t);
void lcd_init_8d(void);
void display_picture(void);
/******************************* Main Program Code *************************/
int main(void)
{
// configure the microprocessor pins for the data lines
lcd_C7_ddr |= (1<<lcd_C7_bit); // 8 data lines - output
lcd_C6_ddr |= (1<<lcd_C6_bit);
lcd_C5_ddr |= (1<<lcd_C5_bit);
lcd_C4_ddr |= (1<<lcd_C4_bit);
lcd_C3_ddr |= (1<<lcd_C3_bit);
lcd_C2_ddr |= (1<<lcd_C2_bit);
lcd_C1_ddr |= (1<<lcd_C1_bit);
lcd_C0_ddr |= (1<<lcd_C0_bit);
// configure the microprocessor pins for the control lines
lcd_RS_ddr |= (1<<lcd_RS_bit); // RS line - output
lcd_WR_ddr |= (1<<lcd_WR_bit); // WR line - output
lcd_RD_ddr |= (1<<lcd_RD_bit); // RD line - output
lcd_RES_ddr |= (1<<lcd_RES_bit); // RES line - output
// initialize the LCD controller as determined by the defines (LCD instructions)
lcd_init_8d(); // initialize the LCD display for an 8-bit interface
// endless loop
while(1)
{
display_picture();
};
return 0;
}
/******************************* End of Main Program Code ******************/
/*============================== 8-bit LCD Functions ======================*/
/*
Name: lcd_init_8d
Purpose: initialize the LCD module for a 8-bit data interface
Entry: equates (LCD instructions) set up for the desired operation
Exit: no parameters
Notes: uses time delays rather than checking the busy flag
*/
void lcd_init_8d(void)
{
lcd_write_command_8d(0x0000);
_delay_ms(250);
lcd_write_command_8d(0x0001);
_delay_ms(250);
// Power-up delay
_delay_ms(100); // initial 40 mSec delay
lcd_write_command_8d(0x0028);//display OFF
lcd_write_command_8d(0x0011);
lcd_write_data_8d(0x0000); //exit SLEEP mode
lcd_write_command_8d(0x0036);
lcd_write_data_8d(0x0080);//MADCTL: memory data access control
//TRY ONE OF THE THREE
lcd_write_command_8d(0x003A);lcd_write_data_8d(0x0066);//COLMOD: Interface Pixel format *** I use 262K-colors in 18bit/pixel format when using 8-bit interface to allow 3-bytes per pixel
//lcd_write_command_8d(0x003A);lcd_write_data_8d(0x0055);//COLMOD: Interface Pixel format *** I use 65K-colors in 16bit/pixel (5-6-5) format when using 16-bit interface to allow 1-byte per pixel
//lcd_write_command_8d(0x003A);lcd_write_data_8d(0x0006); //Interface pixel format: 8-bit 8080 mode, 3bytes per pixel
lcd_write_command_8d(0x00B2);
lcd_write_data_8d(0x000C);
lcd_write_data_8d(0x0C);
lcd_write_data_8d(0x00);
lcd_write_data_8d(0x33);
lcd_write_data_8d(0x33);//PORCTRK: Porch setting
lcd_write_command_8d(0x00B7);
lcd_write_data_8d(0x0035);//GCTRL: Gate Control
lcd_write_command_8d(0x00BB);
lcd_write_data_8d(0x002B);//VCOMS: VCOM setting
lcd_write_command_8d(0x00C0);
lcd_write_data_8d(0x002C);//LCMCTRL: LCM Control
lcd_write_command_8d(0x00C2);
lcd_write_data_8d(0x0001);
lcd_write_data_8d(0xFF);//VDVVRHEN: VDV and VRH Command Enable
lcd_write_command_8d(0x00C3);
lcd_write_data_8d(0x0011);//VRHS: VRH Set
lcd_write_command_8d(0x00C4);
lcd_write_data_8d(0x0020);//VDVS: VDV Set
lcd_write_command_8d(0x00C6);
lcd_write_data_8d(0x000F);//FRCTRL2: Frame Rate control in normal mode
lcd_write_command_8d(0x00D0);
lcd_write_data_8d(0x00A4);
lcd_write_data_8d(0xA1);//PWCTRL1: Power Control 1
lcd_write_command_8d(0x00E0);
lcd_write_data_8d(0x00D0);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x0005);
lcd_write_data_8d(0x000E);
lcd_write_data_8d(0x0015);
lcd_write_data_8d(0x000D);
lcd_write_data_8d(0x0037);
lcd_write_data_8d(0x0043);
lcd_write_data_8d(0x0047);
lcd_write_data_8d(0x0009);
lcd_write_data_8d(0x0015);
lcd_write_data_8d(0x0012);
lcd_write_data_8d(0x0016);
lcd_write_data_8d(0x0019);//PVGAMCTRL: Positive Voltage Gamma control
lcd_write_command_8d(0x00E1);
lcd_write_data_8d(0x00D0);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x0005);
lcd_write_data_8d(0x000D);
lcd_write_data_8d(0x000C);
lcd_write_data_8d(0x0006);
lcd_write_data_8d(0x002D);
lcd_write_data_8d(0x0044);
lcd_write_data_8d(0x0040);
lcd_write_data_8d(0x000E);
lcd_write_data_8d(0x001C);
lcd_write_data_8d(0x0018);
lcd_write_data_8d(0x0016);
lcd_write_data_8d(0x0019);//NVGAMCTRL: Negative Voltage Gamma control
lcd_write_command_8d(0x002A);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x00EF);//X address set
lcd_write_command_8d(0x002B);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x0000);
lcd_write_data_8d(0x0001);
lcd_write_data_8d(0x003F);//Y address set
lcd_write_command_8d(0x0029); //display ON
_delay_ms(100);
}
/*...........................................................................
Name: lcd_write_character_8d
Purpose: send a byte of information to the LCD data register
Entry: (theData) is the information to be sent to the data register
Exit: no parameters
Notes: does not deal with RW (busy flag is not implemented)
*/
void lcd_write_data_8d(uint8_t theData)
{
lcd_write_8(theData); // write the data
lcd_RS_port |= (1<<lcd_RS_bit); // select the Data Register (RS high)
lcd_WR_port &= ~(1<<lcd_WR_bit); // make sure WR is initially low
_delay_ms(1);
lcd_WR_port |= (1<<lcd_WR_bit); // WR High
}
/*...........................................................................
Name: lcd_write_instruction_8d
Purpose: send a byte of information to the LCD instruction register
Entry: (theInstruction) is the information to be sent to the instruction register
Exit: no parameters
Notes: does not deal with RW (busy flag is not implemented)
*/
void lcd_write_command_8d(uint8_t theCommand)
{
lcd_RS_port &= ~(1<<lcd_RS_bit); // select the Instruction Register (RS low)
lcd_RD_port |= (1<<lcd_RD_bit); // RD High
lcd_WR_port &= ~(1<<lcd_WR_bit); // make sure WR is initially low
lcd_write_8(theCommand); // write the instruction
_delay_ms(10);
lcd_WR_port |= (1<<lcd_WR_bit); // WR High
_delay_ms(1);
}
/*...........................................................................
Name: lcd_write_8
Purpose: send a byte of information to the LCD module
Entry: (theByte) is the information to be sent to the desired LCD register
RS is configured for the desired LCD register
E is low
RW is low
Exit: no parameters
Notes: use either time delays or the busy flag
*/
void lcd_write_8(uint8_t theByte)
{
lcd_C7_port &= ~(1<<lcd_C7_bit); // assume that data is '0'
if (theByte & 1<<7) lcd_C7_port |= (1<<lcd_C7_bit); // make data = '1' if necessary
lcd_C6_port &= ~(1<<lcd_C6_bit); // repeat for each data bit
if (theByte & 1<<6) lcd_C6_port |= (1<<lcd_C6_bit);
lcd_C5_port &= ~(1<<lcd_C5_bit);
if (theByte & 1<<5) lcd_C5_port |= (1<<lcd_C5_bit);
lcd_C4_port &= ~(1<<lcd_C4_bit);
if (theByte & 1<<4) lcd_C4_port |= (1<<lcd_C4_bit);
lcd_C3_port &= ~(1<<lcd_C3_bit);
if (theByte & 1<<3) lcd_C3_port |= (1<<lcd_C3_bit);
lcd_C2_port &= ~(1<<lcd_C2_bit);
if (theByte & 1<<2) lcd_C2_port |= (1<<lcd_C2_bit);
lcd_C1_port &= ~(1<<lcd_C1_bit);
if (theByte & 1<<1) lcd_C1_port |= (1<<lcd_C1_bit);
lcd_C0_port &= ~(1<<lcd_C0_bit);
if (theByte & 1<<0) lcd_C0_port |= (1<<lcd_C0_bit);
}
void display_picture(void)
{
int i;
lcd_write_command_8d(0x002C); //Memory write
for(i=0;i<(128*40);i++) //Write 40 Lines
{
lcd_write_data_8d(0x00FF); //Red
lcd_write_data_8d(0x0000); //Green
lcd_write_data_8d(0x0000); //Blue
}
for(i=0;i<(128*40);i++) //Write 40 Lines
{
lcd_write_data_8d(0x0000); //Red
lcd_write_data_8d(0x00FF); //Green
lcd_write_data_8d(0x0000); //Blue
}
for(i=0;i<(128*40);i++) //Write 40 Lines
{
lcd_write_data_8d(0x0000); //Red
lcd_write_data_8d(0x0000); //Green
lcd_write_data_8d(0x00FF); //Blue
}
for(i=0;i<(128*40);i++) //Write 40 Lines
{
lcd_write_data_8d(0x00FF); //Red
lcd_write_data_8d(0x00FF); //Green
lcd_write_data_8d(0x00FF); //Blue
}
}