Forum: Mikrocontroller und Digitale Elektronik PCF8574 muss mehrfach ausgelesen werden


von Hermann G. (hermann_g)


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

von Jörg S. (joerg-s)


Lesenswert?

Der DIP-Schalter hängt direkt am Pin uns schliesst den gegen Masse kurz?

von H. P. Bolliger (Gast)


Lesenswert?

Schreibst du in die Dipswitch-bit des PCF8574 einen High-Pegel bevor du 
sie als Input brauchst?

von Hermann G. (hermann_g)


Lesenswert?

Ja, der Dip-Schalter hängt direkt am PCF und ist mit Masse verbunden.

Und ich setzte alle Bits zuvor auf HIGH (siehe Code). Anders würde ich 
auch beim letzten Zyklus keine Werte auslesen können.

Ach ja, das Problem besteht immer, also unabhängig von einer Wertänder 
am Dip-Schalter

von Michael S. (Gast)


Lesenswert?

Hallo Hermann G.

Der PCF8574 hat einen open collector als Ausgang.
Wenn ein Pin auf 1 gesetzt wird, dann schaltet er durch.

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

Ergo: Pinstatus muss 0 sein.
Der Schalter muss nach Masse oder VCC schalten.

mfg

Michael S.

von Falk B. (falk)


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

von Hermann G. (hermann_g)


Lesenswert?

Falk Brunner schrieb:
> http://www.mikrocontroller.net/articles/Port-Expan...

Genau so habe ich meine Schaltung aufgebaut, also ensprechend den LEDs 
und dem Taster.
Funktioniert ja auch alles, abgesehen davon, dass ich wiederholt 
auslesen muss...

von Michael Ṡ (Gast)


Lesenswert?

Oh, sorry ....

Das war ein Erklärungsversuch - als Schuss aus der Hüfte - ohne das 
Datenblatt zu konsultieren.


Michael S.

von Peter D. (peda)


Lesenswert?

Was macht denn dieses "I2CEngine();"?
Vielleicht stößt das nur einen Interrupthandler an und das Lesen ist 
noch garnicht passiert.
Mach mal ne Wartezeit dahinter.


Peter

von Hermann G. (hermann_g)


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.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?


von Juppi J. (juppiii)


Lesenswert?

I2CMasterBuffer[0] = PCF8574A_ADDR | 0x0E;
 // 1. Byte = PCF8574A +Adresse (schreiben)

Ist die Schreib_Grund_Adr des Pcf 8574A  nicht $71 ?

C programmiere ich aber noch nicht.

von Hermann G. (hermann_g)


Lesenswert?

Die Lib ist ja für AVR, der LPC hat ja die ARM-Architektur, das geht 
nicht denke ich oder?

R/W Bit sollte passen, 0x70 + einstellbaren Adreesraum für schreiben
und 0x71 für lesen.

von Peter D. (peda)


Lesenswert?

Stimmt denn die Baudrate?
Die standard I2C-ICs können nur max 100kHz.
Probier mal 10kHz.


Peter

von Hans Peter B. (Gast)


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

von Hermann G. (hermann_g)


Lesenswert?

@ Peter

ändert leider auch nichts am Verhalten, selbst bei 1 kHz..

@ Hans Peter

Im SlaveBuffer landen bei mir keine Daten, weder mit meinem Code noch 
mit deinem

von juppi (Gast)


Angehängte Dateien:

Lesenswert?

Kommt auch der Takt Impuls für das einlesen des ACK.
Nach dem Daten einlesen oder ausgeben.

von Hermann G. (hermann_g)


Lesenswert?

juppi schrieb:
> Kommt auch der Takt Impuls für das einlesen des ACK.
> Nach dem Daten einlesen oder ausgeben.

ich hab leider kein Oszi hier, mit dem ich mir die Pegel anschauen 
kann...
Aber ich versuch mal eins zu organisieren

von Hermann G. (hermann_g)


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

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.