Forum: Mikrocontroller und Digitale Elektronik PCF8574AP mit ATMEGA8 - scheitere beim Zugriff


von Slawa S. (slawa_s)


Angehängte Dateien:

Lesenswert?

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

von Slawa S. (slawa_s)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?


von goal (Gast)


Lesenswert?

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;
}

von link (Gast)


Lesenswert?

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

von link (Gast)


Lesenswert?

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.

von Slawa S. (slawa_s)


Lesenswert?

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.

von Slawa S. (slawa_s)


Lesenswert?

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.

von link (Gast)


Lesenswert?

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 ??

von Slawa S. (slawa_s)


Lesenswert?

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!

von Peter D. (peda)


Lesenswert?

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
Noch kein Account? Hier anmelden.