Forum: Mikrocontroller und Digitale Elektronik PIC16F886: I2C Problem mit ACK Expander PCF8575


von Bernd K. (koesters60) Benutzerseite



Lesenswert?

Hallo, Guten Morgen.
Ich habe ein Problem und bin fast am Verzweifeln. Also frage ich euch 
mal.
Mein Projekt:
- mit PIC 16F886
- Programmiersprache: pmp (IDE mit Turbo Pascal)...bitte nicht lachen, 
aber ich komme damit am besten zurecht
- ein I2C Bus mit Expandern PCF8574 (8 I/O pins) und PCF8575 (2x8 Pins)
- das I/O mit dem PCF8574 funktioniert, keine Probleme, das eine Byte 
wird gelesen
- beim PCF7575 hab ich Probleme, ich kann nur 1 Byte Input lesen, das 
zweite Byte wird nicht richtig gelesen.

Also hab ich mal den Oszi angeworfen und sehe dass beim Lesen etwas mit 
den ACK Bits nicht stimmt.
Mein Wissensstand ist dieser:
- bei einer Write Sequenz sendet der Empänger, also der Expander, 
jeweils nach 8 empfangenen Bits das ACK Bit (zu sehen als 9. Bit)
- bei einer Read Sequenz sendet der Slave nach Empfang des Adress Bytes 
sein ACK bit und sendet die aktuellen Daten des ersten Ports an den 
Master, der Master quittiert den Empfang mit seinem ACK Bit,
- nach dem ACK des ersten Datenbytes sendet der Slave die aktuellen 
Daten des zweiten Ports. Wenn das ACK des Masters aber fehlt (wie in 
meinem Problemfall, siehe angehängte Bilder), sendet der Slave keine 
aktuellen Daten sondern lauter 1'.

Mein Problem ist also vermutlich, dass der Master bei einem Read mit 2 
Datenbytes kein ACK sendet. Ja, das ACK fehlt schon bei dem ersten Byte. 
Da  das ACK aber erst nach dem Empfang der Daten gesetzt wird, wird das 
erste Datenbyte noch korrekt empfangen, aber nicht mit einem ACK vom 
Master bestätigt.

Nun meine Frage, weiß jemand wie ich den PIC Master dazu bringe sein ACK 
zu senden bei einer Read Sequenz?

Anhang: 2 Screenshots
Bild 1: das Adressbyte wird vom Slave richtg ACKnowledged (=das 0 Bit 
als 9. Bit nach den 8 Adressbits, in dieser Sequenz schicke ich nur 
1-Daten um die Pins auf Input zu schalten --- das funktioniert also
Bild 2: in der Read Sequenz bleibt das ACK vom Master High --> Problem!

Kann mir jemand helfen?
Gruß Bernd.

von Bernd K. (koesters60) Benutzerseite



Lesenswert?

bin's noch mal.
Ich hab mir die Sache bei dem PCF8574 mit dem Oszi auch mal genauer 
angeschaut, er sendet ja nur ein Datenbyte. Auch bei dem fehlt wie ich 
richtig vermutete, das positive ACK vom Master (= value auf der SDA 
Leitung). Das war mir bisher nicht aufgefallen, weil das Byte die 
aktuellen Inputs richtig enthielt. Aber es fehlt das positive ACK des 
Masters.

Hoppla, und ich sehe es fehlt der 9. Clockimpuls nach dem Datenbyte.

Oder wird bei nur einem Datenbyte gar kein ACK gesetzt vom Master und er 
clockt gar nicht mehr den 9. Impuls?

Nun sehe ich auch dass bei den 2-Bytigen PCF8575 das erste Datenbyte nur 
6 Clockimpulse hat, also kein ACK, das 2. Byte dann aber 9 Clocks aber 
der ACK ist nicht gesetzt.

Sehr komisch.

Bernd.

: Bearbeitet durch User
von Franko P. (sgssn)


Lesenswert?

Hab ich da was falsch verstanden? Wenn der master sendet, kommt doch das 
ACK vom Empfänger. Das macht doch sonst gar keinen Sinn.

Gruß

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

ja, wenn der Master sendet kommt das ACK vom Empfänger.

Bei mir ist das Problem, wenn der Master Daten empfängt, sendet er kein 
ACK zum Sender, dem Expander. Beim Ersten Byte clockt der Master nur 
8mal, beim zweiten Byte 9 mal, aber sein ACK fehlt.

von Clemens L. (c_l)


Lesenswert?

Bernd K. schrieb:
> der Master quittiert den Empfang mit seinem ACK Bit

Falsch. Der Master sendet ACK, wenn er weiter lesen will. Das letzte zu 
lesende Byte quittiert er mit NACK.

> weiß jemand wie ich den PIC Master dazu bringe sein ACK
> zu senden bei einer Read Sequenz?

Zeig mal den Quelltext.

von Bernd K. (koesters60) Benutzerseite


Angehängte Dateien:

Lesenswert?

Clemens L. schrieb:
> Falsch. Der Master sendet ACK, wenn er weiter lesen will. Das letzte zu
> lesende Byte quittiert er mit NACK.

Ja, aber der Master machts bei mir nicht. Wo liegt der Fehler bei mir?

: Bearbeitet durch User
von Rahul D. (rahul)


Lesenswert?

Bernd K. schrieb:
> im Datenblatt des PPCF8575 steht aber, dass bei einem Read der Slave das
> ACK generiert....s. Copy

Das ist doch genau das, was Clemens schrieb:
Um die Übertragung seitens des Maters zu beenden, schickt dieser ein 
NACK.
Alle anderen, fortlaufenden Lesevorgänge werden mit einem ACK quittiert.
Der Fehler liegt demnach an der I²C-Leseroutine des Masters
==> Quewllcode zeigen!

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

meine Quellcodes:

die I2C Procedures (das ist Turbo Pascal)
1
procedure PCF2_Read ();
2
begin
3
  //Adresse des zu lesenden PCF Expanders
4
  OPCODE := PCF_ADDR shl 1;
5
  //I2C Start
6
  I2C_Master_Start;
7
  //Lesen: zunächst Port auf HIGH schalten -->Pullups notwendig
8
  I2C_Master_Write(OPCODE);    //Opcode mit R/W = 0 = W
9
  I2C_Master_Write(0xFF);      //Outputs HIGH damit die Pins INPUT werden
10
  I2C_Master_Write(0xFF);      //Outputs HIGH damit die Pins INPUT werden
11
  I2C_Master_RepeatedStart;    // restart weil jetzt wieder eine Adresse mit W/R kommt
12
  I2C_Master_Write(OPCODE or 0x01);    //Opcode mit R/W = 1 = R
13
  //Daten empfangen  bei pcf8475 2x,  bei pcf8474 nur 1x
14
  PCF_Data_Read1 := I2C_Master_Read;
15
  PCF_data_Read2 := I2C_Master_Read;
16
  //I2C Stop
17
  I2C_Master_Stop;
18
end;
19
------------------------------------
20
Unit adI2C;
21
interface
22
23
//I2C Routinen
24
Procedure I2C_Master_Init;
25
procedure I2C_Master_Write(data:byte);
26
function  I2C_Master_Read : byte;
27
Procedure I2C_Master_Start;
28
Procedure I2C_Master_Stop;
29
Procedure I2C_Master_RepeatedStart;
30
31
//==================================================
32
//------------[ MCP und PCF ADRESSEN ]--------------
33
//--------------------------------------------------
34
Var
35
  SCL_D  : boolean @ TRISC.RC3;
36
  SDA_D  : boolean @ TRISC.RC4;
37
38
const
39
 I2C_CLOCK    = 100000; //100000;                              // Required I2C bit rate in Hz
40
 I2C_CLK_INIT = (FREQUENCY div 4 div I2C_CLOCK) - 1;           // I2C bit rate init value
41
 {$IF (I2C_CLK_INIT <= 0) or (I2C_CLK_INIT >= 256)}
42
     {$UERROR 'The requested I2C speed cannot be achieved with these settings'}
43
 {$IFEND}
44
45
Implementation
46
47
//==================================================
48
//---------------[ I2C-Master Routines ]------------
49
//--------------------------------------------------
50
Procedure I2C_Master_Init;
51
begin
52
  SSPCON  := 0x28;
53
  SSPCON2 := 0x00;
54
  SSPSTAT := 0x00;      //im I2C master-mode: sets transmit not in progress
55
  SSPADD  := I2C_CLK_INIT;
56
  SCL_D   := 1;         //das sind TRISC.3 und 4 --> Outputs
57
  SDA_D   := 1;
58
end;
59
60
Procedure I2C_Master_Waitforidle;
61
begin
62
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
63
end;
64
65
Procedure I2C_Master_Start;
66
begin
67
  //I2C_Master_WaitforIdle();
68
   while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
69
  SEN := 1;
70
end;
71
72
Procedure I2C_Master_Stop;
73
begin
74
  //I2C_Master_WaitforIdle;
75
   while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
76
  PEN := 1;
77
  nop;nop;nop;
78
end;
79
80
Procedure I2C_Master_RepeatedStart() ;
81
begin
82
  //I2C_Master_WaitforIdle;
83
   while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
84
  RSEN := 1;
85
  nop;nop;nop;
86
end;
87
88
procedure I2C_Master_Write(data:byte);
89
begin
90
  //I2C_Master_WaitforIdle;
91
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
92
  SSPBUF := data;
93
  while (NOT SSPIF) do; // Wait Until Completion
94
  SSPIF := 0;
95
end;
96
97
function I2C_Master_Read : byte;
98
begin
99
  //I2C_Master_WaitforIdle;
100
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
101
  RCEN :=1;
102
  while (NOT SSPIF) do; // Wait Until Completion
103
  //I2C_Master_WaitforIdle;
104
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
105
  return SSPBUF;
106
  SSPIF := 0;
107
end;
108
109
initialization
110
End.
111
*******************

: Bearbeitet durch User
von Bernd K. (koesters60) Benutzerseite


Lesenswert?

Rahul D. schrieb:
> Der Fehler liegt demnach an der I²C-Leseroutine des Masters

ja, es muß an diesem Unterprogramm liegen, da fehlt noch irgendein 
Registersetzen oder an der Procedure I2C_Master_Init
1
Procedure I2C_Master_Init;
2
begin
3
  SSPCON  := 0x28;
4
  SSPCON2 := 0x00;
5
  SSPSTAT := 0x00;      //im I2C master-mode: sets transmit not in progress
6
  SSPADD  := I2C_CLK_INIT;
7
  SCL_D   := 1;         //das sind TRISC.3 und 4 --> Outputs
8
  SDA_D   := 1;
9
end;
10
11
12
13
function I2C_Master_Read : byte;
14
begin
15
  //I2C_Master_WaitforIdle;
16
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
17
  RCEN :=1;
18
  while (NOT SSPIF) do; // Wait Until Completion
19
  //I2C_Master_WaitforIdle;
20
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
21
  return SSPBUF;
22
  SSPIF := 0;
23
end;

: Bearbeitet durch User
von Rahul D. (rahul)


Lesenswert?

Bernd K. schrieb:
> I2C_Master_Stop;


Ungünstig...
Das sollte meiner Meinung nach erst am Ende des kompletten Lesevorgangs 
passieren.
Dir fehlt da eine Schleife über die Anzahl der zu lesenden Bytes.
Danach kann dann das Stop-Signal gesendet werden.

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

Rahul D. schrieb:
> Ungünstig...
> Das sollte meiner Meinung nach erst am Ende des kompletten Lesevorgangs
> passieren.
> Dir fehlt da eine Schleife über die Anzahl der zu lesenden Bytes.
> Danach kann dann das Stop-Signal gesendet werden.

mache ich doch:
Stop ist einmal am Ende und
innen sind 2 Reads.
// im Code sind Kommentare
1
procedure PCF2_Read ();
2
begin
3
  //Adresse des zu lesenden PCF Expanders
4
  OPCODE := PCF_ADDR shl 1;
5
  //I2C Start
6
  I2C_Master_Start;
7
  //Lesen: zunächst alles auf HIGH schalten
8
  I2C_Master_Write(OPCODE);    //Opcode mit R/W = 0 = W
9
  I2C_Master_Write(0xFF);      //Outputs HIGH damit die Pins INPUT werden
10
  I2C_Master_Write(0xFF);      //Outputs HIGH damit die Pins INPUT werden
11
  I2C_Master_RepeatedStart;    // restart weil jetzt wieder eine Adresse mit W/R kommt
12
  I2C_Master_Write(OPCODE or 0x01);    //Opcode mit R/W = 1 = R
13
  //Daten empfangen  bei pcf8475 2x,  bei pcf8474 nur 1x
14
  PCF_Data_Read1 := I2C_Master_Read;
15
  PCF_data_Read2 := I2C_Master_Read;
16
  //I2C Stop
17
  I2C_Master_Stop;
18
end;

Hier der Link zum Datenblatt 
https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/40001291H.pdf

: Bearbeitet durch User
von Ron-Hardy G. (ron-hardy)


Lesenswert?

setze mal ACKEN in SSPCON2 (siehe Datasheet S.178)

von Clemens L. (c_l)


Lesenswert?

AN735 (Using the PICmicro MSSP Module for I2C Communications) sagt:
> The Acknowledge bit event consists of first setting the
> Acknowledge state, ACKDT (SSPCON2<5>) and then
> asserting high the event control bit ACKEN (SSPCON2<4>).

https://ww1.microchip.com/downloads/en/appnotes/00735a.pdf

: Bearbeitet durch User
von Bernd K. (koesters60) Benutzerseite


Lesenswert?

Clemens L. schrieb:
> AN735 (Using the PICmicro MSSP Module for I2C Communications)

genau das hab ich gesucht, wußte gar nicht dass es ein ANxxx bezüglich 
I2C gibt.
Danke, das arbeite ich mal durch und teste. Ich melde mich dann.

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

Jetzt hab ich's gepackt, es läuft.

Für das Lesen von 2 Datenbytes vom PCF8575 Expander hab ich jetzt 2 
Routinen, eine für das erste Datenbyte und eine für das zweite.

Bei der ersten Sequenz wird am Ende der Übertragung noch das ACK 
eingeschoben.

Hier mein Code:
1
procedure PCF2_Read ();
2
begin
3
  OPCODE := PCF_ADDR shl 1;
4
  I2C_Master_Start;
5
  I2C_Master_Write(OPCODE or 0x01);    //Opcode mit R/W = 1 = R
6
  PCF_Data_Read1 := I2C_Master_Read1;   //<--- NEU: Sequenz mit ACK
7
  PCF_data_Read2 := I2C_Master_Read2;   //<--- NEU: Sequenz ohne ACK
8
  I2C_Master_Stop;
9
end;
10
11
------------------------------------------------------------
12
function I2C_Master_Read1 : byte;
13
begin
14
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do; //wait until in idle mode
15
  RCEN :=1;
16
  while (NOT SSPIF) do;           // Wait Until Completion
17
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do; //wait until in idle mode
18
  //neu
19
  I2C_Master_SetACK;  //<----------- NEU!!
20
21
  return SSPBUF;
22
  SSPIF := 0;
23
end;
24
25
procedure I2C_Master_SetACK;
26
begin
27
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do; //wait until in idle mode
28
  ACKDT := 0;   //ACK=0
29
  ACKEN := 1;   //Event setzen
30
end;
31
32
function I2C_Master_Read2 : byte;
33
begin
34
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
35
  RCEN :=1;                                                  //Read enable
36
  while (NOT SSPIF) do;                                   // Wait Until Completion
37
  while((SSPSTAT and 0x04) or (SSPCON2 and 0x1F)) do;     //wait until in idle mode
38
  return SSPBUF;
39
  SSPIF := 0;
40
end;

Damit wäre mein Problem dank eurer Hilfe (besonders von Clemens mit dem 
Hinweis auf das ANxx Papier) gelöst. Ich bedanke mich herzlich.

Gruß Bernd.

: Bearbeitet durch User
von Rainer W. (rawi)


Lesenswert?

Bernd K. schrieb:
> meine Quellcodes:

Nächstes Mal:
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Bernd K. (koesters60) Benutzerseite


Angehängte Dateien:

Lesenswert?

ich möchte euch noch das Oszi Bild dazu zeigen. Es zeigt das neu 
einschobene ACK.

Mich wundert nur, dass SDA nach dem ACK Clock bis zum nächsten 
Byte-Lesen LOW bleibt. Ist das normal?

: Bearbeitet durch User
von Clemens L. (c_l)


Lesenswert?

Bernd K. schrieb:
> Mich wundert nur, dass SDA nach dem ACK Clock bis zum nächsten
> Byte-Lesen LOW bleibt. Ist das normal?

Ja. Der Zustand von SDA wird nur während der steigenden Flanke von SCL 
gelesen; was mit SDA passiert, während SCL Low ist, ist egal. (Und da um 
das ACK-Bit herum zwischen Master und Slave umgeschaltet wird, kann es 
durchaus passieren, dass SDA hin und her wackelt.)

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

danke, Clemens, dann kann alles nun so lassen wie es ist.

Was ich mich bei diesem ACK Gedöns allerdings frage, warum ist das ACK 
nicht schom standardmäßig eingeschaltet, wenn der Master liest. Ob Lesen 
oder Schreiben ist, sieht er doch an dem W/R Bit in dem Adressbyte, das 
er als erstes zum Slave geschickt hat.

: Bearbeitet durch User
von Clemens L. (c_l)


Lesenswert?

Bernd K. schrieb:
> warum ist das ACK nicht schom standardmäßig eingeschaltet, wenn der
> Master liest

Weil der Master am Ende ein NACK senden muss. Und in vielen Anwendungen 
wird genau ein Byte gelesen.

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

Der Sinn des NACK am Ende leuchtet mir noch nicht ein.

Ich hab jetzt mal dieses getestet:
1. Am Ende wird ein ACK geschickt: ----> gelesene Daten sind OK
2. Am Ende wird ein NACK geschickt: ---> gelesene Daten sind OK
3. Am Ende weder ein ACK noch ein NACK:--> alle Daten OK

Also wozu soll der Impuls dienen?
Ich sehe es so: der ACK dient dazu, dass der Slave sich zum Senden des 
nächsten Bytes vorbereiten kann/soll, nach dem letzten Byte wird nichts 
mehr abgerufen, also wäre der ACK Impuls auch nicht nötig (es hat da 
keinen Sinn mehr).

von Peter D. (peda)


Lesenswert?

Der Master muß als letztes ein NACK senden, damit der Slave weiß, daß er 
nun SDA loslassen muß. Ansonsten können weitere Daten das Stop des 
Masters verhindern.

von Bernd K. (koesters60) Benutzerseite


Angehängte Dateien:

Lesenswert?

Peter D. schrieb:
> Der Master muß als letztes ein NACK senden, damit der Slave weiß, daß er
> nun SDA loslassen muß. Ansonsten können weitere Daten das Stop des
> Masters verhindern.

scheint aber nicht so zu sein. Am Ende setzt meine Master Stop Procedure 
das Register PEN=1. Laut Datenblatt bewirkt das, dass SDA und SCL High 
gehen.
Das Loslassen der SDA durch den Slave wird also initiiert durch die Stop 
Condition und nicht durch ein NACK.

Datenblatt des PIC 16F886:
PEN: Stop Condition Enable bit (in I2C Master mode only)
SCK Release Control:
1 = Initiate Stop condition on SDA and SCL pins. Automatically cleared 
by hardware.
0 = Stop condition Idle

Oder sehe ich da noch was falsch?
In meinem angehängten Bild werden SDA und SCL released nach High auch 
ohne ein NACK, sondern vermutlich durch das PEN=1.
Es ist wohl der Zustand dass die SCL permanent high geht, das den Slave 
veranlasst auch die SDA loszulassen.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Na dann setze mal den PCF8574 auf 0x00 und versuche ihn zurück zu lesen. 
Der Master kann dann kein Stop mehr senden.
Es sei denn, der PIC hat auch ein I2C-Recovery implementiert, wie die 
alten Philips 80C51:
"If the SDA line is obstructed by another device on the bus (e.g., a 
slave device out of bit synchronization), the problem can be solved by 
transmitting additional clock pulses on the SCL line (see Figure 14). 
The SIO1 hardware transmits additional clock pulses when the STA flag is 
set, but no START condition can be generated because the SDA line is 
pulled LOW while the I2C bus is considered free. The SIO1 hardware 
attempts to generate a START condition after every two additional clock 
pulses on the SCL line. When the SDA line is eventually released, a 
normal START condition is transmitted, state 08H is entered, and the 
serial transfer continues."

von Peter D. (peda)


Lesenswert?

Ich sehe gerade, Dein PIC verletzt die I2C-Spezifikation. Du sendest zum 
Schluß nur 8 Takte, d.h. der ACK-Slot fehlt. Damit erfolgt das Stop 
fälschlich anstelle des ACK.

von Bernd K. (koesters60) Benutzerseite


Lesenswert?

Peter, ich hab mal deinen Fall getestet PCF8575 alle 16 Pins auf Output 
0 und dann 2 Bytes lesen mit ACK oder NACK oder garnix nach dem 2. 
Byteread:
1. Bei NACK und garnix wird die Sequenz mit der Stop Condition sauber 
beendet. Aber wie du schon vermutest, der Fall mit dem fehlenden 
ACK/NACK Puls ist nicht Spec-konform.
2. Bei ACK am Ende hängt die Sequenz, naja der Slave wartet auf die 
Clocks....also erwartetes Verhalten.

Aber wie getestet, NACK oder garnix ist kein Unterschied.

Ich habe allerdings zZ nur einen einzigen Slave am Bus, kann also noch 
nicht die komplette Story in ihren Folen testen.

Sicherlich kann man über viele andere Fälle diskutieren.
Ich hab nun das NACK nach dem letzten Read eingebaut, und gut ist's.

: Bearbeitet durch User
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.