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

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 
Wertungen: developerx

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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: Anhang anzeigen _Arduino_I2C_declare.bas

Die Datei mit allen Subroutinen: Anhang anzeigen _Arduino_I2C_subs.bas



FERTIG ! :cool:


Viel Spaß damit....
Cassio
 

riesen

Mitglied
10 Sep 2010
108
1
16
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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!
 

The_Scientist

Neues Mitglied
26 Feb 2011
91
1
0
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

riesen

Mitglied
10 Sep 2010
108
1
16
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

riesen

Mitglied
10 Sep 2010
108
1
16
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
.....wenn ich den String in zwei Teilen anzeige,
klappt es auch wunderbar.

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
 

riesen

Mitglied
10 Sep 2010
108
1
16
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
 

riesen

Mitglied
10 Sep 2010
108
1
16
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
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

riesen

Mitglied
10 Sep 2010
108
1
16
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!!!
 

Cassio

Aktives Mitglied
29 Okt 2008
4.027
17
38
Region Hannover
Sprachen
BascomAVR
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
 

Ü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!


     Spende uns! (Paypal)