Hallo, in der Datei pcf8574_experiment.c wollte ich gezielt untersuchen, warum das Lesen vom Port-Expander nicht funktioniert. Trotz mehrerer Versuche und Nachlesen über das TWI sowie im Forum sind die Versuche ergebnislos geblieben. Ich verwende pcf8574.c und pcf8574.h von diesem vorgefertigten Beispiel hier: http://www.mikrocontroller.net/articles/Port-Expander_PCF8574 http://www.mikrocontroller.net/mc-project/Pages/Projekte/ICs/Port%20Expander/Portexpander%20Beispiel.zip Aufruf im Hauptprogramm erfolgt dann mit diesen Zeilen hier: //Port-Expander bedienen: //Adresse des Portexpanders PCF8574: A2, A1, A0 sind auf GND gelötet -->> 0100 000 = 0x40 /*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/ // pcf8574_set_outputs (i, j); //PCF8574: A2, A1, A0 sind auf GND gelötet -->> 0100 000X = 0x40 oder ein Bit nach rechts verschoben: 0x20 // pcf8574_set_outputs (0x20, i); //PCF8574 hat Adresse 0x20!!! <<<---<<<--- OK funktioniert 0x20 ist falsch, da UP 0..8 erwartet.!!!!!!!!!!!!!<<<---<<<--- // pcf8574_set_outputs (0, i); //PCF8574 hat Adresse 0 !!! <<<---<<<--- OK funktioniert. 0x20 ist falsch, da UP 0..8 erwartet.!!!!!!!!!!!!!<<<---<<<--- /*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/ // input = pcf8574_get_inputs (0x20); //PCF8574: A2, A1, A0 sind auf GND gelötet -->> 0100 000 = 0x40 // pcf8574_set_outputs (0, 0xFF); //Ausgänge sollen vor dem Lesen high sein! input = pcf8574_get_inputs (0); //PCF8574: A2, A1, A0 sind auf GND gelötet -->> 0100 000 = 0x40 GLCD_WriteString(6,0, itoa( input, s, 10)); //Stelle6, Zeile1, Ausgabe des gelesenen Bytes vom PCF8574 //Ende Port-Expander bedienen Gut funktioniert das Schreiben euf ein LCD siehe dg14032-demo24C08_11:I2C_LCD_speed-test.c. Kann mal bitte jemand schauen, ob in der Datei pcf8574_experiment.c im Unterprogramm "pcf8574_get_inputs" und "pcf8574_read_byte" ein Fehler enthalten ist? mit freundlichem Gruß
Versuch mal ob das schreiben Komplett gut geht - ich meine ob du da das korrekte ACK-abhandlung messt. Kannst du einen Oscilloscope drauf setzen ?
Danke für den Hinweis. Ich werde mir mal die Signale auf dem Bus ansehen. Vielleichts stimmt dabei schon etwas nicht und man kann daraus Rückschlüsse ziehen, welcher Befehl da nicht greift. Rückmeldung morgen dann... MfG
Hi >unsigned char pcf8574_get_inputs (unsigned char address) >{ > unsigned char input;> > pcf8574_init (); > pcf8574_send_start (); > pcf8574_send_add_rw (address, 0); //Adresse > pcf8574_send_byte (0xFF); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< > pcf8574_send_add_rw (address, 1);Adresse senden und Lesen einstellen > pcf8574_read_byte (); <<<<<<<<<<<<<<< Da fehlt eine repeated start condition. MfG Spess
Hallo, danke für den Hinweis. Da habe ich also noch einen Fehler zusätzlich eingebaut, weil ich innerhalb der Leseroutine erst die Ausgänge auf high setzen wollte. Mit dem repeated-start geht es auch nicht. Nun geht es aber: Schaltet man direkt zu +5V, wird entsprechend eingelesen, das Display reagiert und auf dem Oszilloskop sieht man schön das entsprechende Bit. Die Ausgänge stehen auf high, die offenen Eingänge lesen aber 0 = 0b00000000 aus. Die Ausgänge liegen auf ca 2 Volt bei high. Kontakt zu +5V setzt das dem Pin entsprechende Bit. Mein Denkfehler war, die auf high stehenden Ausgänge mit GND verbinden zu wollen. Das hätte man auch ohne Oszilloskop hinbekommen können ;-) funktionierender Code: unsigned char pcf8574_get_inputs (unsigned char address) { unsigned char input; pcf8574_init (); pcf8574_send_start (); pcf8574_send_add_rw (address, 1);//Adresse senden und Lesen einstellen input = pcf8574_read_byte (); pcf8574_send_stop (); return input; } unsigned char pcf8574_read_byte (void) { /*send content of TWDR; TWEA = enable ACK*/ // TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //<<<<<<------- Programm bleibt beim Lesen hängen TWCR = (1<<TWINT) | (1<<TWEN); //<<<<<<--<<--<- Programm läuft durch, liest einzelnes Byte /*wait, until byte has been received --> ACK*/ while (!(TWCR & (1<<TWINT))); return TWDR; } //Aufruf aus dem Hauptprogramm: input = pcf8574_get_inputs (0); //PCF8574: A2, A1, A0 sind auf GND gelötet MfG
Hi > /*send content of TWDR; TWEA = enable ACK*/ >// TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //<<<<<<------- Programm >bleibt beim Lesen hängen > TWCR = (1<<TWINT) | (1<<TWEN); //<<<<<<--<<--<- Programm läuft >durch, liest einzelnes Byte Das ist aber nicht allgemein gültig. Beim Lesen vom Slave muss der Master vor der Stop Condition ein NAK (TWCR = (1<<TWINT) | (1<<TWEN);) senden. Da du hier nur ein Byte liest ist das so richtig. Werden mehrere Bytes hintereinander, z.B. von einem EEPROM, gelesen, muss der Master, bis auf das letzte Byte, alle Bytes mit einem ACK (TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN)) bestätigen. Beim letzten Byte wird dann wieder mit NACK gelesen. Lesenswert: http://www.nxp.com/documents/user_manual/UM10204_JA.pdf MfG Spess
Ich werde mich bei der Thematik MCP 23017, Page read beim EEPROM, AVR als Slave und ähnlichem noch genügend damit austoben können. MfG
hier der Link für NichtJapaner: (oute mich hier als solcher) http://www.nxp.com/documents/user_manual/UM10204.pdf
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.