Betrieb eines 27x4 LCD mit PCF8574 am I2C Bus

Cassio

Aktives Mitglied
29. Okt. 2008
4.027
17
38
Region Hannover
Sprachen
  1. BascomAVR
Die zwischenzeitlich verbesserten und überarbeiteten Routinen zum Ansteuern gibt es HIER (einfach drauf klicken)!


Hallo zusammen!

Wie der Eine oder Andere von euch vielleicht bekommen hat, habe ich ja schon einige Male versucht die alten 27x4 Pollindisplays am I2C-Bus zu betreiben. :wink:

Wie ihr einmal in diesem Beitrag und in diesem Beitrag sehen könnt, war das gar nicht so einfach.

Da es zum Betrieb eines HD44780-LCD`s schon seit Jahren eine LIB von Kent Andersson dazu gibt, basierten auch alle meine Versuche auf dieser LIB.
Leider kann man mit der LIB das Display nicht betreiben!
Das liegt zum Einen daran, dass es im INIT der LIB einen Fehler gibt!

Zur Initialisierung des LCD`s im 4-Bit Modus muss folgendes gesendet werden:
&H03, &H03, &H03, &H02,......

Durch einen Fehler in der Kent Andersson LIB wird aber immer:
&H03, &H00, &H00, &H02,......
gesendet!

Das war aber NICHT der alleinige Grund, warum das 27x4 LCD nicht funktionieren wollte.

Ich möchte aber an dieser Stelle jetzt nicht alles wiederholen, was mir so aufgefallen ist und was ich alles ausprobiert habe.......
Aus dem Grunde komme ich zum Wesentlichen!


Da ich keine Möglichkeit gefunden habe das Display mit der Kent Andersson LIB zu betreiben, habe ich das Übermitteln der Daten dann selbst in die Hand genommen. :cool:
Es werden also alle Steuer- und Datensignale im Programm selbst erzeugt und per I2C auf den Weg gebracht.

Hierfür habe ich einige Subroutinen geschrieben, die zum Einen das Aufteilen der Bytes für den 4-Bit Modus erledigen und zum Anderen die genaue Zeichenstelle am Display berechnen.
Diese Daten werden teilweise in ein Array zusammen gefasst und dann über den I2C-Bus zum Display übertragen.

Damit die "Bedienung" beim Programmieren möglichst einfach ist, kann ich zur Displayausgabe folgendes verwenden:
Code:
Lcd_ 2 , 3 , "CASSIO by AVR-Praxis.de  "

Die Angabe "LCD_" kombiniert dabei zwei BASCOM-Anweisungen.....
Einmal "Locate" und einmal "Lcd" !

Mit meiner Anweisung "Lcd_" kann man also die Displayzeile (1-4) auswählen, die Ziffernstelle (1-27) festlegen und sofort noch den Text (27 Zeichen maximale Länge) mit angeben.
Es muss zum Verarbeiten der Daten auch kein "GOSUB" oder "CALL" ausgeführt werden!


Lange Rede, kurzer Sinn.....
Ich stelle hier jetzt einfach mal den ersten Teil von meinen Programmcode ein.
Schließlich kann man Ausführungen zu einem Programm meistens besser nachvollziehen, wenn man das Programm im Ganzen schon mal gesehen hat. :wink:
Da ich mit dem vollständigen Programm leider die max. Zeichengrenze des Beitrags überschreite, hier der erste Teil:
Code:
'CASSIO by AVR-Praxis Forum
'25.12.2011
'I2C Ansteuerung eines 27x4 LCD

$regfile = "m16adef.dat"
$crystal = 8000000                                          ' Intern !


$hwstack = 128
$swstack = 128
$framesize = 128



' ATmega16
'                 +---v---+
'    (XCK/T0) PB0 |1    40| PA0 (ADC0)------Taster1
'        (T1) PB1 |2    39| PA1 (ADC1)------Taster2
' (INT2/AIN0) PB2 |3    38| PA2 (ADC2)--DB4
'  (OC0/AIN1) PB3 |4    37| PA3 (ADC3)--DB5
'        (SS) PB4 |5    36| PA4 (ADC4)--DB6
'      (MOSI) PB5 |6    35| PA5 (ADC5)--DB7
'      (MISO) PB6 |7    34| PA6 (ADC6)--RS
'       (SCK) PB7 |8    33| PA7 (ADC7)
'           RESET |9    32| AREF
'             VCC |10   31| GND
'             GND |11   30| AVCC
'           XTAL2 |12   29| PC7 (TOSC2)--E1
'           XTAL1 |13   28| PC6 (TOSC1)--E2
'       (RXD) PD0 |14   27| PC5 (TDI)
'       (TXD) PD1 |15   26| PC4 (TDO)
'      (INT0) PD2 |16   25| PC3 (TMS)
'      (INT1) PD3 |17   24| PC2 (TCK)
'      (OC1B) PD4 |18   23| PC1 (SDA)-------I2C
'      (OC1A) PD5 |19   22| PC0 (SCL)-------I2C
'      (ICP1) PD6 |20   21| PD7 (OC2)-------LED
'                 +-------+
'

' ================================================
' Bestimme die Ein- und Ausgänge
Ddra = &B_0000_0000                                         '1 ist Ausgang 0 ist Eingang
Porta = &B1111_1111

Ddrb = &B_0000_0000                                         '1 ist Ausgang 0 ist Eingang
Portb = &B1111_1111

Ddrc = &B_0011_1111                                         '1 ist Ausgang 0 ist Eingang
Portc = &B1100_0000

Ddrd = &B_1111_1111                                         '1 ist Ausgang 0 ist Eingang
Portd = &B0000_0000                                         'auf Hi oder Low setzen



Led Alias Portd.7
Taster Alias Pina.0
Taster2 Alias Pina.1



' ==============================================================================
' I2C-Config
Config Scl = Portc.0                                        'I2C SCL
Config Sda = Portc.1                                        'I2C SDA

Config I2cdelay = 1

I2cinit


Const Pcf8574_lcd = &H74                                    'I2C-Adresse des PCx8574(A)

Gosub Lcd_init


'          PCF8574A
'             __
'      A0  -o|1 |o-  Vdd
'      A1  -o|  |o-  SDA
'      A2  -o|  |o-  SCL
'      D4  -o|  |o-  n.c. (INT)
'      D5  -o|  |o-  E1
'      D6  -o|  |o-  E2
'      D7  -o|  |o-  RW
'     GND  -o|_9|o-  RS


' ==============================================================================
Declare Sub Lcd_(byval X1 As Byte , Byval X2 As Byte , Byval Text1 As String * 27)
Dim Pos As Byte                                             'Locate Berechnung
Dim Text As String * 27                                     'LCD Ausgabe
Dim Lcd_text(27) As Byte At Text Overlay                    'ASCII-Werte der LCD Ausgabe
Dim Ascii_zeichen(4) As Byte                                'getrennte ASCII-Werte zur Übermittlung
Dim Zz As Byte                                              'Zeichenzähler
Dim Zi As Byte                                              'Zeichen-Indexzähler
Dim Init(4) As Byte                                         'Byte-Array für LCD-Parameter

Dim I As Byte                                               'Indexzähler
Dim Tb As Bit                                               'Toggle-Bit
Dim Ab As Bit                                               'Anzeige-Bit


' #############################################################################
' Anfangswerte:

Tb = 0                                                      'Toggel-Bit auf 0
Ab = 0                                                      'Taster-Bit auf 0

' ################################################
' #                                              #
' #---------------Arbeitsschleife----------------#
' #                                              #
' ################################################
Do                                                          'Hauptschleife-Beginn

If Taster2 = 0 Then                                         'CLS und Zähler-Test
   Gosub Lcd_cls                                            'beide Displayhälften löschen
   Waitms 250
   Bitwait Taster2 , Set
      For I = 0 To 255 Step 5                               'Variablenausgabe-Test
      Text = Str(i)                                         'Binär zu String wandeln
      Lcd_ 2 , 13 , Text
      Lcd_ 3 , 13 , Text
'      Waitms 1
      Next I
   Waitms 500
   Gosub Lcd_cls                                            'beide Displayhälften löschen
   Reset Tb                                                 'Toggel-Bit auf 0
   Reset Ab                                                 'Taster-Bit auf 0
Else
End If



If Taster = 0 Then                                          'Displayanzeige wechseln
   Toggle Tb
   Reset Ab
   Waitms 250
   Bitwait Taster , Set
Else
End If



If Tb = 0 Then
   If Ab = 0 Then
      Led = 0
      Gosub Lcd_cls
      Lcd_ 1 , 1 , "27x4 LCD mit E + E2 via I2C"
      Lcd_ 2 , 3 , "CASSIO by AVR-Praxis.de  "
      Lcd_ 2 , 1 , "*"
      Lcd_ 2 , 27 , "*"
      Set Ab
   Else
   End If

Else
   If Ab = 0 Then
      Led = 1
      Lcd_ 3 , 2 , "fertig gestellt: 25.12.11 "
      Lcd_ 4 , 4 , "I2C manuell gesteuert   "
      Lcd_ 4 , 1 , "!!"
      Lcd_ 4 , 26 , "!!"
      Set Ab
   Else
   End If
End If


Loop                                                        'Hauptschleife-Ende


End                                                         'end program


Obendrein mal ein kleiner Ausschnitt von der Ansteuerung des Displays am PCf8574:
27x4_LCD_Gosub_V05_Anfang.png


.....gleich gehs dann weiter mit dem Programm!
 
Die zwischenzeitlich verbesserten und überarbeiteten Routinen zum Ansteuern gibt es HIER (einfach drauf klicken)!




Hallo.....

Nun geht es erst mal mit dem Rest des Programmcodes weiter!


Subroutinen, die gleich unter die Do_loop Schleife gehören:
Code:
' #############################################################################
Sub Lcd_(x1 As Byte , X2 As Byte , Text1 As String * 27)

Text = Text1                                                'max.27 Zeichen String übergeben

If X1 = 1 Then                                              '1.Zeile angegeben
   Pos = X1 + &H7E                                          'Anzeige-Charakter berechnen
   Pos = Pos + X2                                           'Anzeige-Charakter berechnen
   Gosub Lcd1                                               '1.Displaycontroller verwenden
   Elseif X1 = 2 Then                                          '2.Zeile angegeben
   Pos = X1 + &HBD                                          'Anzeige-Charakter berechnen
   Pos = Pos + X2                                           'Anzeige-Charakter berechnen
   Gosub Lcd1                                               '1.Displaycontroller verwenden
Elseif X1 = 3 Then                                          '3.Zeile angegeben
      Pos = X1 + &H7C                                       'Anzeige-Charakter berechnen
      Pos = Pos + X2                                        'Anzeige-Charakter berechnen
      Gosub Lcd2                                            '2.Displaycontroller verwenden
Elseif X1 = 4 Then                                          '4.Zeile angegeben
      Pos = X1 + &HBB                                       'Anzeige-Charakter berechnen
      Pos = Pos + X2                                        'Anzeige-Charakter berechnen
      Gosub Lcd2                                            '2.Displaycontroller verwenden
Else
End If

End Sub


' #############################################################################
Lcd1:                                                       'Sub zur LCD-Ausgabe auf 1.Displaycontroller
Zz = Len(text)

Init(4) = Pos And &H0F                                      'Zeichen-Startposition Bit3-0
Init(2) = Pos And &HF0                                      'Zeichen-Startposition Bit7-4
Shift Init(2) , Right , 4
Init(1) = Init(2) + &H80                                    'E1 hinzu

Init(3) = Init(4) + &H80                                    'E1 hinzu
I2csend Pcf8574_lcd , Init(1) , 4                           'Array zum Display senden
Waitms 1


Init(1) = &H10                                              'RS-Pin HIGH setzen
I2csend Pcf8574_lcd , Init(1) , 1                           'Daten zum Display senden
Waitms 1

For Zi = 1 To Zz                                            'Zeichenlänge des Strings ermitteln
   Ascii_zeichen(1) = Lcd_text(zi) And &HF0                 'ASCII-Wert Bit7-4
   Shift Ascii_zeichen(1) , Right , 4
   Ascii_zeichen(2) = Ascii_zeichen(1) + &H10               'Bit7-4 + RS-Pin
   Ascii_zeichen(1) = Ascii_zeichen(1) + &H90               'Bit7-4 + RS + E1

   Ascii_zeichen(3) = Lcd_text(zi) And &H0F                 'ASCII-Wert Bit3-0
   Ascii_zeichen(4) = Ascii_zeichen(3) + &H10               'Bit3-0 + RS-Pin
   Ascii_zeichen(3) = Ascii_zeichen(3) + &H90               'Bit3-0 + RS + E1
   I2csend Pcf8574_lcd , Ascii_zeichen(1) , 4               'Daten zum Display senden
   Waitms 1
Next Zi                                                     'je nach Anzahl der Zeichen im String wiederholen

Init(1) = &H00                                              'RS-Pin wieder LOW setzen
I2csend Pcf8574_lcd , Init(1) , 1                           'Daten zm Display senden
Waitms 1

Return



' #############################################################################
Lcd2:                                                       'Sub zur LCD-Ausgabe auf 2.Displaycontroller
Zz = Len(text)

Init(4) = Pos And &H0F
Init(2) = Pos And &HF0
Shift Init(2) , Right , 4
Init(1) = Init(2) + &B0100_0000                             'E2 hinzu

Init(3) = Init(4) + &B0100_0000                             'E2 hinzu
I2csend Pcf8574_lcd , Init(1) , 4
Waitms 1


Init(1) = &B0001_0000                                       'RS-Pin HIGH setzen
I2csend Pcf8574_lcd , Init(1) , 1
Waitms 1

For Zi = 1 To Zz
   Ascii_zeichen(1) = Lcd_text(zi) And &HF0
   Shift Ascii_zeichen(1) , Right , 4
   Ascii_zeichen(2) = Ascii_zeichen(1) + &B0001_0000        'Bit7-4 + RS-Pin
   Ascii_zeichen(1) = Ascii_zeichen(1) + &B0101_0000        'Bit7-4 + RS + E2

   Ascii_zeichen(3) = Lcd_text(zi) And &H0F
   Ascii_zeichen(4) = Ascii_zeichen(3) + &B0001_0000        'Bit3-0 + RS-Pin
   Ascii_zeichen(3) = Ascii_zeichen(3) + &B0101_0000        'Bit3-0 + RS + E2
   I2csend Pcf8574_lcd , Ascii_zeichen(1) , 4
   Waitms 1
Next Zi

Init(1) = &H00                                              'Alle Pins am PCF wieder LOW
I2csend Pcf8574_lcd , Init(1) , 1
Waitms 1

Return



' #############################################################################
Lcd_cls:                                                    'Sub zum löschen beider Displayhälften
'Clear Screen Anweisung
Init(1) = &HC0
Init(2) = &H00
I2csend Pcf8574_lcd , Init(1) , 2                           '0h für E1 + E2 senden
Init(1) = &HC1
Init(2) = &H01
I2csend Pcf8574_lcd , Init(1) , 2                           '1h für E1 + E2 senden
Waitms 1

'Erste Zeile, erstes Zeichen anwählen
Init(1) = &HC8
Init(2) = &H08                                              '8h für E1 + E2 senden
I2csend Pcf8574_lcd , Init(1) , 2
Init(1) = &HC0
Init(2) = &H00                                              '0h für E1 und E2 senden
I2csend Pcf8574_lcd , Init(1) , 2
Waitms 1
Return



' #############################################################################
Lcd_init:                                                   'Sub zum Initialisieren beider Displaycontroller
Init(1) = &H00
Init(2) = &H00
I2csend Pcf8574_lcd , Init(1) , 2
Waitms 50

Init(1) = &HC3
Init(2) = &H03
I2csend Pcf8574_lcd , Init(1) , 2                           '03h
Waitms 1
I2csend Pcf8574_lcd , Init(1) , 2                           '03h
Waitms 1
I2csend Pcf8574_lcd , Init(1) , 2                           '03h
Waitms 1
Init(1) = &HC2
Init(2) = &H02
I2csend Pcf8574_lcd , Init(1) , 2                           '02h (4Bit Modus)
Waitms 1


I2csend Pcf8574_lcd , Init(1) , 2
Init(1) = &HC8
Init(2) = &H08
I2csend Pcf8574_lcd , Init(1) , 2                           '28h (4 Zeilen Display)
Waitms 1

Init(1) = &HC0
Init(2) = &H00
I2csend Pcf8574_lcd , Init(1) , 2
Init(1) = &HCE
Init(2) = &H0E
I2csend Pcf8574_lcd , Init(1) , 2                           '0Eh (Select Mode)
Waitms 1

Init(1) = &HC0
Init(2) = &H00
I2csend Pcf8574_lcd , Init(1) , 2
Init(1) = &HC6
Init(2) = &H06
I2csend Pcf8574_lcd , Init(1) , 2                           '06h (Select Mode)
Waitms 1

Init(1) = &HC0
Init(2) = &H00
I2csend Pcf8574_lcd , Init(1) , 2
Init(1) = &HCC
Init(2) = &H0C
I2csend Pcf8574_lcd , Init(1) , 2                           '0Ch (Select Mode)
Waitms 1

Init(1) = &HC0
Init(2) = &H00
I2csend Pcf8574_lcd , Init(1) , 2
Init(1) = &HC1
Init(2) = &H01
I2csend Pcf8574_lcd , Init(1) , 2                           '01h (Cls)
Waitms 1


Return


Zum Schluss noch ein Foto vom funktionstüchtigem Display:
27x4_I2C_manuell_V05.jpg


und vom "händischen" INIT, dass dem original BASCOM-INIT entspricht:
27x4_INIT_von_Hand.png



Fragen oder Hinweise zum Programm beantworte bzw. schreibe ich dann später mal!

Viele Grüße,
Cassio
 
Hi,

hatte Dir noch gar nicht gratuliert.:adore:

Ich denke, man weiss hier Deine Zeit- Investition zu Schätzen.
 
Hallo Michael!

Nun ja..... du kennst mich doch auch schon ein bisschen. :wink:

Ich habe nach unserem letzen Treffen einfach nicht aufgegeben.
Gerade weil ich schon so viel ausprobiert hatte und es immer noch nicht funktionierte.
Das Thema ist aber immer noch nicht ganz beendet, denn ich möchte gern die Kent Andersson-LIB noch so verändern dass es damit auch funktioniert. :)


Es war aber auch interessant das Ganze zu entwickeln, denn die Erfahrungen kann ich nun bei meinem nächsten Vorhaben ganz gut nutzen. :wink:


Grüße,
Cassio
 
Hi Cassio,

ja, stimmt schon. Hast aber saubere Arbeit geleistet. Und für uns alles zum Nulltarif...Soooviel können wir Dir ja nicht beibringen...:wink:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)