Problem, 27x4 LCD via PCF8574 und I2C ansteuern

Status
Für weitere Antworten geschlossen.

Cassio

Aktives Mitglied
29. Okt. 2008
4.027
17
38
Region Hannover
Sprachen
  1. BascomAVR
Problem wurde inzwischen gelöst, daher wurde dieser Beitrag geschlossen!
Näheres zum Thema erfahrt ihr HIER !





Hallo zusammen!

In laufe meiner "Weiterentwicklung" des RFID-Öffners wollte ich mir aus einem "alten" 27x4 LCD eine neue Serviceeinheit mit 8 Tasten zusammen stellen.

Da der Betrieb des kleinen 16x2 LCD am I2C-Bus problemlos funktionierte und laut "Kent Andersson" auch LCD`s mit zwei E-Leitungen verwendet werden können, habe ich mir gleich eine passende Platine erstellt.

Hier mal das Layout:
I2C-27x4-LCD.gif


und hier die echte Platine:
a_DSCF0907.jpg


Die I2C-Platine kann nun als Sandwich-Modul auf der Rückseite des LCD`s aufgesteckt werden.
Sie bietet ein PCF8574(A) für die 2x4 Tastenmatrix am LCD,
einen weiteren PCF8574(A) für das LCD selbst und
einen P82B96 als I2C-Extender, der für eine Leitungslänge bis 100 Meter ausgelegt ist und obendrein alles mit 5V versorgen kann.

a_DSCF0909.jpg a_DSCF0910.jpg a_DSCF0911.jpg


Soweit hat auch alles prima funktioniert....
Leider gelingt es mir nicht, das LCD zum ordnungsgemäßen Betrieb zu überreden. :mad:

Inzwischen habe ich einige Tests durchgeführt und kann daher mit Sicherheit sagen, dass es nicht am LCD liegt und meine "Bus-Platine" ebenfalls in Ordnung ist.

Es kann also nur noch an der Software liegen.... :rolleyes:

Hier mal ein (unzensierter) Auszug, vom Einbinden der LIB`s:


CodeBox bascom


' ==============================================================================
' I2C-Config
Config Scl = Portc.5 'I2C SCL
Config Sda = Portc.4 'I2C SDA

Config I2cdelay = 1

I2cinit


' I2C Matrixtastatur (Kent Andersson)------------------------
$lib "key_i2c.lib" 'LIB für I2C-Matrixtastatur
$external _key_code 'Externe Routine

'*****WICHTIG !*************************************************
'* Die Funktion "_key_scan", in der LIB "key_i2c.lib", MUSS ab BASCOM Ver. 2.0.3.0 auf _key_code geändert werden!
'* Ab BASCOM 2.0.3.0 dürfen Funktionen und Variablen NICHT mehr den selben Namen besitzen!
'* Bitte folgendes in der LIB ändern=
'* [_Key_code]
'* _Key_code:
'* Das war es dann auch schon !
'*****WICHTIG !*************************************************

Const Pcf8574_kbd = &H72 'I2C-Adresse des PCF8574A
!rcall _Key_Init 'Initialisierung aufrufen

Dim _key_scan As Byte 'Variable für Tastenausgabe



' I2C LCD (Kent Andersson)-----------------------------------
$lib "Lcd_i2c.lib" 'LIB für I2C-LCD
'$lib "Lcd_i2c_oi.lib"
Const Pcf8574_lcd = &H74 'I2C-Adresse des PCF8574A


' Configuriere das LCD
'Config Lcd = 40 * 4
'Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portc.0 , E2 = Portc.1 , Rs = Portc.2

'Dim ___lcdno As Byte


Dim _lcd_e As Byte


_lcd_e = 128
'___lcdno = 0
'Initlcd
Cursor Off
Cls

_lcd_e = 64
'___lcdno = 1
'Initlcd
Cursor Off
Cls


Aus "Verzweiflung" habe ich mir sogar schon die LIB vorgenommen und versucht durch kleine Änderungen das INIT des LCD`s so zu manipulieren, dass es vielleicht funktioniert.
Leider Fehlanzeige. :bawling:


Hat vielleicht jemand eine Idee, oder gar eine Lösung zu dem Problem?

Grüße,
Cassio
 
Hallo Cassio,

verwendest Du den HW-TWI des Mega oder den SW-TWI von BASCOM?
Damit BASCOM auf die HW geht musst Du $lib "i2c_twi.lbx" einbinden.
Gemacht oder gewollt? Vielleicht deshalb ein Timing Thema ?!?!?

Grüße,
Markus
 
Hallo Markus!

Ich verwende den Mega8 mit HW I2C, also
PortC.4 (SDA)
und
PortC.5 (SCL)

Inzwischen habe ich schon so viel getestet, dass ich deine Frage nicht mehr genau beantworten kann, ob ich die LIB schon einmal zusätzlich mit eingebunden hatte. ;)

Gewollt war es zu Beginn, dass ich diese LIB nicht mit eingebunden habe.
Dies resultierte aus den Tests und Erfahrungen mit meiner ersten Service-Einheit für den RFID-Öffner.

Ich kann die Platine aber gleich noch mal auspacken und es mit der LIB noch mal probieren.
Moment.... ;)

Gruß,
Cassio
 
Hallo Cassio,

wenn Du die LIB nicht einbindest dann macht BASCOM eine Softwareemulation für den I2C Bus und verwendet die beiden PIN's als normale IO-Pin's!

Grüße,
Markus
 
Hallo Markus!

Ich habe mir eben mal auf die Schnelle den Testausbau wieder hergestellt.
Nun ist mir auch wieder eingefallen, dass ich es schon einmal probiert hatte, denn die Fehlermeldung kenne ich schon. ;)

Sobald ich die LIB "i2c_twi.lbx" mit einbinde, bekomme ich zig mal die Fehlermeldung:
Error : 61 Line : 237 Label not found [_I2C_HP_DELAY ] , in File :......

Ich habe die LIB aber bei meinem RFID-Öffner auch nicht verwendet und wenn ich an meine neue Platine das kleine 16x2 LCD anschließe, funktioniert auch das auf anhieb.

Daher denke ich mal dass es am INIT liegen müsste, dass durch die "lcd_i2c.lib" von Kent Andersson erstellt wird.

Gruß,
Cassio
 
Hi Markus!

Ich habe meinem Programm einfach mal das Label "_I2C_HP_DELAY" gegeben, damit beim kompilieren keine Fehlermeldung mehr produziert wird und ich das Programm flashen kann......

Leider funktioniert es damit auch nicht. :eek:

Also wieder zurück zum "Anfang".


Ich kann meinen unzensierten Testcode auch hier gern mal einstellen.
Ist durch die vielen Versuche aber etwas "wild". ;)


CodeBox bascom

'
$regfile = "m8def.dat"
'$crystal = 14745600 '14,7456MHz für gerade Baudwerte
'$crystal = 12000000 'extern Frequenz (Baud-Fehler 0,16%)
$crystal = 8000000

$hwstack = 64
$swstack = 64
$framesize = 64

$baud = 19200

' ================================================
' Bestimme die Ein- und Ausgänge

' PD.0 = RxD
' PD.1 = TxD
' PD.2 = INT0 (I2C)
' PD.3 =
' PD.4 = LCD-DB4
' PD.5 = LCD-DB5
' PD.6 = LCD-DB6
' PD.7 = LCD-DB7
Ddrd = &B1111_0010 '1 ist Ausgang 0 ist Eingang
Portd = &B0000_1101 'auf Hi oder Low setzen

'PC.0 = LCD-E1
'PC.1 = LCD-E2
'PC.2 = LCD-RS
'PC.3 =
'PC.4 = SDA
'PC.5 = SCL
Ddrc = &B11_0_111 '1 ist Ausgang 0 ist Eingang
Portc = &B00_1_000 'auf Hi oder Low setzen

'PB.0 =
'PB.1 =
'PB.2 =
'PB.3 = _MOSI
'PB.4 = _MISO
'PB.5 = _SCK
'PB.6 = _XTAL1
'PB.7 = _XTAL2
Ddrb = &B011 '1 ist Ausgang 0 ist Eingang
Portb = &B100 'auf Hi oder Low setzen0


' ==============================================================================
' I2C-Config
Config Scl = Portc.5 'I2C SCL
Config Sda = Portc.4 'I2C SDA

Config I2cdelay = 1

I2cinit


' I2C Matrixtastatur (Kent Andersson)------------------------
$lib "key_i2c.lib" 'LIB für I2C-Matrixtastatur
$external _key_code 'Externe Routine

Const Pcf8574_kbd = &H72 'I2C-Adresse des PCF8574A
!rcall _Key_Init 'Initialisierung aufrufen

Dim _key_scan As Byte 'Variable für Tastenausgabe



' I2C LCD (Kent Andersson)***************************************************************
$lib "Lcd_i2c.lib" 'LIB für I2C-LCD
'$lib "Lcd_i2c_oi.lib"
Const Pcf8574_lcd = &H74 'I2C-Adresse des PCF8574A


' Configuriere das LCD
'Config Lcd = 40 * 4
'Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portc.0 , E2 = Portc.1 , Rs = Portc.2


'Dim ___lcdno As Byte
Dim _lcd_e As Byte


_lcd_e = 128
'___lcdno = 0
!Rcall _Init_LCD
'Initlcd
'Cursor Off
'Cls

_lcd_e = 64
'___lcdno = 1
!Rcall _Init_LCD
'Initlcd
'Cursor Off
'Cls
' ***************************************************************************************



' ================================================
' Globale Interrupts einschalten
Enable Interrupts


' ================================================
' Config für INT0 (I2C-Matrix)
Enable Int0 ' Überwache INT0
On Int0 Matrix_scan
Enable Int0



' ================================================
' Bestimme die Variablen
Dim Kb As String * 1

Dim I As Byte 'Indexzähler
Dim Z1 As Byte 'Zähler 1

Dim Puls As Bit


' #############################################################################
_lcd_e = 128
'___lcdno = 0

Locate 1 , 1
Lcd "RFID-Leser (I2C)"
Locate 2 , 1
Lcd " by Cassio "

Wait 1

Locate 1 , 1
Lcd "Zaehler I = "


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

Toggle Portb.1
Toggle Puls

If I < 255 Then
Incr I
Else
Locate 1 , 1
Lcd "Zaehler I = "
I = 0
End If


If Puls = 0 Then
_lcd_e = 128
' ___lcdno = 0
Else
_lcd_e = 64
' ___lcdno = 1
End If


Locate 2 , 1
Lcd " " ; I ; " "




If _key_scan > 0 And _key_scan < 13 Then
I = 0
Portb.1 = 1
Locate 1 , 1
Lcd "Zaehler I = "
Wait 1
Else
End If


If _key_scan > 12 Then
Portb.1 = 1
!Rcall _Init_LCD
Locate 1 , 1
Lcd "Zaehler I = "
Wait 1
Portb.1 = 0
Wait 1
Portb.1 = 1
Wait 1
Else
End If

Waitms 500

Loop 'Hauptschleife-Ende



' ################################################
' # #
' #----------------Subroutinen-------------------#
' # #
' ################################################
'--------------------------------------------------------------------Matrix_Scan
Matrix_scan:

!rcall _key_code 'externe Routine aufrufen

If _key_scan > 0 Then
Kb = Lookupstr(_key_scan , Matrix_wert) 'Wert vom Key_scan der Tastatur anpassen
Print "Key_scan= " ; _key_scan
Print "KB= " ; Kb
Else
End If

Return


End

' ------------------------------------------------------------------Data-Tabelle
Matrix_wert:
Data "Z" , "7" , "8" , "9" , "A" , "4" , "5" , "6" , "B" , "1" , "2" , "3" , "C" , "F" , "0" , "E" , "D"
Return



Gruß,
Cassio
 
Hallo Cassio,
ich hatte mal in diesem Beitrag http://www.avr-praxis.de/forum/showpost.php?p=11013&postcount=5
ein kleines Programm beschrieben, mit dem man auf einem zweiten AVR die Kommunikation sniffen kann. Wenn du den anstelle des Displays anschließt, müsstest du eigentlich sehen können, ob in beiden Fällen (direkt am Mega8 und über den PCF) die gleichen Daten gehen. Wenn das übereinstimmt, bleiben nur noch die Steuerleitungen oder tatsächlich das Timing.

HBA
 
Hallo HBA!

Danke, für den Hinweis!

Muss ich mir gleich noch mal ansehen..... vielleicht bringt es mich ja weiter.

Wie oben schon erwähnt, kann ich eigentlich Fehler am LCD oder dem PCF ausschließen.
Dafür habe ich mir extra einen Adapter gebaut:
a_DSCF0913.jpg a_DSCF0912.jpg

Mit dem Adapter kann ich einmal das 27x4 LCD direkt mit 2,54mm Raster an meinem Mega8 testen UND
mit den beiden Folienleitern greife ich an meiner Platine (hinter dem PCF) die Pins:
GND, Vcc, Vo, RS, RW, E1, E2
sowie die 4 Bit`s DB4, DB5, DB6, DB7 ab, welche ich dann an einem 16x2 LCD zugeführt habe.
Das kleine 16x2 LCD funktioniert dabei auch problemlos. :rolleyes:


Dadurch konnte ich also feststellen dass sowohl das 27x4 LCD funktioniert, als auch meine I2C-Platine.

Leider klappt es mit dem 27x4 LCD nicht am PCF...... :cool:


Hast du zufällig die "lcd_i2c.lib" ?
Da sie im Internet frei zugänglich ist, müsste ich sie ja hier auch sonst mit einstellen können. :hmmmm:

Gruß,
Cassio


PS:
Im MCS-Forum gibt es den Inhalt der LIB unter diesem LINK !
Kema (Kent Andersson) hat dort auch persönlich zu einem Problem geantwortet.....
aber auch der Hinweis hat leider keinen Erfolg gebracht.
 
Hallo !

Da es zu der LIB aus dem Link von 2005 doch einige Unterschiede gibt, stelle ich hier "meine" mal mit ein.

Vielleicht findet einer der ASM`ler ja darin die Lösung, oder einen Hinweis zur Optimierung.

Code:
copyright = Kent Andersson
www       = none
email     = kent@smmab.se
comment   = I2C LCD driver
libversion   = 1.02
date         = 31 march 2002
statement    = You are free to use this code any way you like, if you are able to optimize
statement    = it better, please send me an update on my e-mail.
history      = No known bugs.

;define a constant named PCF8574_LCD pointing to the i2c address
;dimension _lcd_e as byte to control the E-lines (4 lines LCD:s)
;_lcd_e should have one of the following values
;128 to enable E1, 64 to enable E2, 192 to enable both E1 and E2 (cls, deflcdchar) 
;Connect the following pins from PCF8574 to LCD
;
;P0 - D4
;P1 - D5
;P2 - D6
;P3 - D7
;P4 - RS
;P5 - RW (not used, set to 0 to ground for write)
;P6 - E2 (on 1 or 2 line display nc)
;P7 - E1

[_Init_LCD]
_Init_LCD:
 *BASIC: waitms 50
 ldi r16,&hc0       ; this is to make the initialization on both halfs of a 4-line LCD
 Ldi _temp1, &h03   ; at init-time I call all routines before _lcd_e is loaded into r16
 Rcall _Send_to_LCD
 *BASIC: waitms 4
 Rcall _Send_to_LCD
 Rcall _Send_to_LCD
 Ldi _temp1, &h02
 Rcall _Send_to_LCD
 Ldi _temp1, &h28
 Rcall _Write_lcd_byte  ;RS flag should to be 0, so jump directly to write byte
 Ldi _temp1, &h08
 Rcall _Write_lcd_byte
 Ldi _temp1, &h0c
 Rcall _Write_lcd_byte
 Ldi _temp1, &h01
 Rjmp _Write_lcd_byte
[END]


[_Write_lcd]
_Write_lcd:
* lds r16,{_lcd_e} 
 sbr r16,&h10                         ;set RS flag (4 high bits is used as control)
 rjmp _write_lcd_byte
_Lcd_Control:
* lds r16,{_lcd_e} 
_write_lcd_byte:
 push r24
 Swap _temp1                                
 Rcall _Write_lcd_Nibble 
 pop r24        
_Write_lcd_nibble:
 Cbr _temp1,&HF0                      ; E1, E2, RW, RS low

_Send_to_LCD:
push r26
push r27
 ldi r25,3
_send_3_times:
 *BASIC: i2csend pcf8574_LCD,_temp1
 eor _temp1,R16	                      ; Xor E1 and/or E2 to set them
@genus(250)
 ldi r26,0
_LCD_delay:
 dec R26
 brne _LCD_delay
 Dec R25
 Brne _send_3_times 
 eor _temp1,R16			       ; Xor to restore to initial state (even number of times)
pop r27
pop r26
ret

[END]


Wie in dem Link von Kent Andersson selbst geschrieben, habe ich schon das Semikolon vor "@genus(250)" entfernt......
Hat leider auch nicht den gewünschten Erfolg gebracht.


Schöne Grüße,
Cassio
 
Hallo !

Also ich habe heute noch mal so einiges probiert......
Leider ist es mir nicht gelungen das Display in Betrieb zu nehmen.

Ich lege den Versuchsaufbau erst mal wieder an die Seite.
Sollte noch jemand eine Idee haben, dann kann ich das aber sofort testen.


Grüße,
Cassio
 
Hallo !

Es lässt mich ja nicht locker...... ;)


Ich habe meinen "Spezialadapter" (zum Abgreifen der PINs des PCF) noch mal rausgeholt und alles noch mal ausprobiert.

a_DSCF0921.jpg

Ich greife also die Anschlüsse an meiner I2C-Platine ab (hinter dem PCF8574A) und führe die einzelnen PINs über das Steckbrett zum kleinen 16x2 LCD.

Wenn ich in der LIB das Semikolon vor dem "@genus(250)" entferne, dann funktioniert mein 16x2 Display auch nicht mehr (gibt nur noch wirre Zeichen aus).
Ergo habe ich es wieder eingetragen und schon läuft das kleine LCD auch wieder (wie oben auf dem Bild zu sehen ist).


Ob ich das 27x4 Display hingegen allein am PCF betreibe, oder parallel mit dem 16x2 LCD spielt dabei keine Rolle.
Es blinkt höchstens mal irgendwo ein Zeichen, der Cursor, oder eine ganze Reihe..... :rolleyes:


Inzwischen hatte ich auch laut Datenblatt mal das ganze INIT für das Display übern I2C (passend zum PCF) mal einzeln aus dem Programm gesendet und das INIT in der LIB entfernt.
Hat aber leider auch nicht funktioniert. :(

Ist doch schon seltsam....

Grüße,
Cassio
 
Hallo zusammen!

Kann mir mal einer auf die Sprünge helfen, falls ich hier einen Knoten im Hirn haben sollte? :rolleyes:


Laut Datenblatt des Displays werden Parameter übergeben, wenn RS = 0 ist.
Setze ich RS = 1, dann werden Daten übermittelt..... und ausgegeben.

Wenn ich also Parameter übermitteln möchte (RS = 0), dann muss ich doch trotzdem die entsprechende E-Leitung auf High setzen, um den richtigen Controller anzusprechen......


Ich habe also nun mal das INIT in der "Lcd_i2c.lib" gelassen und schiebe nachträglich noch mal alle Parameter via I2C zum Display ins Steuerregister, um es noch einmal "richtig" einzustellen.


Hier mal mein Codeabschnitt dazu:
Code:
'PCF8574A Pins:
' D7654_3210
'   | | | | | | | |
' B0000_0000
'   | | | | | | | |
'   | | | | | | | D4
'   | | | | | | D5
'   | | | | | D6
'   | | | | D7
'   | | | RS
'   | | RW
'   | E2
'   E1

I2cstart
I2cwbyte Pcf8574_lcd

I2cwbyte &B11000000                                         'Display löschen 0000_0001
I2cwbyte &B11000001
Waitus 250
I2cwbyte &B11000000                                         'Cursor Home
I2cwbyte &B11000010
Waitus 250
I2cwbyte &B11000000                                         'Entry Mode Set 0000_0110
I2cwbyte &B11000110
Waitus 250
I2cwbyte &B11000000                                         'Display on, Cursor off, Blink off
I2cwbyte &B11001100
Waitus 250
I2cwbyte &B11000010                                         '4Bit set
I2cwbyte &B11001010                                         '2/4 Zeilen , Inverter ein
Waitus 250
I2cwbyte &B11010000                                         'RS reset
I2cwbyte &B11010000
Waitus 250
I2cstop

Da das Display am PCF8574A hängt, habe ich die Bits entsprechend der Beschaltung angepasst.

Die 250µs Wartezeit habe ich eingebaut, weil man eigentlich das Busy-Flag abfragen soll..... Was natürlich nicht funktioniert, weil RW auf GND liegt. ;)

Laut Datenblatt müssen im 4Bit-Modus immer zwei Schreibzugriffe getätigt werden......
1.Schritt= D7...D4
2.Schritt= D3...D0

Auf diese Weise ist die oben gezeigte Routine enstanden.
Ich hänge das Datenblatt noch mal mit an.

Anhang anzeigen Text-LCDs.pdf

Vielleicht habe ich auch etwas übersehen, oder falsch verstanden. :rolleyes:

Grüße,
Cassio
 
Hi Cassio,

Kann mir mal einer auf die Sprünge helfen, falls ich hier einen Knoten im Hirn haben sollte? :rolleyes:
das glaub ich auch :D

Schau dir nochmal deine INIT-Sequenz an ... Die paßt überhaupt nicht.
Du magst wohl die richtigen Datenbytes senden aber was ist mit den
Impulsen auf dem E-Pin ?


Code:
'PCF8574A Pins:
' D7654_3210
'   | | | | | | | |
' B0000_0000
'   | | | | | | | |
'   | | | | | | | D4
'   | | | | | | D5
'   | | | | | D6
'   | | | | D7
'   | | | RS
'   | | RW
'   | E2
'   E1

....
I2cwbyte &B11000000                                         'Cursor Home
I2cwbyte &B11000010
Waitus 250
....

1.Schritt= D7...D4
2.Schritt= D3...D0

es müßte ja eigentlich so aussehen ...
Code:
....
I2cwbyte &B00000000                                         'Cursor Home D7-4
I2cwbyte &B10000000                                         'Cursor Home E-Puls
I2cwbyte &B00000000                                         'Cursor Home
I2cwbyte &B00000010                                         'Cursor Home D3-0
I2cwbyte &B10000010                                         'Cursor Home E-Puls
I2cwbyte &B00000010                                         'Cursor Home
Waitus 250
....
oder was meinst du dazu ?

Gruß
Dino
 
es müßte ja eigentlich so aussehen ...
Code:
....
I2cwbyte &B00000000                                         'Cursor Home D7-4
I2cwbyte &B10000000                                         'Cursor Home E-Puls
I2cwbyte &B00000000                                         'Cursor Home
I2cwbyte &B00000010                                         'Cursor Home D3-0
I2cwbyte &B10000010                                         'Cursor Home E-Puls
I2cwbyte &B00000010                                         'Cursor Home
Waitus 250
....
oder was meinst du dazu ?


Hallo Dino!

Ich hatte zwar schon mal mit den Zwischenschritten gearbeitet (E1+2 high, E1+2 low)....
aber nicht so, wie in deinem Beispiel.

Du meinst also, ich sollte die Daten z.B. an D7-D4 anlegen, obwohl E1+2 noch low sind..... dann das Gleiche mit E1+2 high..... und dann wieder mit low, so dass die Impulse der E-Leitungen erzeugt werden? :hmmmm:


Den letzen Schritt hatte ich bei meiner "Version" nicht gemacht.
OK, dann probiere ich das auch noch mal.
Ich habe schon so viel probiert, da kommt es auf einen Versuch mehr oder weniger auch nicht an. ;)

Hoffen wir mal, dass es die Lösung ist.


Ach so.....
Kommst du mit dem Initialisieren für den 4Bit-Modus klar (auf der ersten Seite)?
Wie meinen die das mit 3?h :confused:
Das ? bedeutet für D7-D4 = 0011 also 03h
Soll nun 03h gesendet werden, oder 33h ? :hmmmm:
Allerdings 33h mit 4Bit?

Gruß,
Cassio
 
Hallo,

hier mal ne 4-Bit Initialisierung in Assembler ...



CodeBox ASM

; ==================================================================
; ===== LCD initialisieren (4-Bit-Modus) ===========================
; ==================================================================
lcdinit:
push r16 ; r16 auf Stack retten (fuer wiederherstellung)

cbi portb,5 ; RS (PB5) loeschen => E loeschen
cbi portb,4 ; RS (PB4) loeschen => Cmd

; Powertip PC1602-E 16x2 Chr , Controller ST7066U
; 4-Bit-Modus ( D4-7 , D0-3 )
;
; === 4-Bit Init ===
; RS RW D7654 - RS 0=Cmd 1=Data , RW 0=Wr 1=Rd
; - wait >40ms
;
; - RS:0 RW:0 0b 0011 (0x3)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0010 (0x2) - FunctionSet 4Bit (1)
; - RS:0 RW:0 0b NF** (0x8) - Lines,Font (N 0=1L 1=2L , F 0=5x8Dot)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0010 (0x2) - FunctionSet 4Bit (2)
; - RS:0 RW:0 0b NF** (0x8) - Lines,Font (N 0=1L 1=2L , F 0=5x8Dot)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0000 (0x0) - DisplaySet
; - RS:0 RW:0 0b 1DCB (0xC) - Display,Cursor,Blink (0=Off / 1=On)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0000 (0x0) - Clear Display
; - RS:0 RW:0 0b 0001 (0x1)
;
; - wait >1,52ms
;
; - RS:0 RW:0 0b 0000 (0x0) - EntryMode
; - RS:0 RW:0 0b 01IS (0x6) - Inc/Dec,Shift (I 1=inc , S 0=NoShift)
;

ldi r16,7 ; 50ms ;
rcall waitx7m ; 7 x 7ms warten

; ===== 8-Bit =====
ldi r16,0x03 ; <=<=<=<=<=<=<=<= ### 0x3 ###
out portc,r16 ; Daten setzen (PC0-3 => D4-7) =0=
rcall wait580n ; >50ns warten
rcall lcdex ; EX pulsen zum uebernehmen (580ns)
rcall wait3m ; >37us warten


; * set function (SF) mode: 37us
; * Bit 0 : -
; * Bit 1 : -
; * Bit 2 : F: 0 = 5x8, 1 = 5x10 (Font)
; * Bit 3 : N: 0 = 1L, 1 = 2L (Display Lines)
; * Bit 4 : DL: 0 = 4Bit , 1 = 8Bit (Data Length)
; * Bit 5 : 1
; * Bit 6 : 0
; * Bit 7 : 0
; *
; * 00101000 : SF, 4-bit mode, 2 lines, 5x8 Font
;
ldi r16,0x28 ; 00101000 Set Function Mode (SF)
rcall lcdcmd ; ausfuehren (erstes Mal)

ldi r16,0x28 ; 00101000 Set Function Mode (SF)
rcall lcdcmd ; ausfuehren (zweites Mal)


; * set display (SD) mode: 37us
; * Bit 0 : B: 0 = off , 1 = on (turn on character blinking)
; * Bit 1 : C: 0 = off , 1 = on (turn on cursor)
; * Bit 2 : D: 0 = off , 1 = on (turn on display)
; * Bit 3 : 1
; * Bit 4 : 0
; * Bit 5 : 0
; * Bit 6 : 0
; * Bit 7 : 0
; *
; * SD: 0x20 = 00001100
; * SD: turn off display
; ldi r16,0b00100000 ; Set Display Mode (SD) 0x20
;
rcall lcdcmd ; ausfuehren
ldi r16,0x0C
rcall lcdcmd


; * clear and home (CH) : 1,52ms
; * CH: 0x01 = 00000001
; * CH: clear and home
; ldi r16,0b00000001 ; Clear and Home (CH) 0x01
;
ldi r16,0x01
rcall lcdcmd
rcall wait3m ; >1,52ms warten


; * set entry (SE) mode: 37us
; * Bit 0 : S: 0 = off , 1 = on (Display Shift)
; * Bit 1 : I/D: 0 = Dec , 1 = Inc (Crs/Dsp Move Direction)
; * Bit 2 : 1
; * Bit 3 : 0
; * Bit 4 : 0
; * Bit 5 : 0
; * Bit 6 : 0
; * Bit 7 : 0
; *
; * SE: 0x50 = 00000110
; * SE: increment display start after Write
;
ldi r16,0x06
rcall lcdcmd

pop r16 ; r16 wiederherstellen
ret ;


Da ist die Reihenfolge zu sehen.

Also ...
1. Daten-Nibble übertragen
2. ein paar Nanosekunden warten (Beruhigung der Leitungen und Busregister)
3. E-Puls erzeugen (Datenübernahme)
4. Verarbeitungszeit abwarten

Gruß
Dino
 
Hallo Dino!

Ich habe den Code mal geändert:
Code:
'PCF8574A Pins:
'  D7654_3210
'   |||| ||||
' &B0000_0000
'   |||| ||||
'   |||| |||D4
'   |||| ||D5
'   |||| |D6
'   |||| D7
'   |||RS
'   ||RW
'   |E2
'   E1

I2cstart
I2cwbyte Pcf8574_lcd

I2cwbyte &B00000000
I2cwbyte &B11000000                                         'Display löschen 0000_0001
I2cwbyte &B00000000

I2cwbyte &B00000001
I2cwbyte &B11000001
I2cwbyte &B00000001
Waitus 250
I2cwbyte &B00000000
I2cwbyte &B11000000                                         'Cursor Home
I2cwbyte &B00000000

I2cwbyte &B00000010
I2cwbyte &B11000010
I2cwbyte &B00000010
Waitus 250
I2cwbyte &B00000000
I2cwbyte &B11000000                                         'Entry Mode Set 0000_0110
I2cwbyte &B11000000

I2cwbyte &B00000110
I2cwbyte &B11000110
I2cwbyte &B00000110
Waitus 250
I2cwbyte &B00000000
I2cwbyte &B11000000                                         'Display on, Cursor off, Blink off
I2cwbyte &B00000000

I2cwbyte &B00001100
I2cwbyte &B11001100
I2cwbyte &B00001100
Waitus 250
I2cwbyte &B00000010
I2cwbyte &B11000010                                         '4Bit set
I2cwbyte &B00000010

I2cwbyte &B00001010
I2cwbyte &B11001010                                         '2/4 Zeilen , Inverter ein
I2cwbyte &B00001010
Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11010000                                         'RS reset
I2cwbyte &B00010000

I2cwbyte &B00010000
I2cwbyte &B11010000
I2cwbyte &B00010000
Waitus 250
I2cstop


Leider hatte ich mit der Variante auch kein Glück.

Was ist denn mit RS-Pin?
Der muss doch auch pulsen...... :hmmmm:

Soll ich das da noch mal mit einbauen?

Gruß,
Cassio
 
Hi Dino!

Ich habe nun mal den RS-Pin mit einbezogen:
Code:
I2cstart
I2cwbyte Pcf8574_lcd

I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Display löschen 0000_0001
I2cwbyte &B00010000

I2cwbyte &B00010001
I2cwbyte &B11000001
I2cwbyte &B00010001
Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Cursor Home
I2cwbyte &B00010000

I2cwbyte &B00010010
I2cwbyte &B11000010
I2cwbyte &B00010010
Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Entry Mode Set 0000_0110
I2cwbyte &B11010000

I2cwbyte &B00010110
I2cwbyte &B11000110
I2cwbyte &B00010110
Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Display on, Cursor off, Blink off
I2cwbyte &B00010000

I2cwbyte &B00011100
I2cwbyte &B11001100
I2cwbyte &B00011100
Waitus 250
I2cwbyte &B00010010
I2cwbyte &B11000010                                         '4Bit set
I2cwbyte &B00010010

I2cwbyte &B00011010
I2cwbyte &B11001010                                         '2/4 Zeilen , Inverter ein
I2cwbyte &B00011010
I2cstop

Es wäre wohl etwas übertrieben zu sagen, wir sind auf dem richtigen Weg......
aber zeigt schon mal Punkte und Striche an. ;)

Trotzdem blinkt noch alles munter vor sich hin (mal ein Cursor, mal eine ganze Zeile, mal 1 1/2 Zeilen......) :rolleyes:


Gruß,
Cassio
 
Hi,

Was ist denn mit RS-Pin?
Der muss doch auch pulsen...... :hmmmm:
da muß nix pulsen. RS=Register Select ... Oder nenn es einfach A0 (Adressbit 0)

Code:
'PCF8574A Pins:
'  D7654_3210
'   |||| ||||
' &B0000_0000
'   |||| ||||
'   |||| |||D4
'   |||| ||D5
'   |||| |D6
'   |||| D7
'   |||RS
'   ||RW
'   |E2
'   E1

Code:
;	=== 4-Bit Init ===
;	  RS   RW   D7654	- RS 0=Cmd 1=Data , RW 0=Wr 1=Rd
;	- wait >40ms

40ms warten (nach Power On)

;
;	- RS:0 RW:0 0b 0011 (0x3)
;	- wait >37us
;

0 0 0 0 0011 - 0x03 anlegen
1 0 0 0 0011 - E-Puls
0 0 0 0 0011 - E-Puls-Ende
37us warten

;	- RS:0 RW:0 0b 0010 (0x2) - FunctionSet 4Bit (1)
;	- RS:0 RW:0 0b NF** (0x8) - Lines,Font (N 0=1L 1=2L , F 0=5x8Dot)
;	- wait >37us
;

0 0 0 0 0010 - 1. Nibble anlegen
1 0 0 0 0010 - E-Puls
0 0 0 0 0010 - E-Puls-Ende

0 0 0 0 1000 - 2. Nibble anlegen
1 0 0 0 1000 - E-Puls
0 0 0 0 1000 - E-Puls-Ende
37us warten

;	- RS:0 RW:0 0b 0010 (0x2) - FunctionSet 4Bit (2)
;	- RS:0 RW:0 0b NF** (0x8) - Lines,Font (N 0=1L 1=2L , F 0=5x8Dot)
;
;	- wait >37us
;

0 0 0 0 0010 - 1. Nibble anlegen
1 0 0 0 0010 - E-Puls
0 0 0 0 0010 - E-Puls-Ende

0 0 0 0 1000 - 2. Nibble anlegen
1 0 0 0 1000 - E-Puls
0 0 0 0 1000 - E-Puls-Ende
37us warten

;	- RS:0 RW:0 0b 0000 (0x0) - DisplaySet
;	- RS:0 RW:0 0b 1DCB (0xC) - Display,Cursor,Blink (0=Off / 1=On)
;
;	- wait >37us
;

0 0 0 0 0000 - 1. Nibble anlegen
1 0 0 0 0000 - E-Puls
0 0 0 0 0000 - E-Puls-Ende

0 0 0 0 1100 - 2. Nibble anlegen
1 0 0 0 1100 - E-Puls
0 0 0 0 1100 - E-Puls-Ende
37us warten

;	- RS:0 RW:0 0b 0000 (0x0) - Clear Display
;	- RS:0 RW:0 0b 0001 (0x1)
;
;	- wait >1,52ms
;

0 0 0 0 0000 - 1. Nibble anlegen
1 0 0 0 0000 - E-Puls
0 0 0 0 0000 - E-Puls-Ende

0 0 0 0 0001 - 2. Nibble anlegen
1 0 0 0 0001 - E-Puls
0 0 0 0 0001 - E-Puls-Ende
1,52ms warten

;	- RS:0 RW:0 0b 0000 (0x0) - EntryMode
;	- RS:0 RW:0 0b 01IS (0x6) - Inc/Dec,Shift (I 1=inc , S 0=NoShift)

0 0 0 0 0000 - 1. Nibble anlegen
1 0 0 0 0000 - E-Puls
0 0 0 0 0000 - E-Puls-Ende

0 0 0 0 0110 - 2. Nibble anlegen
1 0 0 0 0110 - E-Puls
0 0 0 0 0110 - E-Puls-Ende
und wieder warten

Das müßte die 4Bit-Init-Sequenz für den Controller am E1-Pin.

Gruß
Dino
 
Hi,


da muß nix pulsen. RS=Register Select ... Oder nenn es einfach A0 (Adressbit 0)


Hi !

Schön......
Ich bin ja auch nur drauf gekommen, weil mir das Scope dies aber am RS-Pin anzeigt. ;)

RS liegt am PCF scheinbar immer auf LOW und wird dann mit jeder Datenübertragung auch auf HIGH geschaltet.


Seitdem ich das gemacht habe, tanzen ein paar kleine "p" über das Display.
Ist halt mal etwas anderes. :D

Letzter Code:
Code:
I2cstart
I2cwbyte Pcf8574_lcd

I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Display löschen 0000_0001
I2cwbyte &B00010000
Waitus 250
I2cwbyte &B00010001
I2cwbyte &B11000001
I2cwbyte &B00010001

Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Cursor Home
I2cwbyte &B00010000
Waitus 250
I2cwbyte &B00010010
I2cwbyte &B11000010
I2cwbyte &B00010010

Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Entry Mode Set 0000_0110
I2cwbyte &B11010000
Waitus 250
I2cwbyte &B00010110
I2cwbyte &B11000110
I2cwbyte &B00010110

Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11000000                                         'Display on, Cursor off, Blink off
I2cwbyte &B00010000
Waitus 250
I2cwbyte &B00011100
I2cwbyte &B11001100
I2cwbyte &B00011100

Waitus 250
I2cwbyte &B00010010
I2cwbyte &B11000010                                         '4Bit set
I2cwbyte &B00010010
Waitus 250
I2cwbyte &B00011010
I2cwbyte &B11001010                                         '2/4 Zeilen , Inverter ein
I2cwbyte &B00011010
'I2cwbyte &B00011000
'I2cwbyte &B11001000                                         '2/4 Zeilen , Inverter aus
'I2cwbyte &B00011000

Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11010000                                         'Display löschen 0000_0001
I2cwbyte &B00010000
Waitus 250
I2cwbyte &B00010000
I2cwbyte &B11010000
I2cwbyte &B00010000
I2cstop
 
Hallo zusammen!

Ich habe hier zwar noch so einiges ausprobiert..... aber leider bekomme ich das Display via I2C nicht zum Laufen. :rolleyes:

Um Defekte und Ähnliches auszuschließen, habe ich die Hardware noch mal überprüft.
Das (bzw. die) Display(s) sind in Ordnung, wie auf dem Bild zu erkennen ist:
(LCD per 1,27 zu 2,54 Adapter direkt am AVR)
a_DSCF0933.jpg


Anschließend habe ich getestet, ob die Programmierung mit Standarddisplays und zwei E-Leitungen funktioniert.
Dafür habe ich zwei I2C-Platinen verwendet, bei denen der PCF8574A auf die selbe Adresse "hört".
Lediglich die Anschlüsse E1 und E2 habe ich bei den Displays dann unterschiedlich angeschlossen.
a_DSCF0925.jpg

Um beide "Hälften" zu überprüfen, wird eine Variable von 0 bis 255 hochgezählt und abwechselnd auf E1 und E2 ausgegeben.
(Gerade Zahlen immer auf E1 und Ungerade immer auf E2)

Soweit funktioniert auch alles..... nur eben mit den 27x4 LCD´s am I2C nicht. :mad:


Ich lege den Aufbau nun erst mal wieder an die Seite.
Wenn doch noch jemand eine Idee, oder einen Link zur Lösung hat, dann einfach hier melden. :)

Grüße,
Cassio
 
Status
Für weitere Antworten geschlossen.

Über uns

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

User Menu

 Kaffeezeit

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

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


     Spende uns! (Paypal)