Hallo zusammen,
ich bin noch recht neu im Umgang mit Mikrocontrollern und versuche
folgendes Setup zum Laufen zu bringen:
Ich habe einen ATmega328P auf einem Breadboard mit einem 8MHz Quarz. An
PIN 28 (SCL) und PIN 27 (SDA) ist das Display 1602 (HD44780) über einen
I2C Controller (PCF8574AT) verbunden.
Die Adresse des I2C Controllers ist 0x27 oder 0x3F (keine Lötbrücken).
Die I2C clock ist dabei 100kHz.
Die Verbindungslänge ist 30 cm.
SDA und SCL sind über 7,87kOhm Widerstände an 5V verbunden.
Ich programmiere in Atmel Studio 7 und verwende zur Ansteuerung den Code
von Nico/Thomas Eichelmann (http://computerheld.de/i2clcd/) und das I2C
MasterInferace von Peter Fleury
(http://homepage.hispeed.ch/peterfleury/avr-software.html).
Ich habe die i2clcd.h in folgender Weise angepasst:
Das Problem ist, dass auf dem Display in der ersten Zeile nur weiße
Blöcke angezeigt werden. Ich habe herausgefunden, dass das auf eine
nicht ausgeführte oder fehlerhafte Initialisierung des Displays
zurückzuführen ist.
Ich habe jetzt den Fehler so eingegrenzt, dass während der
Initialisierung des Displays (lcd_init) die Funktion i2c_write
aufgerufen wird.
1
unsignedchari2c_write(unsignedchardata)
2
{
3
uint8_ttwst;
4
5
// send data to the previously addressed device
6
TWDR=data;
7
TWCR=(1<<TWINT)|(1<<TWEN);
8
9
// wait until transmission completed
10
while(!(TWCR&(1<<TWINT)));
11
12
// check value of TWI Status Register. Mask prescaler bits
13
twst=TW_STATUS&0xF8;
14
if(twst!=TW_MT_DATA_ACK)return1;
15
16
return0;
17
18
}/* i2c_write */
Es bleibt dabei bei der Abfrage
1
while(!(TWCR&(1<<TWINT)));
hängen.
Mit dem Oszi habe ich herausgefunden, dass SDA währenddessen high ist,
jedoch SCL low ist. SCL ist auch low, wenn ich das Display nicht am
ATmega angeschlossen habe.
Vielen Dank schon einmal für eure Hilfe. :)
Viele Grüße
Hi
Bist Du am richtigen SCL-Pin?
SCL und SDA müssen in Ruhe beide HIGH sein.
Wenn Du auf SCL einen Takt hast, passt ggf. die Adresse nicht.
Sonst: Was macht das Display, was macht Es nicht?
Was ist wo am µC angeschlossen?
MfG
Sven K. schrieb:> I2C Controller (PCF8574AT) verbunden.> Die Adresse des I2C Controllers ist 0x27 oder 0x3F (keine Lötbrücken).
Meiner Meinung nach: Der 8574 A hat eine andere Adresse, siehe
Datenblatt.
Arbeitnehmer schrieb:> Meiner Meinung nach: Der 8574 A hat eine andere Adresse, siehe> Datenblatt
Sehe ich auch so
0x70 schreiben
0x71 lesen
jeweils ohne gesetzte Adress-Brücken.
@ Arbeitnehmer / Dieter:
Vielen Dank für den Hinweis. Ich hatte mich blind auf den Hinweis des
Verkäufers des I2C Moduls verlassen.
Das Display scheint auf 0x7E zu reagieren (A0-2 = 1).
Werden A0-2 durch die Lötbrücken auf low gezogen?
Beim PCF857 (ohne A) sind bei 0x27 standardmäßig ja auch A0-2 auf 1
gesetzt.
Allerdings schaltet sich das Display jetzt nach Start des µC aus.
Womöglich ist irgendwo ein DISPLAYOFF Befehl zu häufig?
Ich werde jetzt versuchen damit weiter zu arbeiten.
@ Patrick:
Ich glaube die Verkabelung ist richtig (PIN 28 (SCL) und PIN 27 (SDA)).
Ich gehe jetzt davon aus, dass es tatsächlich ein Addressfehler war.
(s.o.)
Danke trotzdem für die Antwort.
Viele Grüße
Dieter F. schrieb:> Arbeitnehmer schrieb:>> Meiner Meinung nach: Der 8574 A hat eine andere Adresse, siehe>> Datenblatt>> Sehe ich auch so>> 0x70 schreiben> 0x71 lesen
Klar, deshalb ist im Datenblatt (Table 5. PCA8574A address map) abhängig
von A[0..2] als Adresse angegeben 38h .. 3Fh.
;-(
Patrick J. schrieb:> Hi>> Aus gehen liest sich zumindest so, daß das Display Steuerbefehle> bekommt.>> Die Belegung der 8bit des Expander ist bei den verschiedenen Versionen> nicht identisch!> Bei den 0x27 z.B. Bit 3 die Hintergrundbeleuchtung.> Dort sind verschiedene Versionen gezeigt:> http://arduino-info.wikispaces.com/LCD-Blue-I2C?responseToken=93c153e52892ea62109f6eaf90429aa5>> MfG
Ich habe alle Verbindungen vom Display zum PCF857AT durchgepiepst und
bin dann auf folgende Verbindungen gekommen:
1
#define LCD_D4_PIN 4 /**< LCD-Pin D4 is connected to P4 on the PCF8574 */
2
#define LCD_D5_PIN 5 /**< LCD-Pin D5 is connected to P5 on the PCF8574 */
3
#define LCD_D6_PIN 6 /**< LCD-Pin D6 is connected to P6 on the PCF8574 */
4
#define LCD_D7_PIN 7 /**< LCD-Pin D7 is connected to P7 on the PCF8574 */
5
#define LCD_RS_PIN 0 /**< LCD-Pin RS is connected to P0 on the PCF8574 */
6
#define LCD_RW_PIN 1 /**< LCD-Pin RW is connected to P1 on the PCF8574 */
7
#define LCD_EMPTY_PIN 3 /**< this pin is not connected */
8
#define LCD_E_PIN 2 /**< LCD-Pin D4 is connected to P2 on the PCF8574 */
Sofern die Beschriftungen der Pins auf dem Display nicht falsch sind,
sollte das hoffentlich passen.
War das das, was du gemeint hast?
Viele Grüße
Wolfgang schrieb:> Klar, deshalb ist im Datenblatt (Table 5. PCA8574A address map) abhängig> von A[0..2] als Adresse angegeben 38h .. 3Fh.> ;-(
Scheinbar hest Du meinen Beitrag nicht richtig gelesen:
0x70 schreiben
0x71 lesen
incl. Schreib-/Lese-Bit. Ohne macht eine Adressierung keinen Sinn -
oder?
Hi
Hier ging es doch um die Ansteuerung per I2C-Portexpander, oder was habe
ich verpasst?
Da der Expander nur 8bit hat und Du dort auch noch E,RS,RW mit drüber
bringen musst, bleiben 4bit für's Display über.
Zum Umschalten auf 4-bit-Betrieb reicht Das, danach 16x2,
Cursor,Blinken,Display-Shift, dann Display an, fertig.
Wobei im 4-Bit-Betrieb jedes Byte in zwei Nibble gesendet wird, wo die
Steuer-Bits doppelt gesendet werden.
MfG
Patrick J. schrieb:> Hi>> Hier ging es doch um die Ansteuerung per I2C-Portexpander, oder was habe> ich verpasst?> Da der Expander nur 8bit hat und Du dort auch noch E,RS,RW mit drüber> bringen musst, bleiben 4bit für's Display über.> Zum Umschalten auf 4-bit-Betrieb reicht Das, danach 16x2,> Cursor,Blinken,Display-Shift, dann Display an, fertig.>> Wobei im 4-Bit-Betrieb jedes Byte in zwei Nibble gesendet wird, wo die> Steuer-Bits doppelt gesendet werden.>>> MfG
Hi Patrick,
entschuldige, wenn ich noch nicht alles ganz durchschaue.
Ja es geht um einen I2C-Portexpander mit 8 bit.
Die 4 Datenbits werden kopiert und werden in D0-3 und D4-7 des Displays
geschrieben:
1
#define LCD_D0 (1 << LCD_D4_PIN) /**< bit 0 in 1st lower nibble */
2
#define LCD_D1 (1 << LCD_D5_PIN) /**< bit 1 in 1st lower nibble */
3
#define LCD_D2 (1 << LCD_D6_PIN) /**< bit 2 in 1st lower nibble */
4
#define LCD_D3 (1 << LCD_D7_PIN) /**< bit 3 in 1st lower nibble */
5
6
#define LCD_D4 (1 << LCD_D4_PIN) /**< bit 4 in 2nd lower nibble */
7
#define LCD_D5 (1 << LCD_D5_PIN) /**< bit 5 in 2nd lower nibble */
8
#define LCD_D6 (1 << LCD_D6_PIN) /**< bit 6 in 2nd lower nibble */
9
#define LCD_D7 (1 << LCD_D7_PIN) /**< bit 7 in 2nd lower nibble */
10
11
#define LCD_RS (1 << LCD_RS_PIN) /**< RS-bit in 1st and 2nd higher nibble */
12
#define LCD_RW (1 << LCD_RW_PIN) /**< RW-bit in 1st and 2nd higher nibble */
13
#define LCD_EMPTY (1 << LCD_EMPTY_PIN) /**< empty-bit in 1st and 2nd higher nibble */
14
#define LCD_E (1 << LCD_E_PIN) /**< E-bit in 1st and 2nd higher nibble */
So ist es zumindest im Code, den ich habe, realisiert. In der Funktion
lcd_command werden dann jeweils die oberen und unteren 4 bits
nacheinander gesendet:
Hi
Die LCD_write müsste dann mit den Steuerbits verodern und diese so
generierten 8bit per I2C ans Display schicken.
Mit der realen Belegung des Display hast Du hier weniger zu tun, da der
Expander hier vorgibt, was wie zu übertragen ist.
Wenn Du dieses Display bereits an einem anderen µC was anzeigt, bitten
den Code davon sowie den Code dieses µC, denke, da haben wir Differenzen
drin.
Komplette Code wäre hier sinnig, z.B. ist in Deiner Funktion lcd_command
nicht ersichtlich, wo die Steuerbits her kommen und welche Pins wofür
benutzt werden.
MfG
Patrick J. schrieb:> Hi>> Die LCD_write müsste dann mit den Steuerbits verodern und diese so> generierten 8bit per I2C ans Display schicken.>> Mit der realen Belegung des Display hast Du hier weniger zu tun, da der> Expander hier vorgibt, was wie zu übertragen ist.>> Wenn Du dieses Display bereits an einem anderen µC was anzeigt, bitten> den Code davon sowie den Code dieses µC, denke, da haben wir Differenzen> drin.>> Komplette Code wäre hier sinnig, z.B. ist in Deiner Funktion lcd_command> nicht ersichtlich, wo die Steuerbits her kommen und welche Pins wofür> benutzt werden.>> MfG
Ich habe bis jetzt nur den einen µC, deshalb kann ich es gerade nicht an
einem anderen µC testen.
Anbei der gesamt Code als zip. Ich hoffe das ist in Ordnung.
Vielen Dank noch einmal.
Hi
Wie Du oben schreibst, siehst Du nur einen Balken.
Init nicht korrekt
Leider komme ich mit der Schreibweise des Code nicht sonderlich zurecht,
meinem Verständnis nach, dürfte Da rein gar Nichts passieren :O
Patrick J. schrieb:> Hi>> Wie Du oben schreibst, siehst Du nur einen Balken.> Init nicht korrekt>> Leider komme ich mit der Schreibweise des Code nicht sonderlich zurecht,> meinem Verständnis nach, dürfte Da rein gar Nichts passieren :O>
1
void lcd_init(void); //- Display initialization
2
> sequence
3
>
4
> /**
5
> \brief Write data to i2c (for internal use)
6
> \param value byte to send over i2c
7
> \return none
8
> */
9
> void lcd_write_i2c(unsigned char value); //- Write data to i2c
10
>
11
> /**
12
> \brief Write byte to display with toggle of enable-bit
13
> \param value the upper nibble represents E, RS, RW pins and the lower
14
> nibble contains data D0 to D3 pins or D4 to D7 pins
15
> \return none
16
> */
17
> void lcd_write(unsigned char value); //- Write byte to display
18
> with toggle of enable-bit
19
>
20
> /**
> Geht dann noch weiter ...> Ist erkenne da nicht, was wirklich zum Init verschickt wird.>> MfG
Hi Patrick,
die Implementierungen der I2C Funktionen stehen in der "twimaster.c".
Mittlerweile habe ich ja auch keine Balken mehr, sondern das Display
schaltet sich aus.
Die I2C Verbindung steht also scheinbar, nur scheine ich falsche Befehle
zu schicken, oder ähnliches.