Willkommen in unserer Community

Werde Teil unserer Community und registriere dich jetzt kostenlos ...

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Bascom I2C : LCD ( auch Arduino ) mit PCF8574 OHNE LIB betreiben

Dieses Thema im Forum "LED + LCD" wurde erstellt von Cassio, 2. Januar 2012.

  1. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Zur schnelleren Übersicht......

    Ansteuerungsroutinen mit einem PCx8574(A), HIER klicken oder einfach in diesem Beitrag weiter lesen. :wink:

    Ansteuerungsroutinen mit einem PCx8575, HIER klicken !


    Ansteuerungsroutinen für ein Arduino-LCD (mit PCA8574), HIER klicken !


    Ansteuerroutinen für ein 16x2LCD mit Pollin (oder Conrad)-I2C-Adapter findet ihr HIER bzw. in Beitrag 44!



    Betrieb von diversen GLCD`s als Charakter-LCD`s am I2C-Bus wird HIER beschrieben!



    Hallo zusammen!

    Es gibt zwar schon seit Jahren für BASCOM eine LIB zum Betrieb eines LCD am I2C (TWI) Bus ( Lcd_i2c.lib ),
    jedoch funktioniert diese LIB nicht mit jedem Display.
    Obendrein ist die Abarbeitung durch die LIB nicht besonders schnell und es kam bei mir immer mal wieder vor, dass die Displays neu initialisiert werden mussten, weil plötzlich nur noch Unsinn angezeigt wurde.
    Dieser Effekt trat besonders immer dann auf, wenn in schneller Folge die Displayanzeige wechseln sollte.


    Aus den eben genannten Gründen habe ich mich der Sache mal angenommen und rausgekommen ist eine schnelle und zuverlässige Ansteuerung von LCD`s über den I2C bzw. TWI Bus.
    Damit die Verwendung beim Programmieren möglichst einfach ist, benötigt man im Programm selbst nur drei Anweisungen:
    • LCD_ X , Y , "String"
    • LCD_cls
    • LCD_init

    Generell muss das LCD_init natürlich nur einmal zu Beginn ausgeführt werden!
    Es ist aber auch möglich, dies jederzeit im Programm noch einmal aufzurufen..... z.B. durch einen Taster, oder eine Automatik.
    Diese Eigenschaft ist z.B. dann wichtig, wenn man während des Programmablaufes das Display mal vom I2C-Bus trennt und später wieder ansteckt.
    In diesem Fall muss erst mal ein INIT zum Display gesendet werden, damit es wieder funktioniert.

    Die Anweisung LCD_cls erklärt sich wohl von selbst. :wink:
    Es löscht BEIDE Displaycontroller per Parameteranweisung gleichzeitig.

    Mit LCD_ X , Y , "String" erfolgt die Eingabe des Textes, der auf dem Display an der angegebenen Stelle erscheinen soll.
    Für X gibt man die Zeilennummer an,
    für Y gibt man den Startcharakter an und
    bei "String" wird der anzuzeigende Text eingegeben.


    Damit diese Anweisungen funktionieren, muss man folgendes beachten:
    Einmal müssen die zugehörigen Subroutinen und globalen Variablen im Hauptprogramm deklariert werden!
    Code:
    Declare Sub Lcd_(byval X1 As Byte , Byval X2 As Byte , Byval Text1 As String * 27)
    Declare Sub Lcd_cls
    Declare Sub Lcd_init
    Dim Text As String * 27                                     'LCD Ausgabe
    Dim Lcd_text(27) As Byte At Text Overlay                    'ASCII-Werte der LCD Ausgabe
    Dim Init(8) As Byte                                         'Byte-Array für LCD-Parameter
    
    Const Pcx_lcd = &H74                                        'I2C-Adresse des PCx8574(A)
    
    Da es sich bei meinem Testobjekt um ein 27x4 LCD gehandelt hat, habe ich den Text1-String auch auf 27 Zeichen begrenzt.
    Maximal möglich wären hier wohl 40 Zeichen
    !




    In den Subroutinen müssen dann nur noch per "$include"-Anweisung die Routinen mit eingebunden werden!
    Im Hauptprogramm muss man also nur noch:
    Code:
    ' #############################################################################
    Sub Lcd_(x1 As Byte , X2 As Byte , Text1 As String * 27)    'Sub zur Zeichenausgabe am Display
    $include "_2704_i2c.bas"
    
    ' #############################################################################
    Sub Lcd_cls:                                                'Sub zum löschen beider Displayhälften
    $include "_2704_CLS.bas"
    
    ' #############################################################################
    Sub Lcd_init:                                               'Sub zum initialisieren beider Displayhälften
    $include "_2704_init.bas"
    
    angeben und die drei Dateien im selben Verzeichnis abspeichern, in dem sich auch das Hauptprogramm befindet.


    Das war es dann auch schon und es steht der erfolgreichen LCD-Ansteuerung über I2C nichts mehr im Wege. :)


    Was in diesem Beitrag also noch fehlt, sind die einzelnen Subroutinen......
    und die folgen jetzt! :D

    Die Sub zum INIT:
    (Überarbeitete Version vom 09.01.12)
    Code:
    $nocompile
    
    
    ' #############################################################################
    Init(1) = &HC3
    Init(2) = &H03
    I2csend Pcx_lcd , Init(1) , 2                               '03h
    Waitms 1
    I2csend Pcx_lcd , Init(1) , 2                               '03h
    Waitms 1
    I2csend Pcx_lcd , Init(1) , 2                               '03h
    Waitms 1
    Init(1) = &HC2
    Init(2) = &H02
    I2csend Pcx_lcd , Init(1) , 2                               '02h (4Bit Modus)
    Waitms 1
    
    
    I2csend Pcx_lcd , Init(1) , 2
    Init(1) = &HC8
    Init(2) = &H08
    I2csend Pcx_lcd , Init(1) , 2                               '28h (4 Zeilen Dispaly)
    Waitms 1
    
    Init(1) = &HC0
    Init(2) = &H00
    I2csend Pcx_lcd , Init(1) , 2
    Init(1) = &HCE
    Init(2) = &H0E
    I2csend Pcx_lcd , Init(1) , 2                               '0Eh (Select Mode)
    Waitms 1
    
    Init(1) = &HC0
    Init(2) = &H00
    I2csend Pcx_lcd , Init(1) , 2
    Init(1) = &HC6
    Init(2) = &H06
    I2csend Pcx_lcd , Init(1) , 2                               '06h (Select Mode)
    Waitms 1
    
    Init(1) = &HC0
    Init(2) = &H00
    I2csend Pcx_lcd , Init(1) , 2
    Init(1) = &HCC
    Init(2) = &H0C
    I2csend Pcx_lcd , Init(1) , 2                               '0Ch (Select Mode)
    Waitms 1
    
    Init(1) = &HC0
    Init(2) = &H00
    I2csend Pcx_lcd , Init(1) , 2
    Init(1) = &HC1
    Init(2) = &H01
    I2csend Pcx_lcd , Init(1) , 2                               '01h (Cls)
    Waitms 1
    
    End Sub
    

    Die Sub für CLS:
    (Überarbeitete Version vom 09.01.12)
    Code:
    $nocompile
    
    
    'Clear Screen Anweisung
    Init(1) = &HC0
    Init(2) = &H00
    Init(3) = &HC1
    Init(4) = &H01
    'Erste Zeile, erstes Zeichen anwählen
    Init(5) = &HC8
    Init(6) = &H08                                              '8h für E1 + E2 senden
    Init(7) = &HC0
    Init(8) = &H00                                              '0h für E1 und E2 senden
    I2csend Pcx_lcd , Init(1) , 8
    Waitms 1
    
    End Sub
    

    Die Sub für die Textausgabe:
    (Überarbeitete Version vom 09.01.12)
    Code:
    $nocompile
    
    'Dim Pos As Byte                                             'Locate Berechnung
    'Dim Ascii_zeichen(5) As Byte                                'getrennte ASCII-Werte zur Übermittlung
    'Dim Zz As Byte                                              'Zeichenzähler
    'Dim Zi As Byte                                              'Zeichen-Indexzähler
    
    
    ' #############################################################################
    Text = Text1                                                'max.27 Zeichen String übergeben
    
    Select Case X1
    Case 1
       Pos = X1 + &H7E                                          'Anzeige-Charakter berechnen
       Pos = Pos + X2                                           'Anzeige-Charakter berechnen
       Gosub Lcd1                                               '1.Displaycontroller verwenden
    Case 2
       Pos = X1 + &HBD                                          'Anzeige-Charakter berechnen
       Pos = Pos + X2                                           'Anzeige-Charakter berechnen
       Gosub Lcd1                                               '1.Displaycontroller verwenden
    Case 3
          Pos = X1 + &H7C                                       'Anzeige-Charakter berechnen
          Pos = Pos + X2                                        'Anzeige-Charakter berechnen
          Gosub Lcd2                                            '2.Displaycontroller verwenden
    Case 4
          Pos = X1 + &HBB                                       'Anzeige-Charakter berechnen
          Pos = Pos + X2                                        'Anzeige-Charakter berechnen
          Gosub Lcd2                                            '2.Displaycontroller verwenden
    Case Else
    End Select
    
    
    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                                    'Bit7-4 + E1
    
    Init(3) = Init(4) + &H80                                    'Bit3-0 + E1
    I2csend Pcx_lcd , Init(1) , 4                               'Start-Array zum Display senden
    Waitus 100
    
    Ascii_zeichen(5) = &H00
    
    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 Pcx_lcd , Ascii_zeichen(1) , 5                   'ASCII-Daten zum Display senden
       Waitus 400
    Next Zi                                                     'je nach Anzahl der Zeichen im String wiederholen
    
    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 Pcx_lcd , Init(1) , 4
    Waitus 100
    
    Ascii_zeichen(5) = &H00
    
    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 Pcx_lcd , Ascii_zeichen(1) , 5
       Waitus 400
    Next Zi
    
    Return
    

    FERTIG !


    Ein Beispielprogramm zur Verwendung und einige Hinweise folgen in Kürze!

    Grüße,
    Cassio
     
    developerx gefällt das.
  2. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo zusammen!

    Zum Test meiner Ansteuerroutinen habe ich mal ein kleines Programm geschrieben....

    Das Beispielprogramm stelle ich hier mal mit ein:
    Code:
    $regfile = "m16adef.dat"
    $crystal = 16000000                                         'EXTERN !
    
    
    $hwstack = 128
    $swstack = 128
    $framesize = 128
    
    
    
    ' --------------------ATmega16------------------------
    '                    +---v---+
    '       (XCK/T0) PB0 |1    40| PA0 (ADC0)------Taster
    '           (T1) PB1 |2    39| PA1 (ADC1)------Taster2
    '    (INT2/AIN0) PB2 |3    38| PA2 (ADC2)
    '     (OC0/AIN1) PB3 |4    37| PA3 (ADC3)
    '           (SS) PB4 |5    36| PA4 (ADC4)
    '         (MOSI) PB5 |6    35| PA5 (ADC5)
    '         (MISO) PB6 |7    34| PA6 (ADC6)
    '          (SCK) PB7 |8    33| PA7 (ADC7)
    '              RESET |9    32| AREF
    '                VCC |10   31| GND
    '                GND |11   30| AVCC
    '              XTAL2 |12   29| PC7 (TOSC2)
    '              XTAL1 |13   28| PC6 (TOSC1)
    '          (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
    ' DCF77---(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_1011_1111                                         '1 ist Ausgang 0 ist Eingang
    Portd = &B0100_0000                                         'auf Hi oder Low setzen
    
    
    
    Led Alias Portd.7
    Taster Alias Pina.0
    Taster2 Alias Pina.1
    
    
    
    ' ==============================================================================
    Declare Sub Lcd_(byval X1 As Byte , Byval X2 As Byte , Byval Text1 As String * 27)
    Declare Sub Lcd_cls
    Declare Sub Lcd_init
    Dim Text As String * 27                                     'LCD Ausgabe
    Dim Lcd_text(27) As Byte At Text Overlay                    'ASCII-Werte der LCD Ausgabe
    Dim Init(8) As Byte                                         'Byte-Array für LCD-Parameter
    
    Const Pcx_lcd = &H74                                        'I2C-Adresse des PCx8574(A)
    
    '          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
    
    ' ==============================================================================
    ' I2C-Config
    Config Scl = Portc.0                                        'I2C SCL
    Config Sda = Portc.1                                        'I2C SDA
    
    Config I2cdelay = 1
    
    I2cinit
    ' ==============================================================================
    
    
    
    '######################## Pollin Modul : Inverted = 1 ##########################
    Config Dcf77 = Pind.6 , Timer = 1 , Timer1sec = 1 , Debug = 1 , Update = 0 , Check = 1 , Inverted = 1 , Gosub = Sectic
    
    Config Date = Dmy , Separator = .
    
    Enable Interrupts
    
    Date$ = "01.01.07"
    Time$ = "12:00:00"
    
    
    ' #############################################################################
    Dim I As Byte , I2 As Byte                                  'Indexzähler
    Dim Tb As Bit                                               'Toggle-Bit
    Dim Ab As Bit                                               'Anzeige-Bit
    
    Dim Dtag As Byte , Wtag As String * 10
    Dim Sync As Bit
    Dim Puls As Bit
    Dim Status_old As Byte
    
    
    ' #############################################################################
    ' Anfangswerte:
    
    Tb = 0                                                      'Toggel-Bit auf 0
    Ab = 0                                                      'Taster-Bit auf 0
    
    Lcd_init
    
    
    ' ################################################
    ' #                                              #
    ' #---------------Arbeitsschleife----------------#
    ' #                                              #
    ' ################################################
    Do                                                          'Hauptschleife-Beginn
    
    Dtag = Dayofweek()                                          'Wochentag ermitteln
    Wtag = Lookupstr(dtag , Wochentage)                         'Wochentag im Klartext
    
    If Puls = 1 Then                                            'Puls wird von Sectic auf 1 gesetzt
       Lcd_ 1 , 20 , Time$                                      'Zeit anzeigen
       Lcd_ 2 , 1 , Wtag                                        'Wochentag anzeigen
       Lcd_ 2 , 19 , Date$                                      'Datum anzeigen
       Text = Time(dcf_sec)                                     'DCF-Zeit anzeigen
       Lcd_ 3 , 20 , Text
       Reset Puls
    Else
    End If
    
    
    If Status_old <> Dcf_status Then                            'Ausführen beim neuen Status
       Status_old = Dcf_status                                  'Status kopieren
       Text = Bin(dcf_status)                                   'in String konvertieren
       Lcd_ 3 , 6 , Text                                        'Statusbits binär anzeigen
       Text = Str(bdcf_impuls) : Text = Format(text , "000")
       Lcd_ 4 , 14 , Text                                       'DCF-Impulslänge anzeigen
       Text = Str(bdcf_pause) : Text = Format(text , "000")
       Lcd_ 4 , 24 , Text                                       'DCF-Pausenlänge anzeigen
    Else
    End If
    
    
    
    If Taster2 = 0 Then                                         'CLS und Zähler-Test
       Lcd_init                                                 'Display neu initialisieren
       Waitms 250
       Bitwait Taster2 , Set
          For I = 0 To 255                                      'Variablenausgabe-Test
          Text = Str(i)                                         'Binär zu String wandeln
          Lcd_ 1 , 7 , Text
          Lcd_ 2 , 10 , Text
          Lcd_ 3 , 13 , Text
          Lcd_ 4 , 16 , Text
          Next I
       Waitms 500
       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                                                'Toggle-Bit wechseln
       Reset Ab                                                 'Anzeige-Bit zurücksetzen
       Waitms 250
       Bitwait Taster , Set
    Else
    End If
    
    
    If Tb = 0 Then
       If Ab = 0 Then                                           'Layout einmal ausgeben
          Lcd_cls
          Lcd_ 1 , 1 , "Es ist jetzt "
          Lcd_ 2 , 11 , ",  der"
          Lcd_ 3 , 1 , "DCF:"
          Lcd_ 3 , 15 , "Time"
          Lcd_ 4 , 1 , "DCF= Impulse:    Pause:    "
          Set Ab
       Else
       End If
    
    Else
          For I = 1 To 4                                        'Geschwindigkeitstest aller 108 Zeichen
             For I2 = 1 To 27
                Lcd_ I , I2 , "X"
             Next I2
          Next I
          Wait 1
          Tb = 0
    End If
    
    
    ' ----------------------------------------
    If _sec > 1 Then Reset Dcf_status.7                         'Sync-Bit der Softclock zurücksetzen
    
    If _sec = 1 Then
       If Dcf_status.7 = 1 Then
          Sync = 1                                              'Sync der Softclock merken
       Else
          Sync = 0                                              'Kein Sync der Softclock
       End If
    Else
    End If
    ' ----------------------------------------
    If Sync = 1 Then                                            'Wenn Sync der Softclock, dann...
    Lcd_ 1 , 14 , "genau"
    Reset Led                                                   'LED EIN
    Else                                                        'wenn kein Sync, dann.....
    Lcd_ 1 , 14 , "etwa "
    Set Led                                                     'LED AUS
    End If
    
    Loop                                                        'Hauptschleife-Ende
    
    
    End                                                         'end program
    
    ' #############################################################################
    Sectic:
    Set Puls
    Return
    
    
    
    ' #############################################################################
    Sub Lcd_(x1 As Byte , X2 As Byte , Text1 As String * 27)    'Sub zur Zeichenausgabe am Display
    $include "_2704_i2c.bas"
    
    ' #############################################################################
    Sub Lcd_cls:                                                'Sub zum löschen beider Displayhälften
    $include "_2704_CLS.bas"
    
    ' #############################################################################
    Sub Lcd_init:                                               'Sub zum initialisieren beider Displayhälften
    $include "_2704_init.bas"
    
    
    
    ' #############################################################################
    Wochentage:
    Data "    Montag" , "  Dienstag" , "  Mittwoch" , "Donnerstag" , "   Freitag" , "   Samstag" , "   Sonntag"
    
    


    Wenn alles funktioniert, sollte die Display-Ausgabe anschließend so aussehen:
    27x4_LCD_include.jpg


    Das Interessante bei dem Beispielprogram sind die "Geschwindigkeitstests", die ich im Code mit eingebaut habe.
    Einmal wird das Display neu initialisiert und anschließend ein Byte von 0-255 hochgezählt, dessen Werte nacheinander auf allen vier Zeilen versetzt ausgegeben werden.


    Bei einem anderen Test (Taster 1) wird 27 x 4 (also 108 mal) das "X" einzeln positioniert und ausgegeben.
    Dies wird mit zwei verschachtelten FOR-NEXT Schleifen realisiert:
    Code:
          For I = 1 To 4                                        'Geschwindigkeitstest aller 108 Zeichen
             For I2 = 1 To 27
                Lcd_ I , I2 , "X"
             Next I2
          Next I
    
    Das Erstaunliche dabei ist, dass alle 108 Zeichen in nur knapp 190ms fertig auf dem Display platziert sind! :dance3:
    Nachgeprüft habe ich das mit dem Analyser:
    27x4_108_Zeichen_include.png

    Wenn man nun bedenkt, dass die 108 ASCII-Zeichen in zwei Schritten übertragen werden müssen (4bit-Mode) und dann noch für jedes einzelne Zeichen vorher die Parameter zur Darstellung in zwei Schritten gesendet werden, dann sind das:
    108_Zeichen x 2_Schritte = 216_Signale
    108_Parameter x 2_Schritte = 216_Signale
    216_Signale + 216_Signale = 432_Signale am Display in knapp 190ms !

    Diese Geschwindigkeit war mit der LIB von Kent Andersson einfach unerreicht und obendrein war die Ausgabe nicht zuverlässig.
    Bei so einer hohen Datenrate gab es bei mir permanent Probleme, so dass ich das Display immer wieder mal initialisieren musste.


    Wie im Programm zu erkennen ist, wird der Controller dabei mit 16MHz betrieben und lt. Analyser schafft es der I2C-Bus dabei auf 267kHz.

    Fazit:
    Wer also nach einer schnellen und flexiblen Möglichkeit sucht (weil es keine "kryptische" ASM-LIB ist) verschiedenste Typen von LCD`s am I2C Bus zu betreiben, der soll es mit den o.g. Routinen ruhig einmal probieren. :wink:
    Dank reiner BASCOM-Dateien kann jeder seine Anpassungen und Veränderungen selbst vornehmen.

    Viel Spaß damit......

    Grüße,
    Cassio
     
  3. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo zusammen!

    Ich habe die Subroutinen im 1. Beitrag mal aktualisiert! :cool:

    Durch einige Optimierungen konnte ich die Geschwindigkeit noch weiter erhöhen! :D
    Nach letzten Messungen dauert der 108-Zeichen-Test jetzt nicht mehr knapp 190ms sondern nur noch knapp 139ms!

    Das bedeutet, durch die Optimierung arbeitet alles über 25% schneller und trotzdem kommt das Display nicht durcheinander. :dance3:




    Kurz zur Info:
    Momentan arbeite ich gerade an der "16bit"-Version..... also mit einem PCF8575 (16 I/O).
    Code:
    '-----------PCF8575------------
    '             ___
    '     INT  -o|1  |o-  Vdd
    '      A1  -o|   |o-  SDA
    '      A2  -o|   |o-  SCL
    '     P00  -o|   |o-  A0
    '     P01  -o|   |o-  P17
    '     P02  -o|   |o-  P16
    '     P03  -o|   |o-  P15
    '     P04  -o|   |o-  P14
    '     P05  -o|   |o-  P13
    '     P06  -o|   |o-  P12
    '     P07  -o|   |o-  P11
    '     GND  -o|_13|o-  P10
    
    Es soll mir dann eine gleichzeitige Verwendung von LCD und 4x4-Matrixtastatur mit nur einem Bauteil möglich sein.
    Aktuell habe ich die Ansteuerung des LCD`s damit schon fertig!

    Da beim 16bit PCF8575 immer zwei Byte gesendet werden müssen, geht dies natürlich auch zu Lasten der Geschwindigkeit. :(
    Anfangs dauerte der 108-Zeichen-Test fast 425ms! :fie:
    27x4-16bit-I2C_Detail.png
    Inzwischen habe ich die Subroutinen aber soweit optimiert, dass der Zeichen-Test jetzt nur noch 165ms benötigt. :dance3:
    Wenn ich alles fertig habe, werde ich die Routinen dann hier auch kurz vorstellen.

    Vielleicht erstelle ich dafür aber auch einen Blog? :hmmmm:
    Mal sehen.....


    Viele Grüße,
    Cassio
     
  4. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo zusammen!

    Inzwischen konnte ich die Routinen ein weiteres Mal optimieren und nun ist die Zeichenausgabe noch schneller geworden. :D
    Der 108-Zeichen-Test liegt beim PCF8574A inzwischen bei 105ms!
    Mehr geht aber nun wirklich nicht, sonst kommt das LCD zwischendurch ins "Stolpern" und versagt den Dienst. :wink:
    Die neuen Subroutinen werde ich dann demnächst mal aktualisieren.


    Zusätzlich bin ich gerade dabei zwei getrennte Displays zu betreiben.....
    Wenn beide den gleichen Typ des I2C-Bauteils hätten, wäre das auch etwas einfacher. :wink:
    Momentan habe ich aber ein LCD(1) am 16bit I/O PCF8575 ein weiteres LCD(2) am 8bit I/O PCF8574A.

    Mit getrennten Subroutinen klappt es aber recht gut und auch mit der Geschwindgkeit bin ich sehr zu frieden.
    Momentan sieht das Ergebnis also so aus:
    27x4_doppel_I2c.jpg

    Die rechstlichen Routinen und das Testprogramm werden hier dann nach der Fertigstellung natürlich noch veröffentlicht.


    Fehlt jetzt also nur noch die 4x4-Matrixtastatur und dann sollte es komplett sein. :wink:

    Grüße,
    Cassio
     
  5. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo zusammen!

    So, nun habe ich auch meinen letzten Wunsch fertig und alles läuft so, wie ich mir das vorgestellt habe. :cool:


    Für die letzten Tests hatte ich zwei 27x4 LCD`s und eine Matrix-Tastatur am I2C Bus.
    Die Aufteilung war einen Beitrag davor schon erwähnt....
    1x PCF8575 (16 I/O) mit einem LCD (2x E) an P00-P07 und eine 4x4 Matrix-Tastatur an P10-P17
    1x PCF8574A (8 I/O) mit einem LCD (2x E)

    Das Ganze sieht dann aufgebaut so aus: 2x2704+Matrix.jpg

    Nach einigen Versuchen klappt nun auch der störungsfreie Betrieb der Matrix-Tastatur, ohne dass das LCD dabei durcheinander kommt.
    Ich hätte die Matrix zwar auch gern per externen INT gesteuert, aber dies brachte Timingprobleme mitsich.

    Die Geschwindigkeiten können sich dabei wohl auch sehen lassen.
    Hier mal ein paar Messergebnisse mit dem Analyser:
    Einmal der 108-Zeichentest---> 2x2704+Matrix_108Zeichen-Test.png



    und einmal das Auslesen der Matrixtastatur---> 2x2704+Matrix-READ.png


    Zum Schluss nun noch das Testprogramm....
    Code:
    '
    '09.01.2012
    'Cassio by AVR-Praxis.de
    'Testprogramm zum Betrieb von 2 Stück 27x4 LCD`s und Matrix-Tastatur am I2C-Bus
    '1x PCF8575 mit LCD und Matrix-Tastatur
    '1x PCF8574A mit LCD
    '
    $regfile = "m16adef.dat"
    $crystal = 16000000                                         'EXTERN !
    
    $hwstack = 128
    $swstack = 128
    $framesize = 128
    
    ' --------------------ATmega16------------------------
    '                    +---v---+
    '       (XCK/T0) PB0 |1    40| PA0 (ADC0)------Taster
    '           (T1) PB1 |2    39| PA1 (ADC1)------Taster2
    '    (INT2/AIN0) PB2 |3    38| PA2 (ADC2)
    '     (OC0/AIN1) PB3 |4    37| PA3 (ADC3)
    '           (SS) PB4 |5    36| PA4 (ADC4)
    '         (MOSI) PB5 |6    35| PA5 (ADC5)
    '         (MISO) PB6 |7    34| PA6 (ADC6)
    '          (SCK) PB7 |8    33| PA7 (ADC7)
    '              RESET |9    32| AREF
    '                VCC |10   31| GND
    '                GND |11   30| AVCC
    '              XTAL2 |12   29| PC7 (TOSC2)
    '              XTAL1 |13   28| PC6 (TOSC1)
    '          (RXD) PD0 |14   27| PC5 (TDI)
    '          (TXD) PD1 |15   26| PC4 (TDO)
    '         (INT0) PD2 |16   25| PC3 (TMS)
    ' Key_code(INT1) PD3 |17   24| PC2 (TCK)
    '         (OC1B) PD4 |18   23| PC1 (SDA)-------I2C
    '         (OC1A) PD5 |19   22| PC0 (SCL)-------I2C
    ' DCF77---(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_1011_1111                                         '1 ist Ausgang 0 ist Eingang
    Portc = &B0100_0000
    
    Ddrd = &B_1011_0011                                         '1 ist Ausgang 0 ist Eingang
    Portd = &B0100_1100                                         'auf Hi oder Low setzen
    
    
    
    Led Alias Portd.7
    Taster Alias Pina.0
    Taster2 Alias Pina.1
    
    ' ==============================================================================
    ' I2C-Config
    '$lib "i2c_twi.lbx"
    
    Config Scl = Portc.0                                        'I2C SCL
    Config Sda = Portc.1                                        'I2C SDA
    
    Config I2cdelay = 1                                         '8=107ms / 16=135ms / ca. 230kHZ
    I2cinit
    
    
    ' Subroutinen für LCD===========================================================
    Declare Sub Lcd_(byval X1 As Byte , Byval X2 As Byte , Byval Text1 As String * 27)
    Declare Sub Lcd_cls
    Declare Sub Lcd_init
    Dim Text As String * 27                                     'LCD Ausgabe
    Dim Lcd_text(27) As Byte At Text Overlay                    'ASCII-Werte der LCD Ausgabe
    Dim Pos As Byte                                             'Locate Berechnung
    Const Pcx_lcd = &H74                                        'I2C-Adresse des PCF8574A
    
    '-----------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
    
    
    ' Subroutinen für LCD und Matrix================================================
    Declare Sub Lcd16_(byval X161 As Byte , Byval X162 As Byte , Byval Text2 As String * 27)
    Declare Sub Lcd16_cls
    Declare Sub Lcd16_init
    Dim Text16 As String * 27                                   'LCD Ausgabe
    Dim Lcd16_text(27) As Byte At Text16 Overlay                'ASCII-Werte der LCD Ausgabe
    Dim Pos16 As Byte                                           'Locate Berechnung
    Const Pcx_lcd16 = &H40                                      'I2C-Adresse des PCF8575
    
    
    Declare Sub Lese_key                                        'Subroutine für Matrix-Tastatur
    Dim Key_send(2) As Byte                                     'Matrix-Tasten lesen
    Dim Key_code As Byte                                        'Scancode der Matrix-Taste
    Dim Key As String * 1                                       'Taste aus Datazeile
    
    '-----------PCF8575------------
    '             ___
    '     INT  -o|1  |o-  Vdd
    '      A1  -o|   |o-  SDA
    '      A2  -o|   |o-  SCL
    '     RS   -o|   |o-  A0
    '     R/W  -o|   |o-  Col4
    '     E2   -o|   |o-  Col3
    '     E1   -o|   |o-  Col2
    '     D4   -o|   |o-  Col1
    '     D5   -o|   |o-  Row4
    '     D6   -o|   |o-  Row3
    '     D7   -o|   |o-  Row2
    '     GND  -o|_13|o-  Row1
    
    ' ==============================================================================
    Dim Init(8) As Byte                                         'Byte-Array für LCD-Parameter
    Dim Ascii_zeichen(10) As Byte                               'getrennte ASCII-Werte zur Übermittlung
    Dim Zz As Byte                                              'Zeichenzähler
    Dim Zi As Byte                                              'Zeichen-Indexzähler
    
    
    Lcd_init                                                    'LCD zum Betrieb initialisieren
    Lcd16_init                                                  'LCD zum Betrieb initialisieren
    
    
    
    '######################## Pollin Modul : Inverted = 1 ##########################
    Config Dcf77 = Pind.6 , Timer = 1 , Timer1sec = 1 , Debug = 1 , Update = 0 , Check = 1 , Inverted = 1 , Gosub = Sectic
    
    Config Date = Dmy , Separator = .
    
    Enable Interrupts
    
    Date$ = "01.01.07"
    Time$ = "12:00:00"
    
    
    
    ' #############################################################################
    Dim I As Byte , I2 As Byte                                  'Indexzähler
    Dim Tb As Bit                                               'Toggle-Bit
    Dim Ab As Bit                                               'Anzeige-Bit
    
    Dim Dtag As Byte , Wtag As String * 10                      'Wochentag
    Dim Sync As Bit                                             'DCF-Sync
    Dim Puls As Bit                                             'Sekundenpuls
    Dim Status_old As Byte                                      'DCF-Status
    
    
    ' #############################################################################
    ' Anfangswerte:
    
    Tb = 0                                                      'Toggel-Bit auf 0
    Ab = 0                                                      'Taster-Bit auf 0
    
    Set Led                                                     'Kontroll-LED AUS
    
    
    ' ################################################
    ' #                                              #
    ' #---------------Arbeitsschleife----------------#
    ' #                                              #
    ' ################################################
    Do                                                          'Hauptschleife-Beginn
    
    Lese_key                                                    'Matrix-Tastatur prüfen/lesen
    Lcd_ 2 , 27 , Key                                           'Anzeigewert aus DATA-Zeile
    Lcd_ 2 , 17 , " / Taste= "
    Text = Str(key_code) : Text = Format(text , "000")
    Lcd_ 2 , 14 , Text                                          'Scan-Code anzeigen
    
    
    
    Dtag = Dayofweek()                                          'Wochentag ermitteln
    Wtag = Lookupstr(dtag , Wochentage)                         'Wochentag im Klartext
    
    
    
    If Puls = 1 Then                                            'Puls wird von Sectic auf 1 gesetzt
          Lcd16_ 1 , 20 , Time$                                 'Zeit anzeigen
          Lcd16_ 2 , 1 , Wtag                                   'Wochentag anzeigen
          Lcd16_ 2 , 19 , Date$                                 'Datum anzeigen
          Text16 = Time(dcf_sec)                                'DCF-Zeit anzeigen
          Lcd16_ 3 , 20 , Text16
       Lcd_ 1 , 20 , Time$                                      'Zeit anzeigen
       Lcd_ 4 , 1 , Wtag                                        'Wochentag anzeigen
       Lcd_ 4 , 19 , Date$                                      'Datum anzeigen
       Reset Puls
    Else
    End If
    
    
    
    If Status_old <> Dcf_status Then                            'Ausführen beim neuen Status
       Status_old = Dcf_status                                  'Status kopieren
       Text16 = Bin(dcf_status)                                 'in String konvertieren
       Lcd16_ 3 , 6 , Text16                                    'Statusbits binär anzeigen
       Text16 = Str(bdcf_impuls) : Text16 = Format(text16 , "000")
       Lcd16_ 4 , 14 , Text16                                   'DCF-Impulslänge anzeigen
       Text16 = Str(bdcf_pause) : Text16 = Format(text16 , "000")
       Lcd16_ 4 , 24 , Text16                                   'DCF-Pausenlänge anzeigen
    Else
    End If
    
    
    
    If Taster2 = 0 Then
       Lcd_init                                                 'Display neu initialisieren
       Lcd16_init                                               'Display neu initialisieren
          Lcd16_ 1 , 5 , "INIT 1..."
          Lcd_ 1 , 5 , "INIT 1..."
          Lcd16_ 2 , 14 , "OK !"
          Lcd_ 2 , 14 , "OK !"
          Lcd16_ 3 , 5 , "INIT 2..."
          Lcd_ 3 , 5 , "INIT 2..."
          Lcd16_ 4 , 14 , "OK !"
          Lcd_ 4 , 14 , "OK !"
       Waitms 250
       Bitwait Taster2 , Set
       Reset Tb                                                 'Toggel-Bit auf 0
       Reset Ab                                                 'Taster-Bit auf 0
    Else
    End If
    
    
    
    If Taster = 0 Then                                          'Displayanzeige wechseln
       Toggle Tb                                                'Toggle-Bit wechseln
       Reset Ab                                                 'Anzeige-Bit zurücksetzen
       Waitms 250
       Bitwait Taster , Set
    Else
    End If
    
    
    
    If Tb = 0 Then
       If Ab = 0 Then                                           'Layout einmal anzeigen
          Lcd16_cls
          Lcd16_ 1 , 1 , "Es ist jetzt "
          Lcd16_ 2 , 11 , ",  der  "
          Lcd16_ 3 , 1 , "DCF:"
          Lcd16_ 3 , 15 , "Time"
          Lcd16_ 4 , 1 , "DCF= Impulse:    Pause:    "
             Lcd_cls
             Lcd_ 1 , 1 , "Es ist jetzt"
             Lcd_ 2 , 1 , "CASSIO"
             Lcd_ 2 , 7 , "  Key: "
             Lcd_ 2 , 17 , " ? "
             Lcd_ 3 , 1 , "Test von 2x 27x4-LCD am I2C"
             Lcd_ 4 , 11 , ",  der "
          Set Ab
       Else
       End If
    Else
          For I = 1 To 4                                        'Geschwindigkeitstest aller 108 Zeichen
             For I2 = 1 To 27
                Lcd16_ I , I2 , "X"
             Next I2
          Next I
          For I = 1 To 4                                        'Geschwindigkeitstest aller 108 Zeichen
             For I2 = 1 To 27
                Lcd_ I , I2 , "Y"
             Next I2
          Next I
          Wait 1
          Tb = 0
    End If
    
    
    ' ----------------------------------------
    If _sec > 1 Then Reset Dcf_status.7                         'Sync-Bit der Softclock zurücksetzen
    
    If _sec = 1 Then
       If Dcf_status.7 = 1 Then
          Sync = 1                                              'Sync der Softclock merken
       Else
          Sync = 0                                              'Kein Sync der Softclock
       End If
    Else
    End If
    
    ' ----------------------------------------
    If Sync = 1 Then                                            'Wenn Sync der Softclock, dann...
    Lcd16_ 1 , 14 , "genau"
    Lcd_ 1 , 14 , "genau"
    Reset Led                                                   'LED EIN
    Else                                                        'wenn kein Sync, dann.....
    Lcd16_ 1 , 14 , "etwa "
    Lcd_ 1 , 14 , "etwa "
    Set Led                                                     'LED AUS
    End If
    
    
    Loop                                                        'Hauptschleife-Ende
    
    
    End                                                         'end program
    
    ' #############################################################################
    Sectic:
    Set Puls
    Return
    
    
    ' ############################################################################
    Sub Lese_key:
    
    Portc.7 = 1
    
    Key_send(1) = &H00
    Key_send(2) = &H0F
    I2creceive Pcx_lcd16 , Key_send(1) , 2 , 2
    
          Select Case Key_send(2)
             Case 14 : Key_code = 1
             Case 13 : Key_code = 2
             Case 11 : Key_code = 3
             Case 7 : Key_code = 4
             Case Else
                Key_code = 0
                Goto Key_end
          End Select
    
    
    Key_send(2) = &HF0
    I2creceive Pcx_lcd16 , Key_send(1) , 2 , 2
    
          Select Case Key_send(2)
             Case 224 : Key_code = Key_code + 0
             Case 208 : Key_code = Key_code + 4
             Case 176 : Key_code = Key_code + 8
             Case 112 : Key_code = Key_code + 12
          End Select
    
    Key_end:
    Portc.7 = 0
    
    Key = Lookupstr(key_code , Matrix)
    
    End Sub                                                     'Return
    
    
    ' #############################################################################
    Sub Lcd_(x1 As Byte , X2 As Byte , Text1 As String * 27)    'Sub zur Zeichenausgabe am Display
    $include "_2704_i2c.bas"
    
    ' #############################################################################
    Sub Lcd_cls:                                                'Sub zum löschen beider Displayhälften
    $include "_2704_CLS.bas"
    
    ' #############################################################################
    Sub Lcd_init:                                               'Sub zum initialisieren beider Displayhälften
    $include "_2704_init.bas"
    
    
    
    ' #############################################################################
    Sub Lcd16_(x161 As Byte , X162 As Byte , Text2 As String * 27)       'Sub zur Zeichenausgabe am Display
    $include "_2704_i2c_16.bas"
    
    ' #############################################################################
    Sub Lcd16_cls:                                              'Sub zum löschen beider Displayhälften
    $include "_2704_CLS_16.bas"
    
    ' #############################################################################
    Sub Lcd16_init:                                             'Sub zum initialisieren beider Displayhälften
    $include "_2704_init_16.bas"
    
    
    ' #############################################################################
    Matrix:
    Data "_" , "1" , "2" , "3" , "A" , "4" , "5" , "6" , "B" , "7" , "8" , "9" , "C" , "*" , "0" , "#" , "D"
    
    
    ' #############################################################################
    Wochentage:
    Data "    Montag" , "  Dienstag" , "  Mittwoch" , "Donnerstag" , "   Freitag" , "   Samstag" , "   Sonntag"
    
    

    ....und die Subroutinen für den PCF8575 (für den PCF8574A bitte in Beitrag #1 schauen)
    Das INIT:
    Code:
    $nocompile
    
    
    ' #############################################################################
    'Lcd_init:                                                   'Sub zum Initialisieren beider Displaycontroller
    Init(2) = &H0F
    Init(4) = &H0F
    
    
    Init(1) = &H00
    Init(3) = &H00
    I2csend Pcx_lcd16 , Init(1) , 4
    Waitms 50
    
    Init(1) = &HC3
    Init(3) = &H03
    I2csend Pcx_lcd16 , Init(1) , 4                             '03h
    Waitms 1
    I2csend Pcx_lcd16 , Init(1) , 4                             '03h
    Waitms 1
    I2csend Pcx_lcd16 , Init(1) , 4                             '03h
    Waitms 1
    Init(1) = &HC2
    Init(3) = &H02
    I2csend Pcx_lcd16 , Init(1) , 4                             '02h (4Bit Modus)
    Waitms 1
    
    
    I2csend Pcx_lcd16 , Init(1) , 4
    Init(1) = &HC8
    Init(3) = &H08
    I2csend Pcx_lcd16 , Init(1) , 4                             '28h (4 Zeilen Dispaly)
    Waitms 1
    
    Init(1) = &HC0
    Init(3) = &H00
    I2csend Pcx_lcd16 , Init(1) , 4
    Init(1) = &HCE
    Init(3) = &H0E
    I2csend Pcx_lcd16 , Init(1) , 4                             '0Eh (Select Mode)
    Waitms 1
    
    Init(1) = &HC0
    Init(3) = &H00
    I2csend Pcx_lcd16 , Init(1) , 4
    Init(1) = &HC6
    Init(3) = &H06
    I2csend Pcx_lcd16 , Init(1) , 4                             '06h (Select Mode)
    Waitms 1
    
    Init(1) = &HC0
    Init(3) = &H00
    I2csend Pcx_lcd16 , Init(1) , 4
    Init(1) = &HCC
    Init(3) = &H0C
    I2csend Pcx_lcd16 , Init(1) , 4                             '0Ch (Select Mode)
    Waitms 1
    
    Init(1) = &HC0
    Init(3) = &H00
    I2csend Pcx_lcd16 , Init(1) , 4
    Init(1) = &HC1
    Init(3) = &H01
    I2csend Pcx_lcd16 , Init(1) , 4                             '01h (Cls)
    Waitms 1
    
    End Sub
    

    ClearScreen CLS:
    Code:
    $nocompile
    
    Init(2) = &H0F
    Init(4) = &H0F
    Init(6) = &H0F
    Init(8) = &H0F
    
    'Clear Screen Anweisung
    Init(1) = &HC0
    Init(3) = &H00                                              '0h für E1 + E2 senden
    Init(5) = &HC1
    Init(7) = &H01
    I2csend Pcx_lcd16 , Init(1) , 8                             '1h für E1 + E2 senden
    Waitus 500
    
    
    'Erste Zeile, erstes Zeichen anwählen
    Init(1) = &HC8
    Init(3) = &H08                                              '8h für E1 + E2 senden
    Init(5) = &HC0
    Init(7) = &H00                                              '0h für E1 und E2 senden
    I2csend Pcx_lcd16 , Init(1) , 8
    Waitus 500
    
    End Sub
    

    Textausgabe am LCD:
    Code:
    $nocompile
    
    'Dim Pos16 As Byte                                           'Locate Berechnung
    'Dim Ascii_zeichen(10) As Byte                               'getrennte ASCII-Werte zur Übermittlung
    'Dim Zz As Byte                                              'Zeichenzähler
    'Dim Zi As Byte                                              'Zeichen-Indexzähler
    
    
    ' #############################################################################
    Text16 = Text2                                              'max.27 Zeichen String übergeben
    
    Select Case X161
    Case 1
       Pos16 = X161 + &H7E                                      'Anzeige-Charakter berechnen
       Pos16 = Pos16 + X162                                     'Anzeige-Charakter berechnen
       Gosub Lcd161                                             '1.Displaycontroller verwenden
    Case 2
       Pos16 = X161 + &HBD                                      'Anzeige-Charakter berechnen
       Pos16 = Pos16 + X162                                     'Anzeige-Charakter berechnen
       Gosub Lcd161                                             '1.Displaycontroller verwenden
    Case 3
          Pos16 = X161 + &H7C                                   'Anzeige-Charakter berechnen
          Pos16 = Pos16 + X162                                  'Anzeige-Charakter berechnen
          Gosub Lcd162                                          '2.Displaycontroller verwenden
    Case 4
          Pos16 = X161 + &HBB                                   'Anzeige-Charakter berechnen
          Pos16 = Pos16 + X162                                  'Anzeige-Charakter berechnen
          Gosub Lcd162                                          '2.Displaycontroller verwenden
    Case Else
    End Select
    
    End Sub
    
    
    ' #############################################################################
    Lcd161:                                                     'Sub zur LCD-Ausgabe auf 1.Displaycontroller
    Zz = Len(text16)
    
    Init(2) = &H0F
    Init(4) = &H0F
    Init(6) = &H0F
    Init(8) = &H0F
    
    Init(7) = Pos16 And &H0F                                    'Zeichen-StartPos16ition Bit3-0
    Init(3) = Pos16 And &HF0                                    'Zeichen-StartPos16ition Bit7-4
    Shift Init(3) , Right , 4
    Init(1) = Init(3) + &H80                                    'Bit7-4 + E1
    
    Init(5) = Init(7) + &H80                                    'Bit3-0 + E1
    I2csend Pcx_lcd16 , Init(1) , 8                             'Start-Array zum Display senden
    'Waitus 500
    
    Ascii_zeichen(1) = &H10                                     'RS-Pin HIGH setzen
    Ascii_zeichen(2) = &H0F
    Ascii_zeichen(4) = &H0F
    Ascii_zeichen(6) = &H0F
    Ascii_zeichen(8) = &H0F
    Ascii_zeichen(9) = &H00                                     'RS-Pin wieder LOW setzen
    Ascii_zeichen(10) = &H0F
    
    For Zi = 1 To Zz                                            'Zeichenlänge des Strings ermitteln
       Ascii_zeichen(1) = Lcd16_text(zi) And &HF0               'ASCII-Wert Bit7-4
       Shift Ascii_zeichen(1) , Right , 4
       Ascii_zeichen(3) = Ascii_zeichen(1) + &H10               'Bit7-4 + RS-Pin
       Ascii_zeichen(1) = Ascii_zeichen(1) + &H90               'Bit7-4 + RS + E1
    
       Ascii_zeichen(5) = Lcd16_text(zi) And &H0F               'ASCII-Wert Bit3-0
       Ascii_zeichen(7) = Ascii_zeichen(5) + &H10               'Bit3-0 + RS-Pin
       Ascii_zeichen(5) = Ascii_zeichen(5) + &H90               'Bit3-0 + RS + E1
       I2csend Pcx_lcd16 , Ascii_zeichen(1) , 10                'ASCII-Daten zum Display senden
       Waitus 400
    Next Zi                                                     'je nach Anzahl der Zeichen im String wiederholen
    
    Return
    
    
    
    ' #############################################################################
    Lcd162:                                                     'Sub zur LCD-Ausgabe auf 2.Displaycontroller
    Zz = Len(text16)
    
    Init(2) = &H0F
    Init(4) = &H0F
    Init(6) = &H0F
    Init(8) = &H0F
    
    Init(7) = Pos16 And &H0F
    Init(3) = Pos16 And &HF0
    Shift Init(3) , Right , 4
    Init(1) = Init(3) + &B0100_0000                             'E2 hinzu
    
    Init(5) = Init(7) + &B0100_0000                             'E2 hinzu
    I2csend Pcx_lcd16 , Init(1) , 8
    'Waitus 500
    
    Ascii_zeichen(2) = &H0F
    Ascii_zeichen(4) = &H0F
    Ascii_zeichen(6) = &H0F
    Ascii_zeichen(8) = &H0F
    Ascii_zeichen(9) = &H00                                     'RS-Pin wieder LOW setzen
    Ascii_zeichen(10) = &H0F
    
    For Zi = 1 To Zz
       Ascii_zeichen(1) = Lcd16_text(zi) And &HF0
       Shift Ascii_zeichen(1) , Right , 4
       Ascii_zeichen(3) = Ascii_zeichen(1) + &B0001_0000        'Bit7-4 + RS-Pin
       Ascii_zeichen(1) = Ascii_zeichen(1) + &B0101_0000        'Bit7-4 + RS + E2
    
       Ascii_zeichen(5) = Lcd16_text(zi) And &H0F
       Ascii_zeichen(7) = Ascii_zeichen(5) + &B0001_0000        'Bit3-0 + RS-Pin
       Ascii_zeichen(5) = Ascii_zeichen(5) + &B0101_0000        'Bit3-0 + RS + E2
       I2csend Pcx_lcd16 , Ascii_zeichen(1) , 10
       Waitus 400
    Next Zi
    
    Return
    

    Alle Subroutinen sind so geschrieben, dass sie jederzeit nach Aufgabe, Hardware und Herzenslust geändert bzw. angepasst werden können. :wink:


    Grüße,
    Cassio
     
  6. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo zusammen!

    Ein Letztes habe ich nun doch.... :wink:
    Für alle, die ein Arduino-Board mit Arduino-I2C LCD besitzen und verwenden möchten, habe ich jetzt auch noch die passenden Subroutinen geschrieben.

    Ausgelegt sind die Subroutinen für ein 4x20 LCD, mit einem E-Pin und schaltbarer Hintergrundbeleuchtung.
    Dafür muss im Programmkopf folgendes angegeben werden....
    (Aktualisierte Version vom 08.06.2012)
    Code:
    '**********************************************
    $include "_Arduino_I2C_declare.bas"  
    
    '**********************************************
    'Angaben zum Display einstellen! Beispiel 4x16:
    Lcd_zeilen = 4                                              'Anzahl der LCD-Zeilen eintragen!
    Lcd_spalten = 16                                            'Anzahl der LCD-Charakter angeben
    '**********************************************
    
    '**********************************************
    'TWI-Adresse des LCD-Bausteins angeben:
    Const Lcd_arduino = &H40                                    'I2C-Adresse des PCx8574(A)
    '**********************************************
    

    ....und am Ende des Programms wird dann die Subroutinen-Datei vermerkt:
    Code:
    ' #############################################################################
    $include "_Arduino_I2C_subs.bas"      
    

    Anschließend kann man im Programm mit:
    Lcda_ 1 , 1 , "Mustertext"
    die Ausgabe zum LCD schicken.

    Weil das LCD nur einen E-Pin besitzt, gehören die Zeilen 1 und 3, sowie 2 und 4 zusammen!
    Aus dem Grunde ist es also egal, ob ich im Programm (beim meinem 4x16 LCD) folgendes schreibe:
    Code:
    Lcda_ 2 , 17 , "CASSIO  "
    
       ' oder
    
    Lcda_ 4 , 1 , "CASSIO  "
    
    In beiden Fällen erfolgt die Ausgabe des Textes natürlich an der selben Stelle des Displays!
    Ist ja auch logisch! :wink:

    Da es sich bei meinem Display aber nicht um ein Arduino-LCD handelt weiß ich nicht, ob das im Original auch so ist..... gehe da aber mal von aus!
    Meinen Subroutinen ist die Schreibweise aber egal..... es wird beides berücksichtig!

    (Neu in der Version ab dem 08.06.2012)
    Die Hintergrundbeleuchtung lässt sich nun direkt mit:
    Hbl Ein
    und
    Hbl Aus
    steuern, OHNE dass das Display mit Daten aktualisiert werden muss.


    Das war es dann auch schon.... :D


    Nun noch ein Foto vom funktionstüchtigem LCD.....
    4x16_Arduino_LCD.jpg


    ....und der zugehörige Programmcode:
    (Aktualisierte Version vom 08.06.2012)
    Code:
    'Subroutinen für I2C-Arduino-LCD
    '
    $regfile = "m1284pdef.dat"
    $crystal = 12000000                                         'EXTERN !
    
    $hwstack = 128
    $swstack = 128
    $framesize = 128
    
    
    ' ------------------ATmega1284P------------------------
    '                    +---v---+
    '       (XCK/T0) PB0 |1    40| PA0 (ADC0)------Taster
    '           (T1) PB1 |2    39| PA1 (ADC1)------Taster2
    '    (INT2/AIN0) PB2 |3    38| PA2 (ADC2)------Taster_HBL
    '     (OC0/AIN1) PB3 |4    37| PA3 (ADC3)
    '           (SS) PB4 |5    36| PA4 (ADC4)
    '         (MOSI) PB5 |6    35| PA5 (ADC5)
    '         (MISO) PB6 |7    34| PA6 (ADC6)
    '          (SCK) PB7 |8    33| PA7 (ADC7)
    '              RESET |9    32| AREF
    '                VCC |10   31| GND
    '                GND |11   30| AVCC
    '              XTAL2 |12   29| PC7 (TOSC2)
    '              XTAL1 |13   28| PC6 (TOSC1)
    '          (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
    ' DCF77---(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_1011_1111                                         '1 ist Ausgang 0 ist Eingang
    Portd = &B0100_0000                                         'auf Hi oder Low setzen
    
    
    
    Led Alias Portd.7
    Taster Alias Pina.0
    Taster2 Alias Pina.1
    Taster_hbl Alias Pina.2
    
    ' ==============================================================================
    $include "_Arduino_I2C_declare.bas"
    'LCD-Funktionen sind:
    'Lcda_          = zum Ausgeben von Zeichen/Text (nur String)
    'Lcda_cls       = Clear Screen
    'Lcda_init      = LCD initialisieren
    'Hbl (Ein/Aus) = HintergrundBeLeuchtung Ein/Aus schalten
    
    
    '**********************************************
    'Angaben zum Display einstellen! Maximal 4x20:
    Lcd_zeilen = 4                                              'Anzahl der LCD-Zeilen eintragen!
    Lcd_spalten = 20                                            'Anzahl der LCD-Charakter angeben
    '**********************************************
    
    '**********************************************
    'TWI-Adresse des LCD-Bausteins angeben:
    Const Lcd_arduino = &H40                                    '4x16 LCD
    '**********************************************
    '                         PCx8574(A)
    '                             __
    '                      A0  -o|1 |o-  Vdd
    '                      A1  -o|  |o-  SDA
    '                      A2  -o|  |o-  SCL
    '                      RS  -o|  |o-  n.c. (INT)
    '                      RW  -o|  |o-  D7
    '                      E   -o|  |o-  D6
    'HBL=HintergrundBeLeuchtung-o|  |o-  D5
    '                     GND  -o|_9|o-  D4
    
    ' ==============================================================================
    ' Hardware I2C-Config
    $lib "i2c_twi.lbx"
    'Config Twi = 100000                                         'BUS-Takt,
    
    
    ' Software I2C-Config===========================================================
    'Config Scl = Portc.0                                        'I2C SCL
    'Config Sda = Portc.1                                        'I2C SDA
    
    'Config I2cdelay = 1
    
    'I2cinit
    ' ==============================================================================
    
    
    '######################## Pollin Modul : Inverted = 1 ##########################
    Config Dcf77 = Pind.6 , Timer = 1 , Timer1sec = 1 , Debug = 1 , Update = 0 , Check = 1 , Inverted = 1 , Gosub = Sectic
    Config Date = Dmy , Separator = .
    
    Enable Interrupts
    
    Date$ = "01.01.07"
    Time$ = "12:00:00"
    
    
    ' #############################################################################
    Dim I As Byte , I2 As Byte                                  'Indexzähler
    Dim Tb As Bit                                               'Toggle-Bit
    Dim Ab As Bit                                               'Anzeige-Bit
    
    Dim Dtag As Byte , Wtag As String * 10
    Dim Sync As Bit
    Dim Puls As Bit
    Dim Status_old As Byte
    
    ' #############################################################################
    ' Anfangswerte:
    
    Tb = 0                                                      'Toggel-Bit auf 0
    Ab = 0                                                      'Taster-Bit auf 0
    
    Lcda_init
    Hbl Ein
    
    ' ################################################
    ' #                                              #
    ' #---------------Arbeitsschleife----------------#
    ' #                                              #
    ' ################################################
    Do                                                          'Hauptschleife-Beginn
    
    If Taster_hbl = 0 Then                                      'Taster Hintergrundbeleuchtung
       Hbl Ein
    Else
       Hbl Aus
    End If
    
    
    
    If Puls = 1 Then                                            'Puls wird von Sectic auf 1 gesetzt
       Dtag = Dayofweek()                                       'Wochentag ermitteln
       Wtag = Lookupstr(dtag , Wochentage)                      'Wochentag im Klartext
          Lcda_ 1 , 9 , Time$                                   'Zeit anzeigen
          Lcda_ 2 , 1 , Wtag                                    'Wochentag anzeigen
          Lcda_ 2 , 9 , Date$                                   'Datum anzeigen
          Text = Time(dcf_sec)                                  'DCF-Zeit anzeigen
          Lcda_ 3 , 9 , Text
       Reset Puls
    Else
    End If
    
    
    If Status_old <> Dcf_status Then                            'Ausführen beim neuen Status
       Status_old = Dcf_status                                  'Status kopieren
       Text = Bin(dcf_status)                                   'in String konvertieren
       Lcda_ 4 , 9 , Text                                       'Statusbits binär anzeigen
    Else
    End If
    
    
    
    If Taster2 = 0 Then                                         'CLS und Zähler-Test
       Hbl Aus
       Lcda_init                                                'Display neu initialisieren
       Waitms 250
       Bitwait Taster2 , Set
       Hbl Ein
          For I = 0 To 255                                      'Variablenausgabe-Test
          Text = Str(i)                                         'Binär zu String wandeln
          Lcda_ 1 , 7 , Text
          Lcda_ 1 , 23 , Text                                   'entspricht 3 , 7
          Lcda_ 2 , 7 , Text
          Lcda_ 2 , 23 , Text                                   'entspricht 4 , 7
          Next I
       Waitms 500
       Lcda_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                                                'Toggle-Bit wechseln
       Reset Ab                                                 'Anzeige-Bit zurücksetzen
       Waitms 250
       Bitwait Taster , Set
    Else
    End If
    
    
    If Tb = 0 Then
       If Ab = 0 Then                                           'Layout einmal ausgeben
          Lcda_cls
          Lcda_ 1 , 1 , "Uhrzeit"
          Lcda_ 2 , 4 , " der "
          Lcda_ 1 , 17 , "DCF_sec="                             'entspricht 3 , 1
          Lcda_ 2 , 17 , "CASSIO  "                             'entspricht 4 ,1
          Set Ab
       Else
       End If
    
    Else
       Lcda_cls
       Lcda_ 1 , 1 , "1234567890123456"
       Lcda_ 2 , 1 , "23456789012345674567890123456789"
    '(
          For I = 1 To 4                                        'Geschwindigkeitstest aller 64 Zeichen
             For I2 = 1 To 16
                Lcda_ I , I2 , "X"
             Next I2
          Next I
    ')
          Wait 3
          Tb = 0
    End If
    
    
    ' ----------------------------------------
    If _sec > 1 Then Reset Dcf_status.7                         'Sync-Bit der Softclock zurücksetzen
    
    If _sec = 1 Then
       If Dcf_status.7 = 1 Then
          Sync = 1                                              'Sync der Softclock merken
       Else
          Sync = 0                                              'Kein Sync der Softclock
       End If
    Else
    End If
    ' ----------------------------------------
    If Sync = 1 Then                                            'Wenn Sync der Softclock, dann...
    Lcda_ 1 , 8 , "="
    Reset Led                                                   'LED EIN
    Else                                                        'wenn kein Sync, dann.....
    Lcda_ 1 , 8 , ":"
    Set Led                                                     'LED AUS
    End If
    
    Loop                                                        'Hauptschleife-Ende
    
    
    End                                                         'end program
    
    ' #############################################################################
    Sectic:
    Set Puls
    Return
    
    
    ' #############################################################################
    $include "_Arduino_I2C_subs.bas"
    
    
    ' #############################################################################
    Wochentage:
    Data "Mon" , "Die" , "Mit" , "Don" , "Fre" , "Sam" , "Son"
    


    Jetzt folgen noch die einzelnen Dateien.....
    (Aktualisierte Version vom 08.06.2012)

    Die Datei mit den Deklarationen und Variablen: Den Anhang _Arduino_I2C_declare.bas betrachten

    Die Datei mit allen Subroutinen: Den Anhang _Arduino_I2C_subs.bas betrachten



    FERTIG ! :cool:


    Viel Spaß damit....
    Cassio
     
  7. riesen

    riesen Mitglied

    Registriert seit:
    10. September 2010
    Beiträge:
    108
    Zustimmungen:
    0
    Hallo Cassio

    Vielen Dank für deinen Code zur Ansteuerung von I2C-Arduino-LCD's. Ich hatte mit dem Code von Kent Andersson
    auch Probleme.

    Damit die Sache bei mir aber funktionierte, musste ich noch folgende Anpassungen machen:
    - Meine Arduino-Display sind auf die Adresse &H4E eingestellt
    - Nach dem Lcda_init musste ich einen Waitms 500 einfügen, da sonst ein gleich folgender Lcda_ fehlerhafte Zeichen anzeigt
    - Die Konstanten für die Hintergrundbeleuchtung sind bei mir gerade umgekehrt: AUS=0, EIN=8

    So funktioniert dann aber alles super!

    Deine Tippps und Code-Schnippsel machen viele Spass und sind sehr lehrreiche. Nochmals vielen Dank! Weiter so :) !!

    Viele Grüsse aus der Schweiz
    Thomas
     
  8. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo Thomas!

    Willkommen im AVR-Praxis Forum! :ciao:

    Freut mich, dass dir der Programmcode geholfen hat und dein Display nun funktioniert.

    Wie ich ja schon geschrieben hatte, habe ich kein Arduino Board zum Ausprobieren gehabt.
    Deine Anmerkungen werde ich aber gern in die Code`s mit einpflegen!

    Dann bekommt das INIT am Ende besser noch ein "Waitms 500" und im Programmbeispiel tausche ich die Konstanten für AUS und EIN.
    Die Konstante für die I2C-Adresse des Arduino-LCD`s kann ja jeder selber nach belieben anpassen. :wink:


    Grüße und viel Spaß weiterhin,
    Cassio


    EDIT:
    Änderungen wurden im jeweiligen Programmcode durchgeführt!
     
  9. The_Scientist

    The_Scientist Neues Mitglied

    Registriert seit:
    26. Februar 2011
    Beiträge:
    91
    Zustimmungen:
    1
    Ort:
    Country Club Legetafo in Ethiopia
    Sprachen:
    BascomAVR, C#, Assembler
    Hallo Cassio,

    ich habe gerade Deinen Code ausprobiert und bin begeistert....
    Fuer mein Projekt ( http://www.avr-praxis.de/forum/showthread.php?2279-Anzeige-der-Netzfrequenz-als-Grapfik-auf-DG-12232 ) wollte ich ja eh ein zweites Display via TWI/I2C ansteuern...
    Mit dem Code von Kent hatte ich auch so meine Probleme....nach einiger Zeit haengte sich bei mir das Display immer auf....

    Jetzt habe ich auch wieder zuversicht fuer mein anderes Projekt : "MyHouseGoesDigital" Hier wollte ich alle Displays via I2C an die Controller anbinden, da fuer den direkten Anschluss mir Port-Pin's fehlen....aber mit dem Problemen die ich mit Kent's code hatte, habe ich das Projekt auf Eis gelegt....jetzt werde ich es mal wieder 'auftauen" ;-)


    LG aus Addis

    Klaus
     
  10. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo Klaus!

    Na, dann mal los.....
    Hol das alte Projekt wieder raus und auf gehts. :wink:

    Du kannst die einzelnen Programmcode`s für das INIT, den CLS und das Schreiben auch in eine Datei packen und diese dann per $INCLUDE hinzuladen.
    Es müssen also nicht drei einzelne Dateien sein. Das macht den Programmcode noch etwas übersichtlicher und man hat alle Routinen in einer Datei zusammen.

    Ich hatte zwischenzeitlich auch schon mal damit angefangen ein GLCD via I2C direkt zu steuern..... aber das bringt nichts!
    Es ist einfach zu langsam und von daher habe ich es erst mal gelassen. :wink:


    Dann mal viel Spaß damit!
    Cassio
     
  11. riesen

    riesen Mitglied

    Registriert seit:
    10. September 2010
    Beiträge:
    108
    Zustimmungen:
    0
    Hallo Cassio

    Ich habe doch noch ein kleines Problem mit dem Code entdeckt. Wenn ich einen String mit 16 Zeichen anzeigen will,
    erscheint mal gar nichts auf dem Display. Ein Text bis 15 Zeichen klappt wunderbar. Den Code habe ich mal untersucht,
    auf die Schnelle aber keinen Fehler gefunden, aber vielleicht ist es einfach auch scho zu spät am Abend :) ....

    Hast du eine Idee zur Lösung des Problems?

    Viele Grüsse
    Thomas
     
  12. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo Thomas!

    Hm.... so auf die Schnelle (und zur späten/frühen Stunde) fällt mir da nun auch nichts zu ein! :hmmmm:

    Ich habe eben noch mal geschaut.....
    aber ich habe standardmäßig den Text-Ausgabe-String gleich für 20 Zeichen angegeben.
    Von daher sollte es eigentlich passen!

    Wie schon mal erwähnt..... mangels Hardware kann ich das leider nicht am "lebenden Objekt" ausprobieren.

    Ich hätte da so eine Idee:
    Startadresse ab dem 16.Zeichen....
    Nur leider kann ich es nicht übeprüfen.

    Wenn du magst, dann eröffne doch mal in diesem Bereich einen neuen Thread, beschreibe noch mal kurz das Problem, stelle deinen Programmcode dort ein und wir schauen mal, wo der (Oster)hase im Pfeffer liegt. :wink:


    Grüße und einen fröhlichen Ostermontag,
    Cassio
     
  13. riesen

    riesen Mitglied

    Registriert seit:
    10. September 2010
    Beiträge:
    108
    Zustimmungen:
    0
    Guten Ostermontag Cassio

    Ja, der betreffende Code ist ja eigentlich nur ein LCDA_ 1, 1, "1234567890123456" Befehl. Lasse ich die hinterste "6" weg,
    funktioniert die Anzeitge problemlos. Na ja, ist ja nicht sooo weltbewegend, wenn ich den String in zwei Teilen anzeige,
    klappt es auch wunderbar. Es muss also irgendwie mit der Gesamtlänge des anzuzeigenden Strings zusammenhängen.
    Deine Bemerkung mit der Startadresse ab dem 16. Zeichen habe ich nicht ganz verstanden....

    Auch noch schöne Nachosterngrüsse
    Thomas
     
  14. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo Thomas!

    Hm... seltsam!
    Was passiert denn, wenn du: LCDA_ 1 , 16 , "A" zum Display sendest?
    Wird das A dann angezeigt, oder gibt es dann auch Probleme?

    Hilf mir doch mal auf die Sprünge.....
    Hat so ein standard Arduino-LCD eigentlich 4x16 oder 4x20 Zeichen? :hmmmm:

    Wie ich in meinem Beispiel schon geschrieben habe ist es von der Berechnung der Charakter-Startadresse eigentlich egal, ob du zum Beispiel
    LCDA_ 1 , 21 , "....."
    oder
    LCDA_ 3 , 1 , "....."
    schreiben würdest.

    Könntest du das für mich vielleicht mal ausprobieren?

    Folgende Ergebnisse wären interessant....
    Wenn es ein 4x20 Zeichen LCD ist:
    Code:
    Lcda_ 1 , 1 , "A"
    Lcda_ 1 , 20 , "B"
    
    Lcda_ 3 , 1 , "C"
    Lcda_ 3 , 20 , "D"
    
    Wait 3
    
    Lcda_ 2 , 1 , "E"
    Lcda_ 2 , 20 , "F"
    
    Lcda_ 4 , 1 , "G"
    Lcda_ 4 , 20 , "H"
    
    Wait 5
    Lcda_cls
    
    Lcda_ 1 , 1 , "1234567890123456789012345678901234567890"
    Lcda_ 2 , 1 , "1234567890123456789012345678901234567890"
    
    Sollte es ein 4x16 LCD sein, dann kürze bitte die Angaben von 20 auf 16 bzw. "12345678901234567890123456789012"

    Danke, für deine Hilfe!

    Grüße,
    Cassio
     
  15. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map

    Hallo Thomas!

    Was mir auf Grund deiner Bemerkung eben eingefallen ist....
    Es könnte natürlich auch am zeitlichen Faktor liegen, der sich bei dir ab dem 16.Zeichen bemerkbar macht.

    Probiere doch mal den folgenden Code
    und ersetze ihn gegen den alten Programmcode in der LCA_I2C.bas !
    Code:
    $nocompile
    
    Dim Pos As Byte                                             'Locate Berechnung
    Dim Ascii_zeichen(5) As Byte                                'getrennte ASCII-Werte zur Übermittlung
    Dim Zz As Byte                                              'Zeichenzähler
    Dim Zi As Byte                                              'Zeichen-Indexzähler
    
    ' #############################################################################
    'Sub Lcd_(x1 As Byte , X2 As Byte , Text1 As String * 20)
    
    Text = Text1                                                'max.40 Zeichen String übergeben
    
    Select Case X1
    Case 1
       Pos = X1 + &H7E                                          'Anzeige-Charakter berechnen
       Pos = Pos + X2                                           'Anzeige-Charakter berechnen
       Gosub Lcd1                                               '1.Displaycontroller verwenden
    Case 2
       Pos = X1 + &HBD                                          'Anzeige-Charakter berechnen
       Pos = Pos + X2                                           'Anzeige-Charakter berechnen
       Gosub Lcd1                                               '1.Displaycontroller verwenden
    Case 3
       Pos = X1 + &H8C                                          'Anzeige-Charakter berechnen
       Pos = Pos + X2                                           'Anzeige-Charakter berechnen
       Gosub Lcd1                                               '1.Displaycontroller verwenden
    Case 4
       Pos = X1 + &HCB                                          'Anzeige-Charakter berechnen
       Pos = Pos + X2                                           'Anzeige-Charakter berechnen
       Gosub Lcd1                                               '1.Displaycontroller verwenden
    Case Else
    End Select
    
    End Sub
    
    '          PCF8574A
    '             __
    '      A0  -o|1 |o-  Vdd
    '      A1  -o|  |o-  SDA
    '      A2  -o|  |o-  SCL
    '     RS----o|  |o-  n.c. (INT)
    '     RW----o|  |o----D7
    '     E-----o|  |o----D6
    '  Light----o|  |o----D5
    '     GND  -o|_9|o----D4
    
    ' #############################################################################
    Lcd1:                                                       'Sub zur LCD-Ausgabe auf 1.Displaycontroller
    Zz = Len(text)
    
    Init(2) = Pos And &HF0                                      'Zeichen-Startposition Bit7-4
    Init(2) = Init(2) + Hbl
    
    Init(4) = Pos And &H0F                                      'Zeichen-Startposition Bit3-0
    Shift Init(4) , Left , 4
    Init(4) = Init(4) + Hbl
    
    
    Init(1) = Init(2) + &H04                                    'Bit7-4 + E1
    Init(3) = Init(4) + &H04                                    'Bit3-0 + E1
    I2csend Lcd_arduino , Init(1) , 4                           'Start-Array zum Display senden
    Waitus 900
    
    
    Ascii_zeichen(5) = &H00 + Hbl
    
    For Zi = 1 To Zz                                            'Zeichenlänge des Strings ermitteln
       Ascii_zeichen(1) = Lcd_text(zi) And &HF0                 'ASCII-Wert Bit7-4
       Ascii_zeichen(1) = Ascii_zeichen(1) + Hbl
       Ascii_zeichen(2) = Ascii_zeichen(1) + &H01               'Bit7-4 + RS-Pin
       Ascii_zeichen(1) = Ascii_zeichen(1) + &H05               'Bit7-4 + RS + E1
    
       Ascii_zeichen(3) = Lcd_text(zi) And &H0F                 'ASCII-Wert Bit3-0
       Shift Ascii_zeichen(3) , Left , 4
       Ascii_zeichen(3) = Ascii_zeichen(3) + Hbl
       Ascii_zeichen(4) = Ascii_zeichen(3) + &H01               'Bit3-0 + RS-Pin
       Ascii_zeichen(3) = Ascii_zeichen(3) + &H05               'Bit3-0 + RS + E1
       I2csend lcd_arduino , Ascii_zeichen(1) , 5                   'ASCII-Daten zum Display senden
       Waitus 900
    Next Zi                                                     'je nach Anzahl der Zeichen im String wiederholen
    
    Return
    

    Grüße,
    Cassio
     
  16. riesen

    riesen Mitglied

    Registriert seit:
    10. September 2010
    Beiträge:
    108
    Zustimmungen:
    0
    Hallo Cassio

    Vielen Dank für dein "Mitdenken". Du hast mich auf Ideen gebracht, wie ich das Problem
    eingrenzen kann. Folgendes Ergebnis auf einem 16 Zeichen Display:
    - Lcda 1, 1, "0123456789012345" = Keine Anzeige
    - Lcda 1, 2, "123456789012345" = Korrekte Anzeige aller Zeichen von Position 2 an

    Es können also 15 Zeichen von Position 2 an sauber angezeigt werden, 16 Zeichen von
    Position 1 an ergibt keine Anzeige. Dein Beispiel des Lcda 1, 16, "A" wir auch korrekt
    angezeigt.

    Eine Stardard-Arduiono Display gibt es meiner Meinung nach nicht. Aber meistens
    werden 2x16 oder 4x20 angeboten, oft gleich mit einem I2C-Controller angeflanscht.
    Gib doch mal auf ebay.com die Suche nach "Arduino I2C" ein, da siehst du, was da
    oft verkauft wird.

    Vielen Dank auf Dir!!!!!

    Grüsse aus der Schweiz
    Thomas
     
  17. riesen

    riesen Mitglied

    Registriert seit:
    10. September 2010
    Beiträge:
    108
    Zustimmungen:
    0
    Nachtrag:
    Hab eben noch weitere Tests gemacht, auch mit einem 4-Zeilen Display:

    Es können scheinbar generell keine Strings länger als 15 Zeichen angezeigt werden -> keine Anzeige bei >15 Zeichen
     
  18. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo Thomas!

    Jetzt bin ich leider nur teilweise schlauer geworden. :wink:

    Was hast du denn nun für ein Display?
    2x16 oder 4x16?
    Ist das selbst gebaut oder war das eine fertige Einheit?

    Momentan weiß ich nicht, warum du zwar auf direktem Wege das sechzehnte Zeichen fehlerfrei darstellen kannst, aber in der Folge nach dem Fünfzehnten geht gar nichts mehr. :hmmmm:

    Es scheint fast so, als würde es ein Problem des Displaycontrollers sein.
    Die Berechnung der Startposition für das 16. Zeichen passt ja schließlich.
    Nur wenn das Display von der ersten Startadresse selber weiterzählen soll, kommt irgendwas durcheinander.
    Von daher wären ein paar näheren Angaben zur Hardware ggf. schon hilfreich.


    Grüße,
    Cassio
     
  19. riesen

    riesen Mitglied

    Registriert seit:
    10. September 2010
    Beiträge:
    108
    Zustimmungen:
    0
    Weiterer Nachtrag :)

    Habe noch mit einem 20-Zeichen Display probiert, hinsichtlich der Anzeige von 16-Zeichen-String gleiches
    Ergebinis.

    Habe beim 20-Zeichen Display aber auch das Problem, dass:
    Lcda 3, 1, "A" auf Zeile 1 Position 17
    Lcda 4, 1, "A" auf Zeile 2 Position 17
    angezeigt wird......

    Was übersehe ich?

    Nochmals schon mal vielen Dank an Dich!!!
     
  20. Cassio

    Cassio Moderator

    Registriert seit:
    29. Oktober 2008
    Beiträge:
    4.023
    Zustimmungen:
    15
    Ort:
    Region Hannover
    Sprachen:
    BascomAVR
    Map
    Hallo Thomas!

    Du übersiehst gar nichts. :D

    Das ist eigentlich schon logisch.....
    Darum hatte ich ja auch im ursprünglichen Thread gleich folgendes geschrieben:
    Code:
    Lcda_ 2 , 17 , "CASSIO  "
    
       ' oder
    
    Lcda_ 4 , 1 , "CASSIO  "
    
    Die Zeilen 1 und 3 werden vom selben Controller angesteuert.
    Für die Zeilen 2 und 4 ist der zweite Controller zuständig.
    Daher kommt dieser Effekt.

    Es fragt sich jetzt nur, warum geht es "rückwärts"... also LCDA_ 3 , 1 angeben und auf LCDA_ 1 , 17 erfolgt die Anzeige....
    aber nicht vorwärts.

    Irgendwie scheint er die Startadressen der Zeichen auf andere Weise zu verarbeiten.
    Hast du kein Datenblatt? Wenigstens von einem der Display`s?
    HD44780 kompatibel sollen sie meistens ja sein...... aber eben meistens nur fast!

    Grüße,
    Cassio
     

Diese Seite empfehlen

  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)