Quote Originally Posted by iw2fvo View Post
Steve, very good result !
I think It will help a lot of people too .
I am wait to receive the item ( about 20 days ).
Could you please post the code : I will start to study it .
Thanks
Ambrogio
Here it is. This is a simple test program for PBP2.5 or lower. Anything you do not understand please ask. The next step is to include the command selection inside the LCD_WRITE subroutine.
Code:
'****************************************************************
'*  Name    : I2CLCD.BAS                                                                 
'*  Author  : Steve Earl                                                                                  
'*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS]                     
'*          : All Rights Reserved                                                                         
'*  Date    : 17/07/2014                                                                                
'*  Version : 1.0                                                                                            
'*  Notes   : Serial I2C LCD using PBP 2.5                                                       
'*          : PCF8574T I2C port expander 20x4 LCD         
'****************************************************************

define OSC 40     ' set the correct speed here!!
'DEFINE I2C_SLOW 1
SDA         VAR PORTD.2       ; I2C Data pin
SCL         VAR PORTD.3       ; I2C Clock Pin
LCD_Addr CON 78               ; PCF8574T address

'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 1=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
seconds var byte
minutes var byte
hours   var byte

Init:
;----[Initialize the LCD]-------------------------------------------------------
PAUSE 250                           ; LCD Power-on delay
LCD_Backlight = 1                   ; Backlight On
LCD_RW = 0                          ; Write to LCD
LCD_RS = 0                          ; Command Register

LCD_WriteMode = 1                   ;-- Low Nibbles only
LCD_Data = 3                        ; Software 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 50
LCD_Data = $06 : gosub LCD_Write    ; Entry Mode
PAUSE 2                             ; Let command finish
LCD_RS = 1                          ;Switch to Data 
;Print Static Background to LCD
LCD_Data = " " : gosub LCD_Write    ;Line 1
LCD_Data = " " : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write 
LCD_Data = " " : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write
LCD_Data = "S" : gosub LCD_Write 
LCD_Data = "t" : gosub LCD_Write
LCD_Data = "e" : gosub LCD_Write
LCD_Data = "v" : gosub LCD_Write
LCD_Data = "e" : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write 
LCD_Data = "E" : gosub LCD_Write
LCD_Data = "a" : gosub LCD_Write
LCD_Data = "r" : gosub LCD_Write
LCD_Data = "l" : gosub LCD_Write

lcd_rs = 0                          ;Command is next
lcd_data=$a8 : gosub lcd_write      ;Move to start of line 2
pause 2
lcd_rs = 1                          ;Switch back to Data

LCD_Data = " " : gosub LCD_Write    ;Line 2
LCD_Data = " " : gosub LCD_Write
LCD_Data = "D" : gosub LCD_Write 
LCD_Data = "a" : gosub LCD_Write
LCD_Data = "t" : gosub LCD_Write
LCD_Data = "a" : gosub LCD_Write
LCD_Data = "g" : gosub LCD_Write
LCD_Data = "e" : gosub LCD_Write
LCD_Data = "o" : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write
LCD_Data = "L" : gosub LCD_Write
LCD_Data = "i" : gosub LCD_Write
LCD_Data = "m" : gosub LCD_Write
LCD_Data = "i" : gosub LCD_Write
LCD_Data = "t" : gosub LCD_Write
LCD_Data = "e" : gosub LCD_Write
LCD_Data = "d" : gosub LCD_Write

lcd_rs = 0                          ;Command is next
lcd_data=$99 : gosub lcd_write      ;Move to line 3 col 6 
pause 2
lcd_rs = 1                          ;Switch back to Data

LCD_Data = "*" : gosub LCD_Write    ;Line 3
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write 
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write
LCD_Data = "*" : gosub LCD_Write


lcd_rs = 0                          ;Command is next
lcd_data=$D8 : gosub lcd_write      ;Move to line 4 col 5
pause 2
lcd_rs = 1                          ;Switch back to Data

LCD_Data = "T" : gosub LCD_Write    ;Line 4
LCD_Data = "e" : gosub LCD_Write
LCD_Data = "s" : gosub LCD_Write
LCD_Data = "t" : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write
LCD_Data = "P" : gosub LCD_Write 
LCD_Data = "r" : gosub LCD_Write
LCD_Data = "o" : gosub LCD_Write
LCD_Data = "g" : gosub LCD_Write
LCD_Data = "r" : gosub LCD_Write
LCD_Data = "a" : gosub LCD_Write
LCD_Data = "m" : gosub LCD_Write

pause 5000
lcd_rs = 0                          ;Command is next
lcd_data=$D8 : gosub lcd_write      ;Move to line 4 col 5
pause 2
lcd_rs = 1                          ;Switch back to Data

LCD_Data = " " : gosub LCD_Write    ;Clear line 4 and set clock 
LCD_Data = " " : gosub LCD_Write
LCD_Data = "0" : gosub LCD_Write
LCD_Data = "0" : gosub LCD_Write
LCD_Data = ":" : gosub LCD_Write
LCD_Data = "0" : gosub LCD_Write
LCD_Data = "0" : gosub LCD_Write
LCD_Data = ":" : gosub LCD_Write 
LCD_Data = "0" : gosub LCD_Write
LCD_Data = "0" : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write
LCD_Data = " " : gosub LCD_Write

main:                               ;Count seconds and refresh the clock
for hours = 0 to 23
for minutes = 0 to 59
for seconds = 0 to 59  
lcd_rs = 0                          ;Command is next
lcd_data=$DA : gosub lcd_write      ;Move to line 4 col 7
pause 2
lcd_rs = 1                          ;Switch back to Data

LCD_Data = (hours dig 1)+48 : gosub LCD_Write 
LCD_Data = (hours dig 0)+48 : gosub LCD_Write
LCD_Data = ":" : gosub LCD_Write
LCD_Data = (minutes dig 1)+48 : gosub LCD_Write 
LCD_Data = (minutes dig 0)+48 : gosub LCD_Write
LCD_Data = ":" : gosub LCD_Write
LCD_Data = (seconds dig 1)+48 : gosub LCD_Write 
LCD_Data = (seconds dig 0)+48 : gosub LCD_Write
pause 1000
next    ;second
next    ;minute
next    ;hour
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