I’m kicking things off with the recent addition of native support in version 5.83 of the compiler (in my case, for PIC18) for the PCF8574 I/O expander, which allows control of 16x2 and 20x4 LCDs via I2C communication. I'm including an example with the configuration setup and an image showing the result in the simulator.
I have added a function to be able to mix giant numbers on the display.
Code:
' PIC18F46K22 AND Lcd1602_I2C (PCF8574)
' By COS, 2025/04/16, PIC18 OSHONSOFT v5.83
' For simulation only.
' *************************************************************************************
' General configuration
#define CLOCK_FREQUENCY = 64 ' System clock frequency in MHz
#define SINGLE_DECIMAL_PLACES = 1 ' Number of decimal places for floating-point operations
#define STRING_MAX_LENGTH = 30 ' Maximum length for string variables
#define SIMULATION_WAITMS_VALUE = 0
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' Main program
Main:
'**********************************************************************
AllDigital ' Set all pins to digital mode
' Set all ports as input
TRISA = 0xFF ' Set all PORTA pins as input
TRISB = 0xFF ' Set all PORTB pins as input
TRISC = 0xFF ' Set all PORTC pins as input
TRISD = 0xFF ' Set all PORTD pins as input
TRISE = 0xFF ' Set all PORTE pins as input
' ---------------------------------------------------------------------
' Initialize UART at 115200 baud rate (using RC6 for TX and RC7 for RX)
UART1_Init 115200
WaitUs 1 ' Delay for stabilization
' ---------------------------------------------------------------------
' Send initial message through UART
UART1_Write 0x0C ' ASCII control character to clear screen
WaitMs 100 ' Wait for 1 second
UART1_Write "Ready", CrLf ' Send "Ready" message with carriage return and line feed
#define LCD_LINES = 4
#define LCD_CHARS = 20
'#define I2CCLOCK_STRETCH = 10
#define LCD_MODE = lcdPCF8574
#define LCD_SDA = PORTC.4
#define LCD_SCL = PORTC.3
#define LCD_D7 = 7
#define LCD_D6 = 6
#define LCD_D5 = 5
#define LCD_D4 = 4
#define LCD_BL = 3
#define LCD_E = 2
#define LCD_RW = 1
#define LCD_RS = 0
#define LCD_ADDR = 7
WaitMs 50
lcdPCF_BLhigh
WaitMs 50
Lcdinit LcdCurOff
WaitMs 50
Lcdout "LCD 20x4 I2C PCF8574"
Lcdcmdout LcdLine4Home
Lcdout "0123456789-ABCDEFGHI"
WaitMs 500
'WaitMs 500
lcdPCF_BLlow
WaitMs 500
lcdPCF_BLhigh
WaitMs 2000
Lcdcmdout LcdCurOff
Lcd_Out(3, 1, "Load GCRAM.")
'User-defined characters (big number).
Lcddefchar 0, %11111, %11111, %11111, 0, 0, 0, 0, 0 'Top horizontal bar.
Lcd_Out(3, 6, ".")
WaitMs 500
Lcddefchar 1, 0, 0, 0, 0, 0, %11111, %11111, %11111 'Bottom horizontal bar.
Lcddefchar 2, %11111, %11111, %11111, 0, 0, 0, %11111, %11111 'Top and bottom horizontal bar.
Lcd_Out(3, 7, ".")
WaitMs 500
Lcddefchar 3, %11100, %11110, %11110, %11110, %11110, %11110, %11110, %11100 'Left column.
Lcddefchar 4, %00111, %01111, %01111, %01111, %01111, %01111, %01111, %00111 'Right column.
Lcd_Out(3, 8, ".")
WaitMs 500
Lcddefchar 5, 0, 0, 0, 0, 0, %00011, %00111, %01111 'Bottom Right arrow.
Lcddefchar 6, %00011, %00111, %01111, 0, 0, 0, 0, 0 'Top Right arrow.
Lcd_Out(3, 9, ".")
WaitMs 500
Lcddefchar 7, 0, 0, 0, 0, 0, %11000, %11100, %11110 'Bottom Left arrow.
Lcd_Out(3, 10, ".")
WaitMs 500
Lcdcmdout LcdLine3Clear
Dim counter As Integer
counter = 0
While True
LCD_OutBigNum(2, 5, #counter + "ºC")
counter = counter - 1
WaitMs 100
Wend
End
'Function Lcd_Out(line, Xpos, String_Value)
Function Lcd_Out(Line As Byte, Xpos As Byte, txt[20] As String) As Bit
Lcd_PosXY(Xpos, Line)
Lcdout txt
End Function
'Function Lcd_PosXY(Xpos, Line)
Function Lcd_PosXY(Xpos As Byte, Line As Byte) As Bit
If Line = 0 Then Line = 1
If Line > 4 Then Line = 4
If Xpos = 0 Then Xpos = 1
Select Case Line
Case 1
Lcdcmdout LcdLine1Pos(Xpos)
Case 2
Lcdcmdout LcdLine2Pos(Xpos)
Case 3
Lcdcmdout LcdLine3Pos(Xpos)
Case 4
Lcdcmdout LcdLine4Pos(Xpos)
EndSelect
End Function
' **********************************************************************
' Function that enlarges the numeric characters of a string
' Limited string length, written for 2-line
' Line: LCD line.
' Xpos: Starting position to print on the LCD
' strChar: numeric string to write.
' Returns the next position to print (low line).
' *********************************************************************
Function LCD_OutBigNum(Line As Byte, Xpos As Byte, strChar[20] As String) As Byte
Dim data As Byte ' Mask
Dim index As Byte ' Index mask.
Dim xStr As Byte ' Character position of then string.
xStr = 0
While strChar(xStr) > 0
Lcd_PosXY(Xpos, Line) ' Lcd cursor position.
For index = 0 To 5 ' Upper and lower mask print control loop.
Select Case strChar(xStr)
' Numeric characters.
Case "0"
data = LookUp(4, 0, 3, 4, 1, 3), index '0
Case "1"
data = LookUp(6, 255, " ", 5, 255, 7), index '1
Case "2"
data = LookUp(6, 2, 3, 4, 1, 7), index '2
Case "3"
data = LookUp(6, 2, 3, 5, 1, 3), index '3
Case "4"
data = LookUp(4, 1, 255, " ", " ", 255), index '4
Case "5"
data = LookUp(4, 2, 0, 5, 1, 3), index '5
Case "6"
data = LookUp(4, 2, " ", 4, 1, 3), index '6
Case "7"
data = LookUp(6, 0, 3, " ", 255, " "), index '7
Case "8"
data = LookUp(4, 2, 3, 4, 1, 3), index '8
Case "9"
data = LookUp(4, 2, 3, " ", " ", 255), index '9
' Special characters.
Case "º"
Lcdout "o" 'º
Lcd_PosXY(Xpos, Line +1)
Lcdout " "
Xpos++
Exit For
Case "-"
Lcdout "_" '-
Lcd_PosXY(Xpos, Line +1)
Lcdout " "
Xpos++
Exit For
Case Else
Lcdout " "
Lcd_PosXY(Xpos, Line +1)
Lcdout strChar(xStr)
Xpos++
Exit For
EndSelect
'Write the numeric characters.
Lcdout data 'Print the current mask.
If index = 2 Then
Lcd_PosXY(Xpos, Line +1) 'Line change.
Xpos = Xpos + 3 'Position of the new digit.
Endif
Next index
xStr++ 'Next digit to print.
ReturnValue Xpos 'Return to the next position.
Wend
End Function