PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Display über i2c



guenter1604
03.07.2008, 18:22
Hallo,

ein 16*2 Standarddisplay soll über I2c und einen PCA9555D gesteuert werden.
Leider hilft die lcd_i2c.lib nur bedingt weiter, da Anpassungen wegen des PCAs nötig sind. Kann mir da jemand weiterhelfen, Assembler ist nicht gerade mein Steckenpferd ;-)

PicNick
03.07.2008, 19:16
Ich hab' diese .lib garnicht. Ist die zum dowloaden for free ?

guenter1604
03.07.2008, 19:44
Jepp,

guckst du hier:

http://www.mcselec.com/index.php?option=com_content&task=view&id=82&Itemid=57

PicNick
04.07.2008, 12:03
Gut, ich hab' mal geguckt.
Die LCD-I2C. LIb ist ja ergreifend einfach, er repliziert ja das LCD-Byte von Bascom einfach auf die Pins des PCF.
Es ist also nur der I2C - Sende befehl aufzubohren um die kontroll-bytes des PCA.

Wieweit die KEY_I2C sache mit dem Interrupt da hineinintegriert werden kann, hab ich mir aber noch nicht überlegt. Brauchst du das auch ?

guenter1604
04.07.2008, 12:38
Hallo Robert,

danke für deine Unterstützung. "Ergreifend einfach" hört sich gut an. Der grössere Unterschied zwischen den ICs ist eigentlich nur, daß der PCA9555D ein zusätzliches Command-Byte braucht. Mir reicht das Display völlig. Die Key_i2c Sache kann also wegfallen...

Günter

PicNick
04.07.2008, 13:56
Ja, jetzt müßt ich noch wissen, an welche Pins du konkret deine LCD angeschlossen hast

guenter1604
04.07.2008, 14:16
Hallo Robert,

IC: Display:

P0.0-> D0
P0.1-> D1
P0.2-> D2
P0.3-> D3
P0.4-> D4
P0.5-> D5
P0.6-> D6
P0.7-> D7

P1.0-> E
P1.1-> R/W
P1.2-> RS

PicNick
04.07.2008, 20:02
Uiui, das ist ein's drauf. Die Library und das Beispiel ist für 4 Bit-Anschluss ausgelegt.
Jetzt muß ich mal sehen, wie das mit Bascom und 8 Bit LCD eigentlich ist.
Ich hoffe, es brennt dir nicht unter den Nägeln, ich tu, was ich kann.

EDIT: scheint eher eine anspruchslose Sache zu sein. Da scheint mir besser, man macht gleich eine neue Lib. Ich muß noch finden, wo Bascom seine 8-Bit LCD funktions versteckt hat.

guenter1604
05.07.2008, 12:35
Hallo Robert,

8 Bit muß nicht sein! Es ist zwar so verdrahtet, aber was spricht dagegen es einfach 4 Bittig anzusteuern?

PicNick
05.07.2008, 16:10
Blindversuch, kann es leider nicht testen
ist 1:1 die lcd_i2c.lib funktionalität , aber eben für PCA
PCF8674 Pin 0- 7 ==> PCA P0.0-7




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:
;------------------------------------------------------------------------
; initialize PCA
;------------------------------------------------------------------------
*BASIC: i2cstart
*BASIC: i2cwbyte pcf8574_LCD
*BASIC: i2cwbyte &H06 ;command (write register 6)
*BASIC: i2cwbyte &H00 ; val register 6 00 -> all Output
*BASIC: i2cwbyte &HE8 ; val register 7 E8 -> 0, 1, 2 Output 3,4,5,6,7 input
*BASIC: i2cstop
;------------------------------------------------------------------------



*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:
; -----------------------------------send to PCA
*BASIC: i2cstart
*BASIC: i2cwbyte pcf8574_LCD
*BASIC: i2cwbyte &H02 ;command (write register 2)
*BASIC: i2cwbyte _temp1 ; val register 2
*BASIC: i2cstop

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 gesagt: so wie es ist, nur auf PCA

guenter1604
05.07.2008, 18:47
Hallo Robert,

Toll! hab deinen Code gleich ausprobiert.
Bascom mault aber in der Zeile:


*BASIC: i2cwbyte _temp1 ; val register 2
Invalid datatype[[0011]0], inFile blablabla
Variable not dimensioned [0->], in File
Wenn ich die Zeile auskommentiere werden keine Fehler mehr angezeigt.

Der Datentyp von _temp1 stimmt doch????

guenter1604
05.07.2008, 18:53
Selber schuld!

Kommentare in Basiczeilen natürlich mit ' und nicht mit ;

Läuft aber immer noch nicht. Bin am testen...

PicNick
05.07.2008, 19:06
Entschuldige, das mit dem Semikolon war wohl ich

Wenn's möglich ist, wär natürlich ein Test nur der I2c-übermittlung alleine hilfreich. Denn ob das LCD was zeigt, kann verschiedene Ursachen haben.

Mach ein einfaches Bascom testprogramm



DIM toggle AS BYTE

i2cstart
i2cwbyte pcf8574_LCD
i2cwbyte &H06 ;command (write register 6)
i2cwbyte &H00 ; val register 6 00 -> all Output
i2cwbyte &HE8 ; val register 7 E8 -> 0, 1, 2 Output 3,4,5,6,7 input
i2cstop
;------------------------------------------------------------------------

DO
i2cstart
i2cwbyte pcf8574_LCD
i2cwbyte &H02
i2cwbyte toggle
i2cstop
toggle = toggle XOR &HFF
Waitms 1000
LOOP




Jetzt sollten alle P0.0 - P0.7 im Sekundentakt zwischen 0 u. 5V hin un herpendeln. Das kann man auch mit Digtal-Multimeter messen

Geschieht das nicht, haben wir einen anderen Hund drinnen

guenter1604
06.07.2008, 02:10
Hallo Robert,

ganz so einfach ists nicht.

Die Initialisierung des PCA passt.
Aber dann muß das Display initialisiert werden.
Damit das Display überhaupt Daten annimmt muß der Anschluß Enable ein und ausgeschaltet werden

Laut Datasheet vom Display:


I2cstart
I2cwbyte Pcf8574_lcd
I2cwbyte &H03
I2cwbyte &H01
I2cstop
Waitms 2
I2cstart
I2cwbyte Pcf8574_lcd
I2cwbyte &H02
I2cwbyte &H3C
I2cwbyte &H00
I2cstop
Waitms 2
I2cstart
I2cwbyte Pcf8574_lcd
I2cwbyte &H03
I2cwbyte &H01
I2cstop
Waitms 2
I2cstart
I2cwbyte Pcf8574_lcd
I2cwbyte &H02
I2cwbyte &H0F
I2cwbyte &H00
I2cstop
Waitms 2
I2cstart
I2cwbyte Pcf8574_lcd
I2cwbyte &H03
I2cwbyte &H01
I2cstop
Waitms 2
I2cstart
I2cwbyte Pcf8574_lcd
I2cwbyte &H02
I2cwbyte &H01
I2cwbyte &H00
I2cstop

so. jetzt blinkt der Cursor links oben. Soweit sogut.

PicNick
06.07.2008, 11:13
verstehe, ist auch logo. Kann man auch einbauen.
Das gleiche Problem sollte ja aber auch die dzt. LIB haben, muß mal schauen, wie der sich das so vorgestellt hat.

guenter1604
06.07.2008, 23:09
Hallo Robert,

die Ansteuerung des Displays läuft jetzt:


'################################################# ##############################
'# #
'# I2C-Display mit PCA 9555D #
'# #
'# (c) Günter Gerold #
'# #
'# Zum Pin sparen kann ein LCD-Display auch an einen I2C-Bus gehängt werden #
'# Die eingebauten Bascom-Befehle gehen (noch) nicht #
'# Der Zeilenumbruch erfolgt automatisch #
'################################################# ##############################

$regfile = "m8def.dat"
$crystal = 8000000

Config Scl = Portc.5 'Configure i2c SCL
Config Sda = Portc.4
Const Pca9555_lcd = &H40 'Addresse des ICs

Declare Sub Config_To_lcd(byval Configbyte As Byte)
Declare Sub Data_to_lcd(byval Databyte As Byte)

Dim I As Byte
Dim Puffer As Byte
Dim Text As String * 16
Dim Textarr(16) As Byte At Text Overlay

I2cstart 'Hier werden die Ausgänge des ICs gesetzt
I2cwbyte Pca9555_lcd
I2cwbyte &H06
I2cwbyte &H00
I2cwbyte &HE8
I2cstop

Call Config_to_lcd(&H3c) 'Function Set
Call Config_to_lcd(&H0f) 'Display on/off
Call Config_to_lcd(&H01) 'clear Display
Call Config_to_lcd(&H06) 'Entry Mode Set

Text = "Hallo Robert "

For I = 1 To 16
Puffer = Textarr(i)
If I = 9 Then 'Das Display hat 2*8 Zeichen
Call Config_to_lcd(&Hc0) 'Beim 9. Zeichen wird auf die untere Zeile geschaltet
End If
Call Data_to_lcd(puffer)
Next

Do
Loop

Sub Config_to_lcd(configbyte)
I2cstart
I2cwbyte Pca9555_lcd
I2cwbyte &H02
I2cwbyte Configbyte
I2cwbyte &H01
I2cstop
Waitms 2
I2cstart
I2cwbyte Pca9555_lcd
I2cwbyte &H03
I2cwbyte &H00
I2cstop
End Sub
Sub Data_to_lcd(databyte)
I2cstart
I2cwbyte Pca9555_lcd
I2cwbyte &H02
I2cwbyte Databyte
I2cwbyte &H05
I2cstop
I2cstart
I2cwbyte Pca9555_lcd
I2cwbyte &H03
I2cwbyte &H04
I2cstop
End Sub
jetzt müssen wir in den Bascomkeller hinuntersteigen und die "Anschlüsse" suchen. Gibts da nicht nen Hausmeister?

PicNick
07.07.2008, 07:22
...Hausmeister?..
*hehe*
man kann das mal in die Lib einbinden und gucken, wenn's so geht, soll's recht sein

guenter1604
07.07.2008, 10:41
Hallo Robert,

den Hausmeister hab ich zwar nicht gefunden, aber jemanden der ihn kennt!

https://www.roboternetz.de/wissen/index.php/Bascom_Libraries

PicNick
07.07.2008, 13:03
:mrgreen: schöner Artikel. Der Mann muss mächtig ahnung haben :mrgreen:

guenter1604
07.07.2008, 14:08
Hallo Robert,

wenn ich das richtig verstanden habe, muß ich mir den passenden Aufruf in den Libs raussuchen:

CLS = _CLS hab ich gefunden.

Leider finde ich z.B. Upperline und Lowerline nicht. Gibts da ne Liste?

guenter1604
07.07.2008, 22:56
Hallo Robert,

es läuft!!!!



copyright = Guenter Gerold
www = www.gerold-online.de/cms
email = tv@gerold-online.de
comment = I2C LCD Treiber
libversion = 1.00
date = 07.07.2008
statement = Wer was zu verbessern hat kann sich bei mir melden...
statement =
history = Final.


[_Init_LCD]
_Init_LCD:

*BASIC: waitms 20
*BASIC: i2cstart
*BASIC: i2cwbyte gg_Displayport
*BASIC: i2cwbyte &H06
*BASIC: i2cwbyte &H00
*BASIC: i2cwbyte &HE8
*BASIC: i2cstop
Ldi _temp2, &H3c
rCall _gg_i2c_config
Ldi _temp2, &H0f
rCall _gg_i2c_config

_gg_i2c_config:
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H02
*BASIC: I2cwbyte _temp2
*BASIC: I2cwbyte &H01
*BASIC: I2cstop
*BASIC: Waitms 2
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H03
*BASIC: I2cwbyte &H00
*BASIC: I2cstop
ret
[end]


[_CLS]
_CLS:
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H02
*BASIC: I2cwbyte &H01
*BASIC: I2cwbyte &H01
*BASIC: I2cstop
*BASIC: Waitms 2
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H03
*BASIC: I2cwbyte &H00
*BASIC: I2cstop
[end]


[_Write_lcd]
_Write_lcd:

Ldi _temp2, &H05
rjmp _Write_lcd_Byte

_Lcd_control:

Ldi _temp2, &H01

_Write_lcd_Byte:

*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H02
*BASIC: I2cwbyte _temp1
*BASIC: I2cwbyte _temp2
*BASIC: I2cstop
rcall LCD_Write_Enable
ret

LCD_Write_Enable:

*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H03
*BASIC: I2cwbyte &H04
*BASIC: I2cstop
ret
[end]

Folgender Code ruft auf:


'################################################# ##############################
'# #
'# I2C-Display mit PCA 9555D #
'# #
'# (c) Günter Gerold #
'# #
'# Zum Pin sparen kann ein LCD-Display auch an einen I2C-Bus gehängt werden #
'# Die eingebauten Bascom-Befehle können genutzt werden #
'# #
'################################################# ##############################

$regfile = "m8def.dat"
$crystal = 8000000
$lib "gg.lib"
Dim A As Byte
Config Scl = Portc.5 'Configure i2c SCL
Config Sda = Portc.4
Const Gg_displayport = &H40 'Addresse des ICs
Config Lcdbus = 8
Config Lcd = 16 * 1a
Do
Cls
Lcd "123"
Cursor Off
Waitms 2000
Cursor On
Waitms 1000
Cursor Blink
Waitms 1000
Lowerline
Lcd "456"
Waitms 1000
Display Off
Waitms 1000
Display On
Cls
Lcd "Shift"
Waitms 1000
For A = 1 To 8
Shiftlcd Right
Waitms 500
Next
For A = 1 To 8
Shiftlcd Left
Waitms 200
Next
Waitms 1000
Loop

guenter1604
08.07.2008, 00:17
Hallo,

nochmal danke für die Hilfe!!

wenn sich noch was ändert, werde ich es unter http://www.gerold-online.de/cms/index.php?id=146 veröffentlichen. Ebenso werde ich dort noch einen Schaltplan reinstellen.

guenter1604
08.07.2008, 00:56
Hallo,

doch noch ein Hund drin:

LCD "123"

-funktioniert

dim a as string * 8
a = "123"
LCD a

-funktioniert nicht #-o

PicNick
08.07.2008, 07:51
Das dürfte der Unterschied sein, ob eine Variable im SRAM ist oder im Programmspeicher.
Kannst du deine letzte Version von allem + beide LCD Varianten hier reinstellen ? dann hacke ich mir kurz den Code auf, was die Schweinebacke da treibt.

guenter1604
08.07.2008, 08:29
Hallo Robert,

so gehts:



$regfile = "m8def.dat"
$crystal = 8000000
$lib "gg.lib"
Config Scl = Portc.5 'Configure i2c SCL
Config Sda = Portc.4
Const Gg_displayport = &H40 'Addresse des ICs
Config Lcdbus = 8
Config Lcd = 16 * 1a
Cls
Lcd "123"
do
loop


so gehts nicht:


$regfile = "m8def.dat"
$crystal = 8000000
$lib "gg.lib"
Config Scl = Portc.5 'Configure i2c SCL
Config Sda = Portc.4
Const Gg_displayport = &H40 'Addresse des ICs
Config Lcdbus = 8
Config Lcd = 16 * 1a
dim a as string
a = "123"
Cls
Lcd a
do
loop

die Lib ist so wie schon gepostet.
Nach Studie von anderen Libs, bin ich jetzt einfach davon ausgegangen, das das aktuelle Zeichen für das Display in der Variable _temp1 steht, was anscheinend aus einem Register geholt wird. Ob das richtig ist weiss ich nicht. Wie ist an das aktuelle Byte der internen Routinen ranzukommen? Da wird das Problem liegen.
Alle anderen Befehle wie Upperline, Shift, Curser On Off Blink Noblink, CLS usw. laufen einwandfrei.

PicNick
08.07.2008, 10:05
Versuch mal. Der Bascom hat bei SRAM-LCD die Register vernudelt.
Das erste Zeichen hätte er aber eigentlich noch zeigen müssen, dann aber Schrott



copyright = Guenter Gerold
www = www.gerold-online.de/cms
email = tv@gerold-online.de
comment = I2C LCD Treiber
libversion = 1.00
date = 07.07.2008
statement = Wer was zu verbessern hat kann sich bei mir melden...
statement =
history = Final.

[_Init_LCD]
_Init_LCD:
*BASIC: waitms 20
*BASIC: i2cstart
*BASIC: i2cwbyte gg_Displayport
*BASIC: i2cwbyte &H06
*BASIC: i2cwbyte &H00
*BASIC: i2cwbyte &HE8
*BASIC: i2cstop
Ldi _temp2, &H3c
rCall _gg_i2c_config
Ldi _temp2, &H0f
rCall _gg_i2c_config

_gg_i2c_config:
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H02
*BASIC: I2cwbyte _temp2
*BASIC: I2cwbyte &H01
*BASIC: I2cstop
*BASIC: Waitms 2
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H03
*BASIC: I2cwbyte &H00
*BASIC: I2cstop
ret
[end]


[_CLS]
_CLS:
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H02
*BASIC: I2cwbyte &H01
*BASIC: I2cwbyte &H01
*BASIC: I2cstop
*BASIC: Waitms 2
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H03
*BASIC: I2cwbyte &H00
*BASIC: I2cstop
ret
[end]

[_Write_lcd]
_Write_lcd:
Ldi _temp2, &H05
rjmp _Write_lcd_Byte
_Lcd_control:
Ldi _temp2, &H01
_Write_lcd_Byte:
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H02
MOV r17, _temp1
RCALL _i2c_write
MOV r17, _temp2
RCALL _i2c_write
*BASIC: I2cstop
rcall LCD_Write_Enable
ret

LCD_Write_Enable:
*BASIC: I2cstart
*BASIC: I2cwbyte gg_Displayport
*BASIC: I2cwbyte &H03
*BASIC: I2cwbyte &H04
*BASIC: I2cstop
ret
[end]

guenter1604
08.07.2008, 16:51
Robert was soll ich sagen,

es läuft!

Nun ja, ich könnte den Code noch ein bisschen "hübsch" machen...

Nochmals danke für deine Unterstützung.

Damit alle was davon haben werde ich es auf meiner Internetseite ein bisschen aufarbeiten.

Günter

PicNick
08.07.2008, 17:25
Na fein !
Hab' mir grad deine HP angesehen, auch die Lib
Vielleicht sollte man wirklich ein wenig assemblermässigen professionellen kryptischen Schamanismus reinpacken. Sonst sieht das so brav aus :mrgreen: