Hallo. Ich versuche zu über I²C zu prüfen, ob ein EEPROM vorhanden ist oder nicht. dabei haben ich folgende Konfiguration: STM_enableRCCAPB1PeriphClock( RCC_APB1Periph_I2C1, ENABLE ); STM_resetRCCAPB1PeriphCmd( RCC_APB1Periph_I2C1, DISABLE ); I2C_Cmd( m_pEE_I2C_TYPE, ENABLE ); I2C_ITConfig( m_pEE_I2C_TYPE, I2C_IT_ERR, ENABLE ); I2C_InitStructure.I2C_Mode = EE_I2C_MODE; I2C_InitStructure.I2C_DutyCycle = EE_I2C_DUTY_CYCLE; I2C_InitStructure.I2C_OwnAddress1 = EE_I2C_OWN_ADDRESS; I2C_InitStructure.I2C_Ack = EE_I2C_ACK; I2C_InitStructure.I2C_AcknowledgedAddress = EE_I2C_ACK_ADDR; I2C_InitStructure.I2C_ClockSpeed = EE_I2C_CLOCK_SPEED; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 BITOR GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; Mein Ansatz beruht auf der Idee, daß generateSTART() falls erfolgreich das SB-Bit im SR1-Register setzt und send7bitAddress() diese wieder löscht und im Erfolgsfall TxE (Transmit-Buffer leer) oder im Fehlerfall (AF (Acknowledge Fail) setzt; zudem hätte ich erwartet daß im Erfolgsfall auch ADDR gesetzt wird, aber das passiert wohl nicht oder es wird sofort zurückgesetzt. ... I2C_GenerateSTART( m_pI2C1, ENABLE ); volatile uint16_t SR1Register = m_pI2C1->SR1; tRetval = u32_checkEvent( I2C_EVENT_MASTER_MODE_SELECT ); if ( tRetval EQ EE_OK ) { I2C_Send7bitAddress( m_pI2C1, u8DevAddr, I2C_Direction_Transmitter ); // SR1->AF = 1, falls kein EERPOM, // TxE = 1 falls EEPROM, warum nicht ADDR? while ( ( SBBit NEQ 0u ) OR ( TeXBit EQ 0u ) ) { SR1Register = m_pI2C1->SR1; SBBit = SR1Register & 0x001u; ADDRBit = SR1Register & 0x002u; TeXBit = SR1Register & 0x080u; } SR1Register = m_pI2C1->SR1; uint16_t AFBit = SR1Register & 0x0400u; if ( AFBit EQ 0u ) { ... Das scheitert aber, weil sich die Abarbeitung beim I2C_Send7bitAddress() aufhängt; genauer gesagt bei F11 beim Rücksprung nach erfolgreichem I2Cx->DR = Address und bei F10 beim folgenden while ((SBBit NEQ 0u) OR (TeXBit EQ 0u) (Ich verwende den IAR). Kann mir irgendjemand sagen ob die Grundannahmen falsch sind, und falls nicht, was die Ursache für das Aufhängen sein könnte?
Knut S. schrieb: > Mein Ansatz beruht auf der Idee, Das nötige Verfahren wird auch "I2C Acknowledge Polling" genannt. Damit sollten sich auch für deinen geheimnisvollen Rechner irgendwelche Erklärungen finden lassen.
Mea Culpa, Es geht um einen STM32F103 der einen 24AA044 von Microchip ansprechen soll.
Knut S. schrieb: > genauer gesagt bei F11 beim Rücksprung nach erfolgreichem > I2Cx->DR = Address und bei F10 beim folgenden while ((SBBit NEQ 0u) OR > (TeXBit EQ 0u) (Ich verwende den IAR). Du sprichst in Rätseln. Meine Milchmädchenrechnung lautet: wenn man ein Byte von eimem EEPROM lesen möchte und einen Fehlerzustand zurückgemeldet bekommt dass ist kein EEPROM da. So einfach ist das. Dazu braucht es keine sophisticated selbstgeschriebene Detektions- routine.
OMG schrieb: > Knut S. schrieb: >> genauer gesagt bei F11 beim Rücksprung nach erfolgreichem >> I2Cx->DR = Address und bei F10 beim folgenden while ((SBBit NEQ 0u) OR >> (TeXBit EQ 0u) (Ich verwende den IAR). > > Du sprichst in Rätseln. > > Meine Milchmädchenrechnung lautet: wenn man ein Byte von eimem > EEPROM lesen möchte und einen Fehlerzustand zurückgemeldet > bekommt dass ist kein EEPROM da. So einfach ist das. Dazu > braucht es keine sophisticated selbstgeschriebene Detektions- > routine. Korrekt. Es reicht eigentlich völlig aus nach dem rauschreiben der Adresse das ACK zu prüfen. Genau dafür ist das an dieser Stelle ja da.
Knut Schünemann schrieb: > Es geht um einen STM32F103 der einen 24AA044 von Microchip ansprechen > soll. Das geht natürlich nicht, STM-Controller arbeiten nur mit EEPROMs von STM zusammen, doch klar oder?
Ja. Ich hatte es zu Beginn mit einem klassischen Ack Polling versucht, aber da ähnliche Probleme wie Beitrag "I2C Problem mit Acknowledge Polling" bemerkt. ACK und AF gleichzeitig gesetzt und der Prozeß hängt beim lesenden Zugriff auf SR1 nach dem Senden der Adresse; daher die Idee nur einzelne Bits der Register zu zu betrachten in der Hoffnung daß man so Probleme mit der Library umgehen könnte.
Das Problem ist daß das Lesen des Registers nicht zurückkehrt; der Prozeß steht bis ein IRQ-Timeout zuschlägt (nicht nur im Debugger, ich sehe in der freilaufenden Baugruppe dasselbe Verhalten); gleichgültig ob ich nach dem Ereignis mit einer Bibliotheksfunktion wie I2C_CheckEvent() sehe, mit I2C_GetFlagStatus() die einzelnen Flags teste, oder direkt die Bits des Statusregisters prüfe, z.B. (((*(__IO uint32_t*)m_pI2C1 + 0x14u)) & 0x400u). Darum der Versuch, den Vorgängen durch Betrachtung der einzelnen Bits auf die Schliche zu kommen, und dann die Fragen: - warum sind AF und ACK gleichzeitig oben? (ACK ist im CR1, steuert also und gibt keinen Status wieder.) - wie kann ACK überhaupt gesetzt sein, wenn niemand da ist der die Adresse akzeptieren könnte? (dito) - wann wird ADDR je gesetzt? - gibt es für irgendwelche anderen Register außer CR1 noch weitere Zugriffverbot in bestimmten Stati der Kommunikation?
Beitrag #6674957 wurde vom Autor gelöscht.
Ja, dachte ich auch so. Es klappt auch wenn das EEPROM vorhanden ist: Nach dem Schreiben der Adresse AF gelöscht -> paßt. (Wobei es noch das kleine Problem des "wann" gibt. Kann es passieren, daß der Controller schon das Flag prüft, während das EEPROM noch nicht alle Bits empfangen und sein ACK geschickt hat? Das ist ja kein synchroner Vorgang sondern läuft mit einer eigenen Clock auf dem geringeren Tempo des EEPROMs.) Es klappt nicht unbedingt bei fehlendem EEPROM. Registriert der Controller überhaupt die fehlende Antwort als NACK? (Die Leitung bleibt Low, sollte also implizit funktionieren.) Aber wie gesagt beobachte ich in dem Falle ein Halten des Prozesses; und da wäre wieder mein Problem.
Das bezweifle ich. I²C kam vom Philips und wird von einer Vielzahl Herstellern in ihre Produkte integriert; mit variierenden Protokollen für höhere Geschwindigkeiten, etc. Er ist üblich als Kommunikationsprotokoll zwischen Bauteilen unterschiedlicher Hersteller, und auch zwischen Baugruppen mit ganz unterschiedlichen Komponenten. Insbesondere weil nicht jeder Hersteller vom µC auch das ganze Spektrum an Peripherie anbietet. Zudem funktioniert hier das Schreiben und Lesen ja durchaus - wenn das EEPROM existiert; mein Problem ist ein optional vorhandenes EEPROM, also aus Sicht des I²Cs eine Adresse im Kabelbaum, die auch im Nichts enden könnte.
Es wurde jetzt ja schon mehrfach gesagt: Ein nicht vorhandenes i2c-Device verhält sich wie ein falsch addresiertes, und gibt dir ein NACK bei der Addressierung zurück. Rein technisch bleibt SDA im ACK-cycle einfach high, weil nichts da ist, das das low zieht. Das ist eine so grundlegende i2c-Funktion, daß muß jeder I2C-Master im Schlaf ohne jegliches Programmier-Voodoo abhandeln können. Knut S. schrieb: > Es klappt nicht unbedingt bei fehlendem EEPROM. Registriert der > Controller überhaupt die fehlende Antwort als NACK? (Die Leitung bleibt > Low, sollte also implizit funktionieren.) Finde den Fehler. Oliver
:
Bearbeitet durch User
Knut S. schrieb: > Es klappt nicht unbedingt bei fehlendem EEPROM. Registriert der > Controller überhaupt die fehlende Antwort als NACK? (Die Leitung bleibt > Low, sollte also implizit funktionieren.) Welche "fehlende Antwort"? Es geht um EIN Bit. Das ACK/NAK. Wenn die Leitung low bleibt stimmt etwas gewaltig nicht. Woher sollte das low kommen? Vielleicht führst du dir erstmal in aller Ruhe die I2C Specs zu Gemüte und schaust dir dann das Problem nochmal an. Irgendwo scheint es da im Verständnis zu klemmen. Einfach nur HAL/StdPeriph API reicht halt nicht. Man sollte schon wissen was man eigentlich tun will.
:
Bearbeitet durch User
Knut S. schrieb: > Es klappt nicht unbedingt bei fehlendem EEPROM. Registriert der > Controller überhaupt die fehlende Antwort als NACK? (Die Leitung bleibt > Low, sollte also implizit funktionieren.) Rieche ich da fehlende Pullup-Widerstände? Die müssen immer da sein, auch wenn kein EEPROM angeschlossen ist. Fehlende Pullups an den I2C Pins können ein nicht vorhandenes ACK vortäuschen (lassen).
Cyblord -. schrieb: > Wenn die Leitung low bleibt stimmt etwas gewaltig nicht. Woher sollte > das low kommen? Wie ich gerade vorher schrub.
Knut S. schrieb: > Ich versuche zu über I²C zu prüfen, ob ein EEPROM vorhanden ist oder > nicht. Grüße nach Wuppertal erstmal von einem Wettbewerber! hehe :-) Gleiche mal Deinen I2C Code mit meinem ab, der klappt nämlich einwandfrei inzwischen. Und wenn da nix drin steckt gibt es kein Event, while wartet ewig und dann müsste der WDG zuschlagen. Die einzelnen Events ab zu sichern ist nervig, bei mir haut der WDG rein, wenn da ein Bit hängt. Und denke dran, dass EEPROMs nicht rücksetzbar sind! Ja, da gibt es die Geschichte mit den 9 Takten, im Jahre 2000 mal von Microchip in einer AppNote beschrieben worden, die bei mir nie funktioniert hat. Alle 2-3 Wochen stand die Sache still. Inzwischen designe ich die EE mit einem PNP Transistor als abschaltbares VCC und wenn da was hängt schalte ich die kurz ab. Was ist denn das ??? BITOR ??? PIO_InitStructure.GPIO_Pin = GPIO_Pin_6 BITOR GPIO_Pin_7; Man nimmt einfach | :-) Ist übrigens keine gute Idee SPL, HAL und Register zu mischen! Entweder man hält sich an eine API, weil die geprüft ist oder man haut sich zusätzliche Fehler mit dieser Bit-Pfuscherei rein, die kein Mensch später mehr nachvollziehen kann ohne das Reference Manual daneben liegen zu haben. Ohne Dir zu nahe treten zu wollen, der Code sieht grauenhaft aus!
Christian J. schrieb: > Entweder > man hält sich an eine API, weil die geprüft ist oder man haut sich > zusätzliche Fehler mit dieser Bit-Pfuscherei rein, Aha, eine API ist also immer fehlerfrei da geprüft! Wenn man die Register direkt anspricht und das hinreichend kommentiert muß man nicht im RM nachschlagen. Und wenn man ein timeout so einfügt, dass es von der Taktfrequenz des verwendeten Controllers unabhängig ist, vermeidet man spontane Fehler, die nur schwer zu finden sind, Herr Wettbewerber. > Ohne Dir zu nahe treten zu wollen, der Code sieht grauenhaft aus! Deine "i2c_basic.h" auch.
@Oliver S.: Ja, danke, das ist mir jetzt auch klar, die Frage nach der Interpretation der leeren Leitung. Aber die Frage ist, wann liegt dieses Belegung im Register vor? Ich sende die Adresse raus, dann sollte BUSY gesetzt sein, wenn alle Bits draußen sind geht TxE hoch (oder nicht? Ich sehen nicht daß das passiert), irgendwann merkt der Master daß das NACK statt ACK auf der Leitung anliegt und setzt AF im SR1, korrekt? Wann kann ich die Belegung des Registers als endgültigen Zustand ansehen und auswerten, insbesondere wenn mein Slave dann Clock Stretching betreiben könnte? Und wann wird in dem Fall BUSY zurückgesetzt? BTW: Teste ich auf I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED, so prüfe ich ja auf ADDR & BERR (nicht TxE?) & MSL & BUSY & TRA gesetzt. Warum BERR?
@Cyblord & jo mei: Ja, danke, habe ich geprüft; das ist nicht das Problem. Der NACK kommt und wird vom µC erkannt und ist als AF-Bit prüfbar. Es war mein Mißverständis, das ACK-Bit nicht als Steuerbit erkannt zu haben und darum dort eine Reaktion zu erwarten. (Und normales Lesen und Schreiben klappt ja auch.) Aber das bringt mich um Punkt den ich in der Spec nicht verstehe: Wenn der Slave viel langsamer als der µC ist, und außerdem Clock Stretching zugelassen ist, zu welchem Zeitpunkt oder welcher Situation kann ich davon ausgehen, daß ein gelöschtes AF-Bit einen funktionierenden Slave anzeigt? ADDR sehe ich nie gesetzt, auch nicht wenn das angesprochene EERPOM existiert, TxE scheint mir in der Situation ein komplementäres Bit zu AF zu sein, aber warum maskiert I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED dann dieses Bit aus? Sorry wegen der Low Level Fragen, aber bis jetzt habe ich nirgendwo eine Erklärung gefunden - vielleicht war da ja jemand erfolgreicher und hat eine Referenz zu Hand?
Knut S. schrieb: > Aber das bringt mich um Punkt den ich in der Spec nicht verstehe: Wenn > der Slave viel langsamer als der µC ist, und außerdem Clock Stretching > zugelassen ist, zu welchem Zeitpunkt oder welcher Situation kann ich > davon ausgehen, daß ein gelöschtes AF-Bit einen funktionierenden Slave > anzeigt? Der Master sendet immer 9 Takte, d.h. Adresse/Daten + ACK/NACK werden in einem Rutsch gelesen. Clock Stretching ist also egal, der Interrupt kommt immer erst nach den 9 Takten.
@Christian J.: Grüße zurück, wohin auch immer. Danke für den Code. Allerdings ist er praktisch identisch in den Abfolge der Schritte und führt zum selben Fehler: Aufhängen beim 1. I2C_CheckEvent(... ,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) (falls kein EEPRoM existiert, sonst läuft es eh). Aber ich wollte mal sehen ob der Hänger an einer anderen Stelle im Disassembly erfolgt als beim sehr ähnlichen früheren Code, ...und siehe da, als Einzelschritt über Mnenomics funktioniert es, und der das Aufhängen passiert an einem späteren checkEvent(), nachdem man den Einzelschritt Modus verlassen hat. Also eher kein Problem mit dem Quellcode. Reset ist klar, aber ich habe keinen Einfluß auf die Elektronik. Sorry wegen dem Code, ist teilweise Copy & Paste aus der Sandbox, aber mit MISRA-Voreinstellungen aktiv. Auch das mit dem Mischen von APIs ist einsichtig, aber wie gesagt: Sandbox und ich experimentiere mit Vorschlägen aus unterschiedlichen Quellen, und habe auch hier teilweise die Originalquellen zitiert.
Christian J. schrieb: > Und denke dran, dass EEPROMs nicht rücksetzbar sind! Ja, da gibt es die > Geschichte mit den 9 Takten, im Jahre 2000 mal von Microchip in einer > AppNote beschrieben worden, die bei mir nie funktioniert hat. Alle 2-3 > Wochen stand die Sache still. Ja, diese AppNote ist falsch. Man darf nicht stur 9 Takte senden, sondern muß nach jedem Takt prüfen, ob der Bus frei ist. Ein Slave sendet beim Schreiben jeden 9. Takt ein ACK bis zum St. Nimmerleins Tag. Einem EEPROM den Saft abdrehen, das macht man einfach nicht.
:
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.