PCF8574 muss mehrfach ausgelesen werden

#2600141
Lesenswert?

Hallo Zusammen,

zur Zeit experimentiere ich etwas mit I2C und bin dabei bei auf ein 
kleine Problem gestoßen. Ich benutze eine LPC1768 als Master und steuere 
damit einen PCF8574 an. Das funktioniert auch soweit, 4 IOs sind mit 
LEDs verbunden und 4 mit einem Dip-Schalten, also 4 Ein- und 4 Ausgänge.

Die vier LEDs lassen sicher Problemlos ein und ausschalten und auch den 
Dip-Schalter kann ich auslesen, allerdings erst nach wiederholter 
Abfrage?!
Bei der Abfrage lese ich 4 Zyklen lange aus, wobei aber nur im letzten 
Zyklus die richtigen Werte ankommen, davor kommt nur 0x00 an.
Das irritiert mich etwas, eigentlich sollten die Werte ja schon beim 
ersten Mal richtig sein... hier mal der Code:
1
  /* Clear Buffer before Write Data */
2
  for ( j = 0; j < BUFSIZE; j++ )              
3
  {
4
  I2CMasterBuffer[j] = 0;
5
  }
6

7
 
8
    I2CWriteLength = 2;                    // 2 Byte I2C schreiben
9
    I2CReadLength = 0;                    // 0 Byte lesen
10

11
    I2CMasterBuffer[0] = PCF8574A_ADDR | 0x0E;        // 1. Byte = PCF8574A + Adresse (schreiben)
12
    I2CMasterBuffer[1] = 0xFF;                // 2. Byte schreiben  
13
 
14

15
  I2CEngine(); 
16
    delay_ms(5);                        
17

18

19

20
while(1){
21
  int i;
22

23
    /* Clear Buffer before Read Datac */ 
24
    for ( i = 0; i < BUFSIZE; i++ )              // Clear Buffer 
25
    {
26
    I2CMasterBuffer[i] = 0;
27
    
28
    I2CWriteLength = 1;                    // 1 Byte I2C schreiben Transfer
29
    I2CReadLength = 4;                       // 4 Byte lesen
30

31
    I2CMasterBuffer[0] = PCF8574A_ADDR | 0x0E | RD_BIT;      // 1. Byte = PCF8574A + Adresse (lesen)
32

33
      
34
    I2CEngine();
35

36
//  LPC_GPIO2->FIOPIN = I2CMasterBuffer[1];
37
//  LPC_GPIO2->FIOPIN = I2CMasterBuffer[2];
38
//  LPC_GPIO2->FIOPIN = I2CMasterBuffer[3];
39
  LPC_GPIO2->FIOPIN = I2CMasterBuffer[4];

Ich geben die empfangen Daten dann über 8 LEDs aus, die direkt vom µC 
angesteuert werden.

Ich hoffe ich habe die wichtigsten Sachen angegeben.

Vielleicht hatte ja schon mal wer ein ähnliches Problem?

Viele Grüße
#2600236
Lesenswert?

@  Michael S. (Gast)

>Der PCF8574 hat einen open collector als Ausgang.

Ja.

>Wenn ein Pin auf 1 gesetzt wird, dann schaltet er durch.

Nein. Schau ins Datenbatt,

"Fig.9 Simplified schematic diagram of each I/O."

>Wenn du zusätzlich einen Schalter auf low legst, dann bringt das nichts.

Doch.

>Ergo: Pinstatus muss 0 sein.

Nein. HIGH

>Der Schalter muss nach Masse oder VCC schalten.

Nach Masse, VCC geht nicht.

http://www.mikrocontroller.net/articles/Port-Expander_PCF8574

MFG
Falk
#2600845
Lesenswert?

Peter Dannegger schrieb:
> Was macht denn dieses "I2CEngine();"?

I2CEngine() stammt aus einer Code-Sammlung von NXP. Die Kommunikation 
des I2C wir nur durch Interrupthandler übernommen.
Ich habe ein Delay zwischen den einzelnen Abfragen eingebaut, was aber 
nichts gebracht hat...

aber schon mal vielen Dank für die ganzen Antworten :)

edit: Der PCF überträgt schon alle 8 IO-Zustände auf einmal? Fig. 12 
READ MODE im Datenblatt verwirrt mich gerade etwas.
Gast #2601299
Lesenswert?

Ich denke du musst für Read-Operationen mit der I2cEngine()-Function, 
anstelle von I2CMasterBuffer[], den String I2CSlaveBuffer[] verwenden

setze doch mal folgende Sequenz bei dir ein

#define PCA8574A_ADDR   0x70
#define  PCA8574_ADDR  0x40

      /* Clear Buffer before Read Datac */
      for ( i = 0; i < BUFSIZE; i++ )              // Clear Buffer
      {
        I2CMasterBuffer[i] = 0;
  }
  I2CWriteLength = 2;
  I2CReadLength = 2;
  I2CMasterBuffer[0] = PCA8574A_ADDR;
  I2CMasterBuffer[1] = 0xFF;
  I2CMasterBuffer[2] = PCA8574A_ADDR | RD_BIT;
  I2CEngine();

  LPC_GPIO2->FIOPIN = I2CSlaveBuffer[0];

Hans Peter
#2678796
Lesenswert?

Hallo Zusammen,

ich hab das Problem gefunden.
Der "Fehler" liegt im Interrupthandler, dort werden Empfangene Bytes mit 
zwei Feldern Abstand im MasterBuffer abgelegt. Deshalb kommt es so vor, 
als würden erst das dritte abgefragte Datenbit stimmen.

Hier der Auszug aus dem IRQHandler:
1
/* Data byte has been received, regardless following ACK or NACK */
2
  // Master Receive :  Data byte has been received; ACK has been returned.   
3
  case 0x50:  
4

5
    // Master Receive : Data byte has been received; NOT ACK has been returned.
6
  case 0x58:  I2C1MasterBuffer[3+Rd1Index] = LPC_I2C1->I2DAT;
7
        Rd1Index++;


Viele Grüße

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren