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.
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
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ß
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.
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.
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
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!
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
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
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.
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
setze mal ACKEN in SSPCON2 (siehe Datasheet S.178)
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
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.
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
Bernd K. schrieb: > meine Quellcodes: Nächstes Mal: Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
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
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.)
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
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.
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).
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.
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
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."
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.