I2C I/O expander voor 1602 LCD

HD44780
Het gebruik van Alfa Numerieke (HD44780 compatible) displays vergt normaal gesproken minimaal 6 I/O poorten van de controller waarop deze is aangesloten. (4x data, RS, EN en eventueel R/W)
Met het gebruik van een I/O expander chip als de PCF8574 (IC2 aangestuurd, 8 I/O poorten) kan dit terug gebracht worden naar 2 poorten. (SCL en SDA)
Een en ander gaat natuurlijk wel ten koste van een stukje extra firmware in de controller, voor een PIC18F25K2x betreft dit ongeveer 1% van de totale capaciteit.

In PICBASIC (Proton) kan men dit realiseren d.m.v. het “Print” commando uit te schakelen en te vervangen door een stuk code die het 1602 display aanstuurt via de 2 I2C poorten.
Op het Protonbasic forum wat code gevonden die dit doet.
De code is bedoeld voor PIC’s die beschikken over hardware I2C (Synchronous Serial Port (SSP) of (MSSP))
Op het bovenstaande Protonbasic forum item is ook een “I2CPrintSoftCommand.inc” include file te vinden waarmee je elke I/O pin op de PIC als SCL en SDA aan kunt sturen.

Hieronder een stukje demo code met als belangrijkste onderdeel de include file “I2CPrintHardCommand.inc”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  Device = 18F25K22
  XTAL = 8
    OSCCON = %01100000   ;Internal osc on 8Mhz
    ANSELA = %00000000   ;Digitaal
    ANSELB = %00000000   ;Digitaal
    ANSELC = %00000000   ;Digitaal
   
  Symbol Led           = LATA.5
  Symbol Speaker       = PORTC.5
 
  Declare Show_System_Variables = On

  Declare SLOW_BUS Off
  Declare HBUS_BITRATE 400
 
  Clear

  Include "I2CPrintHardCommand.inc"     ' you may need to select alternate config depending on your backpack

' ----------------------------- test data --------------------------------------------------------
  Dim VFloat  As Float                      
  Dim VDword  As DWord
  Dim VSDword As SDword
  Dim VSWord  As SWord
  Dim VWord   As Word
  Dim VByte   As Byte
  Dim VSByte  As SByte
  Dim VBit    As Bit
 
  DelayMS 1000
 
Main:
    Sound  Speaker, [115,20]
  DelayMS 100                                           ' Wait for the LCD to initialise
  VFloat = 1.56789
  VDword = 100
  VSDword = 100
  VSWord = 100
  VWord = 100
  VByte = 10
  VSByte = 10
  VBit = 1
  Toggle Led
  Cls
  Print $FE, 3            ' backlight on On Next Call To Print
  Print At 1,1,"VF=",DEC4 VFloat," VD=",Dec VDword
  Print At 2,1,"VSD=",Dec VSDword," VS=",Dec VSWord
  DelayMS 2000
  Toggle Led
  Cls
  Print At 1,1,"VW=",HEX VWord," VB=",HEX VByte
  Print At 2,1,"VSB=",HEX VSByte," VB=",BIN VBit
  DelayMS 2000
  Toggle Led
  Cls
  Print At 1,1,"AA"," ","AAA"," ","AAAA"," ", "AAAAA"
  Print At 2,1,"AAAAAA"," ","AAAAAAA"
  DelayMS 2000
  Toggle Led
  Cls
  Print At 1,1,"Backlight off"
  DelayMS 250
  Toggle Led
  Print $FE, 4          ' backlight off on next call to PRINT
  Print " "
 
  Low Led
  Stop
' ----------------------------- test data --------------------------------------------------------
  CONFIG_START    
     'FOSC = HSMP                ;external oscillator
     FOSC = INTIO67             ;Internal oscillator block, port function on RA6 and RA7  
     FCMEN = Off                 ;Fail-Safe Clock Monitor disabled
     IESO = Off                  ;internal external switchover mode
     PWRTEN = On                 ;power-up timer
     BOREN = On                  ;brown-out reset
     BORV = 285                  ;brown-out reset value (2,7V)
     WDTEN = Off                 ;watchdog timer
     WDTPS = 128                 ;1:128 WDT prescalar
     PBADEN = Off                ;analog port B<4:0>
     STVREN = On                 ;;stack overflow reset
     LVP = Off                   ;low voltage programming
     XINST = Off                 ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
     Debug = Off                 ;no debug
     CCP2MX = PORTB3            ;CCP2 input/output is multiplexed with RB3
CONFIG_END

De incude file : “I2CPrintHardCommand.inc” welke het originele “Print” commando (en aanverwante commado’s als “Cls”) uitschakelt en vervangt door code die hetzelfde doet, maar dan via de I2C bus. De include file moet tijdens compileren van de .bas file in de zelfde directorie staan als de .bas file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
'*****************************************************************************************************************
'*  Name    : I2CPrintHardCommand.inc                                                                            *
'*  Purpose : allow Proton Print commands to access the standard 1602 LCD via I2C backpack board                 *
'*  Author  : George Towler                                                                                      *
'*  Notice  : I claim no copyright but maybe Barak does                                                          *
'*  Date    : 18/01/2015                                                                                         *
'*  Compiler: 3.5.7.1                                                                                            *
'*  Version : 0.9.0                                                                                              *
'*  Notes   : see http://www.protonbasic.co.uk/showthread.php/62478-%93Print%94-command-for-SPI-Alfa-numeric-LCD *                                                  
'*          :     post #6   Barak shows how to replace Proton commands and how to deal with control (FE$) bytes  *                                                                                                                              
'*****************************************************************************************************************

  #Disable Print                          ;Disable the Proton Print command    

  ;***************************************************************************************************************
  ; Configure items to suit your LCD and I2C hardware, I2CPrint_DataOnHighBits remmed if data is on low bits     *
  ;                                                                                                              *
  Symbol I2CPrint_address         = %01001110   ' PCF8574 Slave Address 0,1,1,1,A2,A1,A0,RW  where W=0           *
  Symbol I2CPrint_InitForLCDLines = $28         ' $28 for two lines                                              *
  Symbol I2CPrint_RS              = %00000001   '                                                                *
  Symbol I2CPrint_RW              = %00000010   '                                                                *
  Symbol I2CPrint_E               = %00000100   '                                                                *
  Symbol I2CPrint_BackLight       = %00001000   '                                                                *
  $define I2CPrint_DataOnHighBits               '                                                                *
  ;***************************************************************************************************************
 
  Symbol I2CPrint_RS_E           = I2CPrint_RS | I2CPrint_E
 
  $ifdef I2CPrint_DataOnHighBits
    Symbol I2CPrint_Init1          = %00110000
    Symbol I2CPrint_Init1_E        = %00110000 | I2CPrint_E
    Symbol I2CPrint_Init2          = %00110000  
    Symbol I2CPrint_Init2_E        = %00110000 | I2CPrint_E
    Symbol I2CPrint_Init3          = %00100000
    Symbol I2CPrint_Init3_E        = %00100000 | I2CPrint_E
  $Else
    Symbol I2CPrint_Init1          = %00000011  
    Symbol I2CPrint_Init1_E        = %00000011 | I2CPrint_E
    Symbol I2CPrint_Init2          = %00000011  
    Symbol I2CPrint_Init2_E        = %00000011 | I2CPrint_E
    Symbol I2CPrint_Init3          = %00000010  
    Symbol I2CPrint_Init3_E        = %00000010 | I2CPrint_E
  $EndIf

  Dim BPF As Byte SYSTEM
  Symbol I2CPrint_tComOrData = BPF.0
  Symbol I2CPrint_tInitialised = BPF.1  

  Dim I2CPrint_PrintStore As Byte
  Dim I2CPrint_PrintData As Byte
  Dim I2CPrint_HighData As Byte
  Dim I2CPrint_LowData As Byte
  Dim I2CPrint_dummy As Byte
  Dim I2CPrint_RSFlag As Byte  
  Dim Backlight_State As Byte

  GoTo I2CPrintCommand_End

  @Print                                              ; assembler Print redirect
  Wreg_Byte I2CPrint_PrintStore                       ; save the W Register

  If I2CPrint_tInitialised = 0 Then                   ; Has LCD been inititalised?
    DelayMS 100                                       ; Power-on delay for slow display types
    HBusOut I2CPrint_address, [I2CPrint_Init1_E]      ; E hi and send command nibble 0011 (3)    
    HBusOut I2CPrint_address, [I2CPrint_Init1]        ; E lo    
    DelayMS 20
    HBusOut I2CPrint_address, [I2CPrint_Init2_E]      ; E hi and send command nibble 0011 (3)    
    HBusOut I2CPrint_address, [I2CPrint_Init2]        ; E lo    
    DelayMS 20
    HBusOut I2CPrint_address, [I2CPrint_Init3_E]      ; E hi and send command nibble 0010 (2)    
    HBusOut I2CPrint_address, [I2CPrint_Init3]        ; E lo    
    DelayMS 20
    I2CPrint_PrintData = I2CPrint_InitForLCDLines     ; 4 bit mode and n lines
    GoSub I2CPrint_SendControl
    I2CPrint_PrintData = $0C                          ; enable display, cursor and blink off
    GoSub I2CPrint_SendControl
    I2CPrint_PrintData = $06                          ; move cursor after each write
    GoSub I2CPrint_SendControl                    
    I2CPrint_PrintData = $80                          ; goto column 1 line 1
    GoSub I2CPrint_SendControl
    Set I2CPrint_tInitialised                         ; Indicate that the LCD is initialised
  EndIf

  I2CPrint_PrintData = I2CPrint_PrintStore
  If I2CPrint_PrintData = 0xFE Then                   ; it is a command header
    I2CPrint_RSFlag = 0                               ; clear a flag so we know the next byte will be a command
  Else
    If I2CPrint_RSFlag = 0 Then                       ; this is a command byte
      If I2CPrint_PrintData = 03 Then
        Backlight_State = I2CPrint_BackLight  
      ElseIf I2CPrint_PrintData = 04 Then
        Backlight_State = 0  
      Else
        GoSub I2CPrint_SendControl
      End If
    Else
      GoSub I2CPrint_SendData
    EndIf
    I2CPrint_RSFlag = 1                               ; set the flag so the next byte will be send as Data
  EndIf                                    
  Byte_Wreg I2CPrint_PrintStore                       ; restore the W register
  Return

' ****************************************************************************
' **                             S U B R O U T I N E S                      **
' ****************************************************************************

I2CPrint_SendData:
  $ifdef I2CPrint_DataOnHighBits
    I2CPrint_HighData = I2CPrint_PrintData & %11110000            ; mask LSBs
    I2CPrint_LowData = I2CPrint_PrintData << 4                    ; shift left
  $Else
    I2CPrint_LowData = I2CPrint_PrintData & %00001111             ; mask MSBs
    I2CPrint_HighData = I2CPrint_PrintData >> 4                   ; shift Right
  $EndIf

  I2CPrint_dummy = I2CPrint_RS_E | I2CPrint_HighData              ; data and e hi
  I2CPrint_dummy = I2CPrint_dummy | Backlight_State               ; data and e hi and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]            
  I2CPrint_dummy = I2CPrint_RS | I2CPrint_HighData                ; data and e lo
  I2CPrint_dummy = I2CPrint_dummy | Backlight_State               ; data and e lo and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]              
  I2CPrint_dummy = I2CPrint_RS | Backlight_State                  ; data and e hi
  HBusOut I2CPrint_address, [I2CPrint_dummy]                      ; Delay, RS on throughout
  I2CPrint_dummy = I2CPrint_RS_E | I2CPrint_LowData               ; data and e hi
  I2CPrint_dummy = I2CPrint_dummy | Backlight_State               ; data and e hi and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]              
  I2CPrint_dummy = I2CPrint_RS | I2CPrint_LowData                 ; data and e lo
  I2CPrint_dummy = I2CPrint_dummy | Backlight_State               ; data and e lo and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]
  Return
 
I2CPrint_SendControl:
  $ifdef I2CPrint_DataOnHighBits
    I2CPrint_HighData = I2CPrint_PrintData & %11110000            ; mask LSBs
    I2CPrint_LowData = I2CPrint_PrintData << 4                    ; shift left
  $Else
    I2CPrint_LowData = I2CPrint_PrintData & %00001111             ; mask MSBs
    I2CPrint_HighData = I2CPrint_PrintData >> 4                   ; shift Right
  $EndIf

  I2CPrint_dummy = I2CPrint_E | I2CPrint_HighData                 ; data and e hi
  I2CPrint_dummy = I2CPrint_dummy | Backlight_State               ; data and e hi and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]              
  I2CPrint_dummy = I2CPrint_HighData | Backlight_State            ; data and e lo and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]              
  I2CPrint_dummy = Backlight_State                                ;
  HBusOut I2CPrint_address, [I2CPrint_dummy]                      ; Delay
  I2CPrint_dummy = I2CPrint_E | I2CPrint_LowData                  ; data and e hi
  I2CPrint_dummy = I2CPrint_dummy | Backlight_State               ; data and e hi and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]              
  I2CPrint_dummy = I2CPrint_LowData | Backlight_State             ; data and e lo and bls
  HBusOut I2CPrint_address, [I2CPrint_dummy]        
  Return

I2CPrintCommand_End:

1602 LCD I2C Backpack bordje bestellen




Hit Counter by Digits
  Sinds 23 Mrt 2015