
Originally Posted by
EarlyBird2
This works because you can see the backlight turn on and off. This tells me the LCD is working and the address is correct. Unfortunately that has eliminated the obvious. I will dig deeper into Darrel's code as I can not see anything that would stop it working.
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
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
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.
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
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
Then add pause 10 delays
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
and let me know the outcome.
I will continue looking for answers.
Bookmarks