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
Printable View
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
Ambrogio,
Any feedback?
If you have no questions then I will post the next improvement which includes the command in the LCD_Write subroutine. I am now looking at using arrays as the next step.
Here it is! including LOOKUP and ARRAYs.
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_Line_1 con $80
LCD_Line_2 con $A8
LCD_Line_3 con $94
LCD_Line_4 con $D4
LCD_BuffSize CON 22
LCD_Buff VAR BYTE[LCD_BuffSize]
'LCD_BuffAddr CON EXT : @LCD_BuffAddr = _LCD_Buff
LCD_BuffLen VAR byte ; 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_buff[0] = $28 ; Function Set, 4-bit, 2-line
LCD_buff[1] = $0C ; Display ON
LCD_buff[2] = $FE
LCD_buff[3] = $06 ; Entry Mode
LCD_buff[4] = $FE
LCD_buff[5] = $01 ; Clear Screen
lcd_bufflen = 6
gosub LCD_Buff_Write
;Print Static Background to LCD
for lcd_idx = 0 to 85
;| | 20 characters
lookup lcd_idx,[" Steve Earl ",_ ;20
$FE,lcd_line_2," Datageo Limited ",_ ;+22 = 42
$FE,lcd_line_3," ********** ",_ ;+22 = 64
$FE,lcd_line_4," 00:00:00 "],lcd_data ;+22 = 86 (0-85)
gosub lcd_write
next
;Set up fixed buffer characters
lcd_bufflen = 10 ;8 characters in clock + $FE + LCD_Line
LCD_buff[0] = $FE ;Command is next
LCD_buff[1] = lcd_line_4 + 6 ;Move to line 4 col 7
LCD_buff[4] = ":" ;Fixed characters
LCD_buff[7] = ":" ; "
main: ;Count seconds and refresh the clock
for hours = 0 to 23
for minutes = 0 to 59
for seconds = 0 to 59
LCD_buff[2] = (hours dig 1)+48
LCD_buff[3] = (hours dig 0)+48
LCD_buff[5] = (minutes dig 1)+48
LCD_buff[6] = (minutes dig 0)+48
LCD_buff[8] = (seconds dig 1)+48
LCD_buff[9]= (seconds dig 0)+48
gosub lcd_buff_write
pause 1000
next ;second
next ;minute
next ;hour
goto main
LCD_WRITE:
if lcd_data = $FE then
lcd_commandMode = 1 ;Next byte Command
lcd_rs = 0 ;Switch to Command Register
else
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
if lcd_commandmode then
lcd_commandmode = 0 ;Reset to data
lcd_rs = 1 ;Switch to Data Register
pause 2
endif
endif
return
Lcd_Buff_Write:
for lcd_idx = 0 to lcd_bufflen - 1
lcd_data=lcd_buff[LCD_idx]
gosub LCD_Write
next
return
Steve,
I am sorry for the delayed reply : I am not at home on those days.
I had a look to your code : it is a good work and I am waiting to check it soon when the hardware is arrived .
Thanks a lot for the assistance.
I think your work will help a lot of people .
Regards,
Ambrogio
I tried using the on board EEPROM by using DATA and READ.
DATA "This is a string",0
but it stores only alternate characters. I was surprised it worked at all but the alternate characters? There has to be a reason for it to work this way.
It looks like this was fixed back in 2010.
http://www.picbasic.co.uk/forum/showthread.php?t=12775
My PBP2.46 is from 2005.
The plot thickens! Here is an extract from this thread http://www.picbasic.co.uk/forum/show...7143#post97143 using DATA with strings and it works.
Ambrogio
After more testing of the DATA command I have come to the conclusion that my very old setup is the cause. I have PBP2.46 and MCSP from ten years ago. Looking at my old code, ten years old, I used WRITE not DATA and I now believe that was because DATA never worked. I wrote a routine just to write to the EEPROM followed by the program fortunately my set up did not overwrite the EEPROM when the PIC was reprogramed, Bruce's FlashLab boards continue to perform flawlessly.
There are three options for the screen setup
1 LOOKUP
2 Embedded string
3 EEPROM
They all work but LOOKUP uses most code space and EEPROM the least.
Steve,
I am very interested in test the programs but I am still waiting to receive the PCF expander.
It will arrive here after my summer holidays. I will let you know.
Thanks for all.
Regards,
Ambrogio
Ciao Ambrogio,
take a look here ... could help!
http://www.protonbasic.co.uk/showthr...ck-on-1602-LCD
Leo
Thanks to all of you in this forum for the assistance.
I am having problem with my healt in this last period of time. I had an important surgery.
I hope to be active again.
Ambrogio
IW2FVO