I have studied the HD44780 and PCF8574 datasheets and compared them to Darell's code and found as expected that his code follows the datasheets precisely. I compared the code
with Darrel's and noticed the I2C_SLOW definition is not included in his code. I then looked at I2CWRITE in the manual and noticed that PAUSE 10 is used to allow time for the transfer to complete again this is not included in Darrel's code.Code:DEFINE OSC 40 ' 10 MHz XTAL AND X 4 INTERNAL PLL DEFINE I2C_SLOW 1 C VAR portd.3 ' S_CLOCK D VAR portd.2 ' S_DATA ADDR VAR BYTE ADDR = %01001110 ' dec 78 , hex 4E CMD VAR BYTE LCD_CMD VAR BYTE E VAR LCD_CMD.BIT2 RS VAR LCD_CMD.BIT0 E=0:RS=0 LCD_CMD = 0 PAUSE 1000 MAIN: I2CWRITE D, C, ADDR, [%00000000] ' bck_lt= off PAUSE 200 I2CWRITE D, C, ADDR, [%00001000] ' bck_lt=on PAUSE 200 GOTO MAIN
What does this indicate is the question?
I compared PBP2.5 and pbp3 manuals and the I2CWRITE instruction is the same. I wondered if the pause in PBP3 is not needed as the compiler takes care of the I2C being busy.
One step at a time.
First remove the I2C_SLOW and test
Then add pause 10 delaysCode:DEFINE OSC 40 ' 10 MHz XTAL AND X 4 INTERNAL PLL 'DEFINE I2C_SLOW 1 SDA VAR PORTD.2 ; I2C Data pin SCL VAR PORTD.3 ; I2C Clock Pin LCD_Addr CON 78 'LCD_BuffSize CON 30 'LCD_Buff VAR BYTE[LCD_BuffSize] 'LCD_BuffAddr CON EXT : @LCD_BuffAddr = _LCD_Buff 'LCD_BuffLen VAR WORD ; Length of data in buffer LCD_Data VAR BYTE ; Data to Send to LCD LCD_Byte VAR BYTE ; Nibbles to Send LCD_RS VAR LCD_Byte.0 ; Register Select bit LCD_RW VAR LCD_Byte.1 ; Read/Write bit LCD_E VAR LCD_Byte.2 ; Enable bit LCD_BackLight VAR LCD_Byte.3 ; Backlight 0=ON LCD_WriteMode VAR BYTE ; 1=LowNibble, 2=HighNibble, 3=Both LCD_CommandMode VAR BIT ; Indicates next byte is a command LCD_Byte2 VAR BYTE ; Same nibble without E bit LCD_Idx VAR BYTE testmode var byte ;----[Initialize the LCD]------------------------------------------------------- PAUSE 250 ; LCD Power-on delay LCD_Backlight = 1 ; Backlight OFF LCD_RW = 0 ; Write to LCD LCD_RS = 0 ; Command Register LCD_WriteMode = 1 ;-- Low Nibbles only LCD_Data = 3 ; Reset 3 times gosub LCD_Write_ PAUSEUS 6000 gosub LCD_Write_ PAUSEUS 1000 gosub LCD_Write_ PAUSEUS 1000 LCD_Data = 2 ; Start 4-bit mode gosub LCD_Write_ PAUSEUS 1000 LCD_WriteMode = 3 ;-- Both Nibbles LCD_Data = $28 gosub LCD_Write_ ; Function Set, 4-bit, 2-line, 5x7 LCD_Data = $0C gosub LCD_Write_ ; Display ON LCD_Data = $01 gosub LCD_Write_ ; Clear Screen PAUSE 2 LCD_Data = $06 gosub LCD_Write_ ; Entry Mode PAUSE 2 ; Let command finish LCD_RS = 1 ' this is data goto main LCD_WRITE_: LCD_E = 1 IF LCD_WriteMode.1 = 1 THEN ; Write High Nibble LCD_Byte = (LCD_Byte & $0F) | (LCD_Data & $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2] ENDIF IF LCD_WriteMode.0 = 1 THEN ; Write Low Nibble LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2] ENDIF return Main: LCD_Backlight = 0 LCD_Data = "T" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "e" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "s" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "t" gosub LCD_Write_: PAUSEUS 50 pause 500 LCD_Backlight = 1 LCD_Data = "-" gosub LCD_Write_: PAUSEUS 50 pause 500 goto main
and let me know the outcome.Code:DEFINE OSC 40 ' 10 MHz XTAL AND X 4 INTERNAL PLL 'DEFINE I2C_SLOW 1 SDA VAR PORTD.2 ; I2C Data pin SCL VAR PORTD.3 ; I2C Clock Pin LCD_Addr CON 78 'LCD_BuffSize CON 30 'LCD_Buff VAR BYTE[LCD_BuffSize] 'LCD_BuffAddr CON EXT : @LCD_BuffAddr = _LCD_Buff 'LCD_BuffLen VAR WORD ; Length of data in buffer LCD_Data VAR BYTE ; Data to Send to LCD LCD_Byte VAR BYTE ; Nibbles to Send LCD_RS VAR LCD_Byte.0 ; Register Select bit LCD_RW VAR LCD_Byte.1 ; Read/Write bit LCD_E VAR LCD_Byte.2 ; Enable bit LCD_BackLight VAR LCD_Byte.3 ; Backlight 0=ON LCD_WriteMode VAR BYTE ; 1=LowNibble, 2=HighNibble, 3=Both LCD_CommandMode VAR BIT ; Indicates next byte is a command LCD_Byte2 VAR BYTE ; Same nibble without E bit LCD_Idx VAR BYTE testmode var byte ;----[Initialize the LCD]------------------------------------------------------- PAUSE 250 ; LCD Power-on delay LCD_Backlight = 1 ; Backlight OFF LCD_RW = 0 ; Write to LCD LCD_RS = 0 ; Command Register LCD_WriteMode = 1 ;-- Low Nibbles only LCD_Data = 3 ; Reset 3 times gosub LCD_Write_ PAUSEUS 6000 gosub LCD_Write_ PAUSEUS 1000 gosub LCD_Write_ PAUSEUS 1000 LCD_Data = 2 ; Start 4-bit mode gosub LCD_Write_ PAUSEUS 1000 LCD_WriteMode = 3 ;-- Both Nibbles LCD_Data = $28 gosub LCD_Write_ ; Function Set, 4-bit, 2-line, 5x7 LCD_Data = $0C gosub LCD_Write_ ; Display ON LCD_Data = $01 gosub LCD_Write_ ; Clear Screen PAUSE 2 LCD_Data = $06 gosub LCD_Write_ ; Entry Mode PAUSE 2 ; Let command finish LCD_RS = 1 ' this is data goto main LCD_WRITE_: LCD_E = 1 IF LCD_WriteMode.1 = 1 THEN ; Write High Nibble LCD_Byte = (LCD_Byte & $0F) | (LCD_Data & $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte] PAUSE 10 I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte2] PAUSE 10 ENDIF IF LCD_WriteMode.0 = 1 THEN ; Write Low Nibble LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte] PAUSE 10 I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte2] PAUSE 10 ENDIF return Main: LCD_Backlight = 0 LCD_Data = "T" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "e" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "s" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "t" gosub LCD_Write_: PAUSEUS 50 pause 500 LCD_Backlight = 1 LCD_Data = "-" gosub LCD_Write_: PAUSEUS 50 pause 500 goto main
I will continue looking for answers.
Steve Earl www.datageo.co.uk
Hi Steve,
no change using both codes.
I still have no backlight and no text.
I appreciate your assistance on this matter: thanks a lot.
I am not skilled enough to go deeper in those kind of codes ...
Regards,
Ambrogio
Can I make one suggestion?
First connect few led on output of PCF8574, and control them. So you are sure that I2C communication woks.
Second connect LCD to PIC directly, get timing and control right.
Then just combine that two.
Try again
Code:DEFINE OSC 40 ' 10 MHz XTAL AND X 4 INTERNAL PLL DEFINE I2C_SLOW 1 SDA VAR PORTD.2 ; I2C Data pin SCL VAR PORTD.3 ; I2C Clock Pin LCD_Addr CON 78 'LCD_BuffSize CON 30 'LCD_Buff VAR BYTE[LCD_BuffSize] 'LCD_BuffAddr CON EXT : @LCD_BuffAddr = _LCD_Buff 'LCD_BuffLen VAR WORD ; Length of data in buffer LCD_Data VAR BYTE ; Data to Send to LCD LCD_Byte VAR BYTE ; Nibbles to Send LCD_RS VAR LCD_Byte.0 ; Register Select bit LCD_RW VAR LCD_Byte.1 ; Read/Write bit LCD_E VAR LCD_Byte.2 ; Enable bit LCD_BackLight VAR LCD_Byte.3 ; Backlight 0=ON LCD_WriteMode VAR BYTE ; 1=LowNibble, 2=HighNibble, 3=Both LCD_CommandMode VAR BIT ; Indicates next byte is a command LCD_Byte2 VAR BYTE ; Same nibble without E bit LCD_Idx VAR BYTE testmode var byte ;----[Initialize the LCD]------------------------------------------------------- PAUSE 1000 ; LCD Power-on delay LCD_Backlight = 1 ; Backlight OFF LCD_RW = 0 ; Write to LCD LCD_RS = 0 ; Command Register LCD_WriteMode = 1 ;-- Low Nibbles only LCD_Data = 3 ; Reset 3 times gosub LCD_Write PAUSEUS 6000 gosub LCD_Write PAUSEUS 1000 gosub LCD_Write PAUSEUS 1000 LCD_Data = 2 ; Start 4-bit mode gosub LCD_Write PAUSEUS 1000 LCD_WriteMode = 3 ;-- Both Nibbles LCD_Data = $28 gosub LCD_Write ; Function Set, 4-bit, 2-line, 5x7 LCD_Data = $0C gosub LCD_Write ; Display ON LCD_Data = $01 gosub LCD_Write ; Clear Screen PAUSE 2 LCD_Data = $06 gosub LCD_Write ; Entry Mode PAUSE 2 ; Let command finish LCD_RS = 1 ' this is data goto main LCD_WRITE: LCD_E = 1 IF LCD_WriteMode.1 = 1 THEN ; Write High Nibble LCD_Byte = (LCD_Byte & $0F) | (LCD_Data & $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2] ENDIF IF LCD_WriteMode.0 = 1 THEN ; Write Low Nibble LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2] ENDIF return Main: I2CWRITE SDA,SCL, LCD_Addr, [%00000000] ' bck_lt= off PAUSE 200 I2CWRITE SDA,SCL, LCD_Addr, [%00001000] ' bck_lt=on PAUSE 200 LCD_Data = "T" gosub LCD_Write: PAUSEUS 50 LCD_Data = "e" gosub LCD_Write: PAUSEUS 50 LCD_Data = "s" gosub LCD_Write: PAUSEUS 50 LCD_Data = "t" gosub LCD_Write: PAUSEUS 50 LCD_Data = "-" gosub LCD_Write: PAUSEUS 50 pause 500 goto Main
Last edited by EarlyBird2; - 12th July 2014 at 22:24.
Steve Earl www.datageo.co.uk
The problem could be with the delay on power up not being long enough for the LCD to initialise before the PIC starts.
Adjust this line and test
;----[Initialize the LCD]-------------------------------------------------------
PAUSE 1000 ; LCD Power-on delay
and please let me know the result.
Steve Earl www.datageo.co.uk
Dear Steve:
Your suggested test gave me the response on the lack of operation. ( see the attached).
The pcf has P0, P5 and P6 not working. This is the reason of the trouble.
I will no longer buy components on Ebay expecially if chinese. That is very bad.
I have no words to express my state. I want to apologize .
Thanks for the help given to me since the beginning.
Will try to buy another expander board: do you know some reliable seller in Europe ?
Regards,
Ambrogio
No problem and no need to apologise. Could you do some more testing on this board?
Check the voltages on the P0 to P7 pins when this program is running.
If all pins change then the PCF8574 chip is good indicating that the fault is either bad soldering or bad PCB track. It is possible to solder jumper wire direct to pins for a temporary repair.Code:DEFINE OSC 40 ' 10 MHz XTAL AND X 4 INTERNAL PLL DEFINE I2C_SLOW 1 C VAR portd.3 ' S_CLOCK D VAR portd.2 ' S_DATA ADDR VAR BYTE ADDR = %01001110 ' dec 78 , hex 4E CMD VAR BYTE LCD_CMD VAR BYTE E VAR LCD_CMD.BIT2 RS VAR LCD_CMD.BIT0 E=0:RS=0 LCD_CMD = 0 PAUSE 1000 MAIN: I2CWRITE D, C, ADDR, [%00000000] ' port off PAUSE 200 I2CWRITE D, C, ADDR, [%11111111] ' port on PAUSE 200 GOTO MAIN
Steve Earl www.datageo.co.uk
I have tested this code and it works!
Code:DEFINE OSC 40 ' 10 MHz XTAL AND X 4 INTERNAL PLL 'DEFINE I2C_SLOW 1 SDA VAR PORTD.2 ; I2C Data pin SCL VAR PORTD.3 ; I2C Clock Pin LCD_Addr CON 78 'LCD_BuffSize CON 30 'LCD_Buff VAR BYTE[LCD_BuffSize] 'LCD_BuffAddr CON EXT : @LCD_BuffAddr = _LCD_Buff 'LCD_BuffLen VAR WORD ; Length of data in buffer LCD_Data VAR BYTE ; Data to Send to LCD LCD_Byte VAR BYTE ; Nibbles to Send LCD_RS VAR LCD_Byte.0 ; Register Select bit LCD_RW VAR LCD_Byte.1 ; Read/Write bit LCD_E VAR LCD_Byte.2 ; Enable bit LCD_BackLight VAR LCD_Byte.3 ; Backlight 0=ON LCD_WriteMode VAR BYTE ; 1=LowNibble, 2=HighNibble, 3=Both LCD_CommandMode VAR BIT ; Indicates next byte is a command LCD_Byte2 VAR BYTE ; Same nibble without E bit LCD_Idx VAR BYTE testmode var byte ;----[Initialize the LCD]------------------------------------------------------- PAUSE 250 ; LCD Power-on delay LCD_Backlight = 1 ; Backlight OFF LCD_RW = 0 ; Write to LCD LCD_RS = 0 ; Command Register LCD_WriteMode = 1 ;-- Low Nibbles only LCD_Data = 3 ; Reset 3 times gosub LCD_Write_ PAUSEUS 6000 gosub LCD_Write_ PAUSEUS 1000 gosub LCD_Write_ PAUSEUS 1000 LCD_Data = 2 ; Start 4-bit mode gosub LCD_Write_ PAUSEUS 1000 LCD_WriteMode = 3 ;-- Both Nibbles LCD_Data = $28 gosub LCD_Write_ ; Function Set, 4-bit, 2-line, 5x7 LCD_Data = $0C gosub LCD_Write_ ; Display ON LCD_Data = $01 gosub LCD_Write_ ; Clear Screen PAUSE 2 LCD_Data = $06 gosub LCD_Write_ ; Entry Mode PAUSE 2 ; Let command finish LCD_RS = 1 ' this is data goto main LCD_WRITE_: LCD_E = 1 IF LCD_WriteMode.1 = 1 THEN ; Write High Nibble LCD_Byte = (LCD_Byte & $0F) | (LCD_Data & $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2] ENDIF IF LCD_WriteMode.0 = 1 THEN ; Write Low Nibble LCD_Byte = (LCD_Byte & $0F) | ((LCD_Data << 4 )& $F0) LCD_Byte2 = LCD_Byte & $FB I2CWRITE SDA,SCL, LCD_Addr,[LCD_Byte, LCD_Byte2] ENDIF return Main: LCD_Backlight = 0 LCD_Data = "T" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "e" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "s" gosub LCD_Write_: PAUSEUS 50 LCD_Data = "t" gosub LCD_Write_: PAUSEUS 50 pause 500 LCD_Backlight = 1 LCD_Data = "-" gosub LCD_Write_: PAUSEUS 50 pause 500 goto main
Steve Earl www.datageo.co.uk
Bookmarks