Hallo, ich benutze einen ATMEGA8 um über I2C den PCF8574AP anzusteuern. Möchte LEDs über FETs an und ausmachen. Doch ich scheitere schon beim Zugriff darauf. Habe auch schon viele comments hier zu dem Thema gelesen und ich mache das auch genau so wie es alle hier schreiben, nur ich kriege mein Byte nicht auf den PCF Baustein drauf. bzw ich weiß gar nicht ob er mein gesendetes Byte überhaupt empfangen hat. (Ich benutze die im Anhang stehende Funktionen) von http://www.mikrocontroller.net/articles/Port-Expander_PCF8574 mache das dann so... pcf8574_init (); pcf8574_send_start (); pcf8574_send_add_rw (0b0111000, 0); pcf8574_send_byte (0b01010101); pcf8574_send_stop (); .. die LEDs an den Ports bleiben trotzdem alle an. :( Hardwareseitig ist auch alles in Ordnung, 10k gegen +5V an SDA SCL, Ext. 16Mhz Quarz. Adresse des PCFs stimmt auch. Habe schon viel rumprobiert, weiß leider nicht wie ich das Ganze vernünftig debugen könnte. Wenn ich Variablen Werte irgendwo sehen könnte dann währe das schon eine Hilfe. LCD habe ich nicht, könnte es evtl durch LEDs an den Ports von ATMEGA anzeigen lassen. Bräuchte einen Tipp wie ich schritt für schritt überprüfen könnte ob.. - PCF auf Anfrage von ATmega8 antwortet (ack?) - ob PCF die Daten epfangen hat oder nicht Wäre für jede Hilfe dankbar. Slawa
Ich habe jetzt von jeder Funktion die einen Rückgabewert liefert den TWSR Register ausgelesen. -> in allen steht 0xF8 drin. Laut Datenblatt "Keine relevante Informationen verfügbar" na toll und jetzt?
Das Adressbyte für den PCF8574: Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Hexadezimal 0 1 0 0 A2 A1 A0 R/W 0x40 + A[2:0]*2 + R/W Das Adressbyte für den PCF8574A: Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Hexadezimal 0 1 1 1 A2 A1 A0 R/W 0x70 + A[2:0]*2 + R/W Passe sie folgende an unsigned char pcf8574_send_add_rw (unsigned char address, unsigned char rw) { /*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/ unsigned char addr_byte = 0; /*shift address one bit left*/ addr_byte = address << 1; /*set RW-Bit, if necessary*/ addr_byte |= rw; /*0b0111xxx0 --> address of Expander*/ //fur eine AP !!! addr_byte |= 0b01110000; // fur eine AP !!! /*TWDR contains byte to send*/ TWDR = addr_byte; /*send content of TWDR*/ TWCR = (1<<TWINT) | (1<<TWEN); /*wait, until address has been sent --> ACK*/ while (!(TWCR & (1<<TWINT))); return TWSR; }
After change pcf8574_send_add_rw as above, you must use those commands pcf8574_set_outputs (0, 0xFF); // set all P-out to one. All leds go out pcf8574_set_outputs (0, 0x00); // set all P-out to one. All leds go out
SORRY After change pcf8574_send_add_rw as above, you must use those commands pcf8574_set_outputs (0, 0xFF); // set all P-out to one. All leds go out pcf8574_set_outputs (0, 0x00); // set all P-out to zero. All leds go on.
Thanks for the tipp! But I already had changed the address from 0100 to 0111 for pcf8574ap unsigned char pcf8574_send_add_rw (unsigned char addr, unsigned char rw) //Senden einer 7-Bit-Slave-Adresse und R/W { unsigned char addr_byte = 0; //Erzeugen eines Bytes zur Adressverarbeitung addr_byte = addr << 1; //Verschiebung der übergebenen Adresse um ein Bit nach links addr_byte |= rw; //Anhängen des R/W-Bits //addr_byte |= 0b01000000; //bei einem PCF8574P addr_byte |= 0b01110000; //bei einem PCF8574AP TWDR = addr_byte; //Adresse in das TWDR Laden TWCR = (1<<TWINT) | (1<<TWEN); //Senden des TWDR-Inhaltes (s. Datasheet) while (!(TWCR & (1<<TWINT))); //Kontrolle: "Adresse gesendet" (TWINT gesetzt) return TWSR; //Rückgabe des Status-Registers } this doesnt help, i steel can not get access to pcf ic over twi @Falk Brunner: Ja danke für den Tipp, aber genau die Funktionen benutze ich ja.
Das Programm bleibt übrigens nach Aufruf der Funktionen.. pcf8574_init (); pcf8574_send_start (); pcf8574_send_add_rw (0b0111000, 0); output = pcf8574_send_byte (0xFF); pcf8574_send_stop (); oder pcf8574_set_outputs (0b0111100, 0x00); ..nicht hängen. Ich werte dannach noch 'output' aus if (output==0xD8){ LED1_ein; } else { LED2_ein; } pcf8574_send_byte liefert mir wirklich 0xD8 zurück. In den Datasheets oder auch sonst im Internet finde ich keine Erklärung zu diesen Statuscode! Was das bedeutet ist mir ein Rätsel.
The reason for your program hanging is in the Code: unsigned char pcf8574_read_byte (void) { /*send content of TWDR; TWEA = enable ACK*/ TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); /*wait, until byte has been received --> ACK*/ while (Not(TWCR & (1<<TWINT))); return TWDR; } You should only use TWEA for multiple reads. I use: Code: unsigned char i2c_read(char more) { TWCR = (1<<TWINT) | (1<<TWEN) | ((more!=0) ? (1<<TWEA) : 0); /* ACK */ return (TWDR); } See also : http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=79303&start=0 Maybe this will help ??
My program is not hanging. Its still running after using the functions. I do not use pcf8574_read_byte at the moment, i am trying to set and unset the ports of pcf. I don't understand what the value "0xD8" in TWSR (Status Register) after using pcf8574_send_byte() is all about! anyway thanks for the help!
pcf8574_send_add_rw (); pcf8574_send_byte (); Diese Funktionen geben Dir den Status zurück. Werte ihn mal aus, statt ihn wegzuschmeißen. Wenn Dir pcf8574_send_add_rw() schon ein NACK zurückgibt, hat es keine Sinn weiterzumachen. Dann ist entweder der PCF8574 nicht am Bus oder auf der falschen Adresse. Du kannst mal alle 16 möglichen Adressen durchtesten, ob auf einer ein ACK kommt: Start, Adresse1, ACK testen, Stop ... Start, Adresse16, ACK testen, Stop Peter
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.