Although there is another thread in this section about this model of COG LCD, I think that starting a new thread is a better option, as the MPU is different.
I've purchased a couple of NHD-C12864B2Z-RN-FBW displays, and connected one of them to a Microchip PIC16LF1936 microcontroller, keeping the second display as a spare unit. Both the display and the PIC microcontroller are powered at 3.3V from a digital, adjustable power supply. Connections have been made following the NHD's datasheet, using 5 x 100nF ceramic capacitors for V0~V4 pins, and 4 x 1uF tantalum capacitors for C1~C3 pins (paying special attention to polarity).
As a starting point, I'm trying to initialize the display (adapting the Example Initialization Program provided by NHD) and then to turn all the display points ON (command 0xA5). But somehow the display seems not to react to any command sent from the PIC, as it is always "clear" (no segments are lighted up). I've double checked all the connections in the proyect board and everything seems to be OK. Also I've checked the signals coming out of the PIC microcontroller using a 4-channel oscilloscope, and both the 8-bit data and the timing between data and /WR signal seem to be OK. The /RD signal is tied to VDD, and the A0 signal is controlled by the PIC, but that line is working OK (always on low-state, as we're writing commands). I've also tried the spare display without success.
FYI, I'm using a NHD-FFC30 board to connect the display to my project board, making sure that the 1# pin on the FFC strip matches the 1# pin on my board.
Here's the code I'm using (compiled with CCS and debugged with MPLAB 8 ). Any advice on how to deal with this situation will be greatly appreciated:
int8 const LCD_INIT_STRING =
0xA2, // 1/9 bias
0XA0, // ADC select, normal
0xC8, // COM output reverse
0xA4, // Display all points normal
0x40, // Display start line set
0x25, // Internal resistor ratio
0x81, // Electronic volume set
0x10, // Electronic volume
0x2F, // Power controller set
0xAF // Display ON
void lcd_send_nibble(int8 nibble)
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB0, !!(nibble & 1));
output_bit(LCD_DB1, !!(nibble & 2));
output_bit(LCD_DB2, !!(nibble & 4));
output_bit(LCD_DB3, !!(nibble & 8));
output_bit(LCD_DB4, !!(nibble & 16));
output_bit(LCD_DB5, !!(nibble & 32));
output_bit(LCD_DB6, !!(nibble & 64));
output_bit(LCD_DB7, !!(nibble & 128));
// This sub-routine is only called by lcd_read_byte().
// 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
#bit retval_4 = retval.4
#bit retval_5 = retval.5
#bit retval_6 = retval.6
#bit retval_7 = retval.7
retval = 0;
retval_0 = input(LCD_DB0);
retval_1 = input(LCD_DB1);
retval_2 = input(LCD_DB2);
retval_3 = input(LCD_DB3);
retval_4 = input(LCD_DB4);
retval_5 = input(LCD_DB5);
retval_6 = input(LCD_DB6);
retval_7 = input(LCD_DB7);
// Read a byte from the LCD and return it.
lectura = lcd_read_nibble();
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
As for the "main":
#use delay(clock = 500000)
#byte OPTION_REG = 0x095
#byte OSCCON = 0x099
#define LCD_DB0 PIN_A0
#define LCD_DB1 PIN_A1
#define LCD_DB2 PIN_A2
#define LCD_DB3 PIN_A3
#define LCD_DB4 PIN_A4
#define LCD_DB5 PIN_A5
#define LCD_DB6 PIN_A6
#define LCD_DB7 PIN_A7
#define LCD_A0 PIN_E2
#define LCD_R PIN_E0
#define LCD_W PIN_E1
OSCCON = 0b0110100;
lcd_init(); // Always call this first.
int i = 0;
Thanks in advance!
I'm assuming your RESET signal is tied to VDD. Can you try using it to issue a hard reset to the LCD before initialization? Similar to this:
digitalWrite( RD_PIN, HIGH ); // aka E - set E to HIGH
digitalWrite( WR_PIN, HIGH ); // aka RW - set RW to HIGH
digitalWrite( RES_PIN, LOW ); // reset pin set LOW
digitalWrite( RES_PIN, HIGH ); // reset pin set HIGH
writeCom( 0xA2 ); // 1/9 bias
writeCom( 0xA0 ); // ADC SELECT NORMAL
writeCom( 0xC0 ); // COM OUTPUT NORMAL
writeCom( 0x25 ); // INTERNAL RESISTOR RATIO
writeCom( 0x81 ); // ELECTRONIC VOLUME MODE SET
writeCom( 0x15 ); // ELECTRONIC VOLUME
writeCom( 0x2F ); // POWER CONTROLLER SET
writeCom( 0x40 ); // DISPLAY START LINE SET
writeCom( 0xAF ); // DISPLAY ON
}Also, can you try using these initialization values and sequence? Please also double check your FFC connection, and if possible, try using 1µF non-polarized caps for all capacitors needed.0
Tried all the proposed solutions, sadly without success... the display doesn't shows anything.
I took these pictures in hope that they will be useful to find a solution:
Here we have the complete assembly. It might look messy but I've checked all the connections and everything is OK.
In this picture you can see the 27-pin FFC strip attached to the 30-pin FFC board (with the retaining lever lifted up for the picture). Notice the three free pins (board pins 28~30) at the right side of the connector.
For the last picture, I took a screenshot with the oscilloscope. This waveform was recorded when sending the "0xA5" instruction (from the "main"). The yellow channel is the /WR signal, and the blue, pink and green channels are the three most significant bits of the instruction (bit 7 ~ bit 5). As far as I can tell, the waveform - and its timing - seems to be OK.
Finally, I've also noticed that when trying to read the "status" from the LCD, it returns ramdom values... seems that something inside the LCD chip is not working as expected.
Hope all these information helps, thanks in advance!!
Thanks for the picture. I believe you have the FFC cable inserted the incorrect way into the FFC30 board. The connector on the board is bottom contact, so you would need to flip the cable.0
Indeed. I've changed the FFC board connection to match the reverse-connected display, and now it works.
Many thanks for your help, I owe you one!
Please sign in to leave a comment.