Hallo zusammen,
leider bin ich ein wenig verzweifelt.
Ich versuche seit einigen Tagen meinen I2C-Bus am STM32F103C8T6 zu
nutzen.
Das Datenblatt habe ich mir mehrfach durchgelesen und in punkto I2C auch
soweit verstanden.
Trotzdem bekomme ich es nicht hin, eine Kommunikation mit einem PCF8574
aufzubauen.
Folgendes Problem besteht:
Ich initialisiere alle notwendigen Register und halte mich auch an die
im Datenblatt angegebene Reihenfolge.
Dann setze ich das Startbit und SDA wird auch auf LOW gezogen, das
Startbit wird dann auch nach Lesen des SR1 und anschließendem
Beschreiben von DR korrekt zurückgesetzt.
In DR schreibe ich die Adresse des PCF8574 (ist in einem LCD-Modul
eingebunden - A0,A1,A2 sind mit PullUps auf HIGH - daher ist die Adresse
des Display statt 0x20 somit 0x27).
Es wäre mir eine wirklich große Hilfe, wenn mir jemand einen heißen Tipp
geben könnte, was ich falsch mache oder vergessen habe.
Der Controller läuft mit 8MHz Quarz + PLL auf 72 MHz hochmultipliziert.
Der Vorteiler für APB1 (PCLK1) ist auf 2 --> also 36MHz am I2C1.
Die Taktfrequenz habe ich auch schon im RCC heruntergesetzt, genauso wie
die
100kHz I2C-Takrtfrequenz auch mal auf 10kHz eingestellt waren.
Leider ohne Erfolg.
Ich habe auch schon andere I2C-Teilnehmer an den Controller
angeschlossen - leider ohne Erfolg.
Am SDA/SCL hängen je 2k2 PullUp-Widerstände gegen 5V (PB6/PB7 sind
5V-Tolerant)
1
void I2C_Init(void){ //I2C initialisieren
2
3
#define __I2C_SCL(x) ((x)?(GPIOB->BSRR |= (1 << 6)):(GPIOB->BSRR |= (1 << (6 + 16)))) //nicht schoen, aber fuer den Test ausreichend...
I2C1->DR = (Adr << 1); //Adresse ist 0x27 -> nach dem 'Schieben' ist der Byteinhalt 0x4E
72
73
while(!__I2C_ADDR_SENT); // <--- Hier bleibt das Programm haengen!! AF ist gesetzt und SCL ist auf LOW (wird nicht durch Slave auf LOW gezogen!)
74
75
while(x){ //Daten senden
76
77
I2C1->DR = (*data++);
78
while(!__I2C_TX_EMPTY);
79
80
x--;
81
}
82
83
//Stop-Condition
84
__I2C_STOP;
85
86
87
return success;
88
89
}
90
91
92
int main(void){
93
94
I2C_Init();
95
unsigned char data[2] = {0x01,0x08};
96
I2C_SendData(0x27,&data,2);
97
98
99
while(1){
100
101
//Hier steht noch weiterer Code - aber die Funktion
102
//bleibt an der markierten Stelle in I2C_SendData(...) hängen...
103
104
105
}
106
107
108
}
Das I2C-Interface scheint also immerhin zu arbeiten, da das Start-Bit ja
generiert wird. Mit dem Oszi sehe ich auch einen Takt auf SCL -
allerdings wird er danach auch LOW gezogen.
Ich habe übrigens nicht vor, den Code so zu lassen :)
Es geht mir im Augenblick erst einmal darum, das System ans Laufen zu
bekommen. Eine wiederverwendbare und adaptierbare Funktion wird dann
gebaut, wenn ich die ersten Bytes erfolgreich gesendet bzw. empfangen
habe.
Es wäre wirklich wunderbar, wenn mir die Experten in diesem Forum unter
die Arme greifen würden.
Vielen Dank im Voraus und einen schönen Freitagabend...
Edit:
Die ERRATA - Init-Sequenz habe ich auch schon einmal komplett
auskommentiert.
Ohne Erfolg natürlich...
Pete V. schrieb:> Ich versuche seit einigen Tagen meinen I2C-Bus am STM32F103C8T6 zu> nutzen.
Da und hie frage ich mich ja, ob es Spass macht wieder mal ein (diesmal
3-eckiges) Rad neu zu erfinden.
Zeitaufwaendig scheint es zumindest zu sein.
"Librarys sind Luxus".
leo
Pete V. schrieb:> Es wäre wirklich wunderbar, wenn mir die Experten in diesem Forum unter> die Arme greifen würden.
Ich könnte mir vorstellen dass deine Magic-Numbers-
Programmierung die meisten Leute abhalten wird sie nach-
zuvollziehen um einen Fehler zu finden.
... if you know what I mean ...
Es geht ganz bestimmt nicht darum, etwas neu zu erfinden.
Ich möchte es verstehen - dazu sollte es doch möglich sein, ein
funktionierenden Code zu programmieren, der an das Datenblatt angelehnt
ist.
Den Lerneffekt, den man beim Einbinden einer fertigen Lib hat, ist nicht
das, was mich zu Frieden stellt.
Bezüglich der MagicNumbers werde ich den Code noch umschreiben. Danke
für den Hinweis :)
Pete V schrieb:> Den Lerneffekt, den man beim Einbinden einer fertigen Lib hat, ist nicht> das, was mich zu Frieden stellt.
Vielleicht hat leo auch nur das selbe gemeint wie ich,
nur in anderen Worten ....
Genormte Low-Level Calls zu nutzen ist nicht verwerflich
und ist bei weitem nicht als Verwendung einer fertigen
Lib zu betrachten.
Pete V schrieb:> Bezüglich der MagicNumbers werde ich den Code noch umschreiben. Danke> für den Hinweis :)
Vielleicht ist dir noch nicht geläufig wo du nachzuschauen
hast um schnell auf einen grünen Zweig zu kommen.
Für deinen Fall wäre das in der SPL die Dateien
stm32f10x_i2c.c
und
stm32f10x_i2c.h
Die bieten dir eine anständige Schnittstelle "nach unten" und
du kannst den Code der da unten verwendet wird auch kopieren
um eigenständig zu sein.
Die Dateien zu verwenden ist beileibe nicht "eine fertige Lib
benutzen".
Okay, das ist ein super Hinweis - danke.
Hab mal vor ein paar Jahren mit dem LPC1768 programmiert und sonst nur
Erfahrungen mit den einschlägigen AVRs - da ist man um jede Quelle
dankbar :)
Das werde ich mir mal hinzufügen und dann Rückmeldung geben :)
moin moin,
ich komme aus der Pascal-Ecke, aber was mir bei Deiner Initialisierung
fehlt:
RCC->APB2ENR->AFIOEN, das Bit0 setzen...wegen der AlternateFunction
Ich habe hier einen Beispiel-Code für dich, wie man die richtige I²C
Schnittstelle benutzt: http://stefanfrings.de/stm32/stm32f1.html#i2c
Du siehst, dass ich hier gar nicht direkt auf die I/O Pins zugreife. Ich
halte deine Initialisierungsroutine für unnötig komplex.
Unabhängig davon würde ich Dir empfehlen, deinen Code weiter zu
untersuchen. Besorge Dir einen "8ch Logic Analysator" und das kostenlose
Programm "PulseView". Damit kannst du die Signale auszeichnen und
untersuchen. Das Programm kann sogar das I²C Protokoll dekodieren.
Das Bild, dass dieses Programm ausgibt, wird so ähnlich aussehen, wie
das angehängte (ein funktionierendes Beispiel für einen anderen Slave).
Damit kann ich dir besser helfen, als deinen Quelltext zu analysieren.
Zwei Sachen fallen mir spontan auf:
1) Fehlende bzw. zu geringe Verzögerungszeiten:
1
__I2C_SCL(true);
2
__I2C_SDA(true);
3
while(!__I2C_SDA_IDR&&!__I2C_SCL_IDR);
4
__I2C_SDA(false);
5
while(__I2C_SDA_IDR);
6
__I2C_SCL(false);
7
while(__I2C_SCL_IDR);
8
__I2C_SCL(true);
9
while(!__I2C_SCL_IDR);
10
__I2C_SDA(true);
11
while(!__I2C_SDA_IDR);
Du fummelst hier an den beiden Signalen herum, ohne lange genug zu
warten. Die beiden letzten Schreibzugriffe könnten letztendlich dazu
führen, dass die Pins gleichzeitig oder fast gleichzeitig auf High
gehen, was im I²C Protokoll nicht zulässig ist.
2) Deine Prozedur, wie du die Daten sendest und empfängst ist völlig
falsch. Das solltest du nochmal einen Blick in das Reference-Manual und
(ganz wichtig!) auch das Errata Dokument werden. Beim STM32 geht das
nämlich nicht ganz so einfach, wie bei AVR. Siehe mein
Beispiel-Quelltext, der setzt 1:1 das um, was ST in den beiden
Dokumenten empfohlen hat.
Ich scheiße-kompliziert aber wohl nötig.
Und dann fällt mich noch etwas ein, wass ich selber herausfinden musst:
Konfiguriere zuerst die I²C Peripherie, und erst danach die I/O Pins.
Nur in dieser Reihenfolge starten sie gleich mit den richtigen Pegeln
ohne die I²C Slaves zu blockieren.
Stefanus F. schrieb:> Ich habe hier einen Beispiel-Code für dich, wie man die richtige I²C> Schnittstelle benutzt: http://stefanfrings.de/stm32/stm32f1.html#i2c>> Du siehst, dass ich hier gar nicht direkt auf die I/O Pins zugreife. Ich> halte deine Initialisierungsroutine für unnötig komplex.>> Unabhängig davon würde ich Dir empfehlen, deinen Code weiter zu> untersuchen. Besorge Dir einen "8ch Logic Analysator" und das kostenlose> Programm "PulseView". Damit kannst du die Signale auszeichnen und> untersuchen. Das Programm kann sogar das I²C Protokoll dekodieren.>> Das Bild, dass dieses Programm ausgibt, wird so ähnlich aussehen, wie> das angehängte (ein funktionierendes Beispiel für einen anderen Slave).> Damit kann ich dir besser helfen, als deinen Quelltext zu analysieren.
Anmerkung zu Pulseview:
Es gibt eine Firmware im Netz die man auf einen STM32-Discovery laden
kann um da Ding nachfolgend als Pulseview-kompatiblen LA zu nutzen,
damit hab ich meinen I2C Kram, der ein Mischmasch wohl aus Stefans und
W.S. und eigenem Code ist, debuggt. 24C08 etc klappt, LCD via 8574 ist
gerade in Arbeit, die Kommunikation funktioniert aber problemlos.
Gruß,
Holm
Stefanus F. schrieb:> Ich habe hier einen Beispiel-Code für dich, wie man die richtige I²C> Schnittstelle benutzt: http://stefanfrings.de/stm32/stm32f1.html#i2c
Hallo Stefan,
zuerst einmal vielen Dank für den Code.
Ich habe Deinen Code 1:1 bei mir übernommen - lediglich die Taktfrequenz
angepasst, da meine Peripherie nicht auf 8, sondern auf 36 MHz läuft.
Leider funktioniert der Code auch nicht bei mir.
Habe dann mal probeweise die Taktfrequenz auf 9 MHz heruntergesetzt
(Vorteiler PCLK1 auf 8 statt 2 @ 72MHz).
Das Verhalten ist genau das gleiche, wie bei meinem Programm.
Die SCL wird auf LOW gehalten und ein AF gesetzt, da wohl kein ACK vom
Slave kommt.
Ich hänge den Slave jetzt einmal an einen Mega328p, da ich dafür eine
funktionierende Bib hab. Vllt stimmt doch etwas nicht mit dem Slave...
Bezüglich dem LogicAnalyzer:
Ich habe mir die Woche einen bestellt, da alles andere nur Gefummele zu
sein scheint und ich sowieso schon öfter einen gebraucht hätte.
Sollte dann im Laufe der Woche ankommen.
Das ganze Thema ist echt zeitintensiv, aber immer, wenn ich solche
Probleme beim Programmieren habe, habe ich am Ende die wertvollsten
Lektionen daraus ziehen können :)
@Stefan:
Du hast lesenswerte Inhalte auf Deiner Internetseite.
Werde mir das im Ganzen noch einmal genauer ansehen.
Pete V. schrieb:> Die SCL wird auf LOW gehalten und ein AF gesetzt, da wohl kein ACK vom> Slave kommt.
Das ACK/NAK wird beim 9. Takt eingelesen. Wenn du nach dem Start keine 9
Taktimpulse siehst, hast du ein Hardwareproblem außerhalb des
Mikrocontrollers.
Probiere dann mal ohne Slave aus. Du müsstest alle 9 Takte sehen und das
NACK (SDA=High), erst danach sollte die Übertragung abbrechen. Und zwar
mit einem sauberen STOP Signal, gefolgt vom Ruhepegel (SDA=High und
SCL=High).
> Das ganze Thema ist echt zeitintensiv,
Ja, I²C ist schwierig. Aber wenn es dann endlich läuft ist es sehr
praktisch.
> Du hast lesenswerte Inhalte auf Deiner Internetseite.
Danke für das Lob. Positives Feedback treibt mich dazu an, die Seite
weiter auszubauen.
Stefanus F. schrieb:> Das ACK/NAK wird beim 9. Takt eingelesen. Wenn du nach dem Start keine 9> Taktimpulse siehst, hast du ein Hardwareproblem außerhalb des> Mikrocontrollers.>> Probiere dann mal ohne Slave aus. Du müsstest alle 9 Takte sehen und das> NACK (SDA=High), erst danach sollte die Übertragung abbrechen. Und zwar> mit einem sauberen STOP Signal, gefolgt vom Ruhepegel (SDA=High und> SCL=High).
Hallo Stefan,
also die Taktimpulse (SCL) kann ich auf dem Oszi sehen.
Ich kann sehen, dass die Taktimpulse raus gehen und auf SDA passiert
auch etwas.
Leider muss ich noch auf meinen LogicAnalyzer warten, bis ich dazu
genaueres sagen kann.
Also die HW des STM32 scheint auf jeden Fall grundsätzlich zu arbeiten.
Das Stop-Signal (Als Fehlerbehandlung nach "goto error") kommt auch.
In deinem Programmcode habe ich dann das "goto error" mal auskommentiert
- die Registerinhalte mit dem AF sind auf jeden Fall genauso wie in
meinem Programm. Der Slave gibt wohl einfach keinen ACK.
In der Zwischenzeit habe ich den Slave (I2C-LCD) an den Mega328p
angeschlossen - es funktioniert dort einwandfrei. Hier liegt also kein
Defekt vor...
Ich setze mal noch die Taktfrequenz von 100kHz runter auf 10kHz...
Mal schauen, ob es an der Leitungslänge liegt (ca. 10cm - sollte
eigentlich irrelevant sein...)
Pete V. schrieb:> Stefanus F. schrieb:>> Das ACK/NAK wird beim 9. Takt eingelesen. Wenn du nach dem Start keine 9>> Taktimpulse siehst, hast du ein Hardwareproblem außerhalb des>> Mikrocontrollers.>>>> Probiere dann mal ohne Slave aus. Du müsstest alle 9 Takte sehen und das>> NACK (SDA=High), erst danach sollte die Übertragung abbrechen. Und zwar>> mit einem sauberen STOP Signal, gefolgt vom Ruhepegel (SDA=High und>> SCL=High).>> Hallo Stefan,>> also die Taktimpulse (SCL) kann ich auf dem Oszi sehen.> Ich kann sehen, dass die Taktimpulse raus gehen und auf SDA passiert> auch etwas.> Leider muss ich noch auf meinen LogicAnalyzer warten, bis ich dazu> genaueres sagen kann.> Also die HW des STM32 scheint auf jeden Fall grundsätzlich zu arbeiten.>> Das Stop-Signal (Als Fehlerbehandlung nach "goto error") kommt auch.> In deinem Programmcode habe ich dann das "goto error" mal auskommentiert> - die Registerinhalte mit dem AF sind auf jeden Fall genauso wie in> meinem Programm. Der Slave gibt wohl einfach keinen ACK.>> In der Zwischenzeit habe ich den Slave (I2C-LCD) an den Mega328p> angeschlossen - es funktioniert dort einwandfrei. Hier liegt also kein> Defekt vor...>> Ich setze mal noch die Taktfrequenz von 100kHz runter auf 10kHz...> Mal schauen, ob es an der Leitungslänge liegt (ca. 10cm - sollte> eigentlich irrelevant sein...)
Meine vorgesehene Frage ob Du die richtige Adresse erwischt hast
erübrigt sich wohl. Hast Du vernünftige Pullup Rs an SCK und SDA?
Mein LCD geht auch, bei mir war das nur eine Frage der richtigen
Bitbelegung dieser China-I2C-zu Display Platine, die mußte ich erst mal
ermitteln. Das ist also ein Adapter für Standard-HD44780 Displays zu
I2C.
Falls Du auch so ein Ding auf dem Tisch hast, probiere erst mal die
Displaybeleuchtung mit Bit 3 (Ausgang P3 am 8574, 0x08) an und aus zu
schalten.
Falls es irgend Jemand braucht, Zuordnung der LCD Pins zu 8574T auf der
China Platine:
P0 -> RS
P1 -> R/W
P2 -> E
P3 -> Background Light
P4 -> DB4
P5 -> DB5
P6 -> DB6
P7 -> DB7
Die Adresse der Platine ist ohne Lötbrücken 0x4E/0x4F.
Gruß,
Holm
Holm T. schrieb:> Falls es irgend Jemand braucht, Zuordnung der LCD Pins zu 8574T auf der> China Platine:>> P0 -> RS> P1 -> R/W> P2 -> E> P3 -> Background Light> P4 -> DB4> P5 -> DB5> P6 -> DB6> P7 -> DB7
Hallo Holm,
ich musste auch erst suchen bei der Erstinbetriebnahme.
Habe dann irgendwo den Schaltplan (siehe Anhang) gefunden.
Dass die Adresse des Displays bei den unteren Bits (A3-A0) eine 0x07
ist, hat mich auch etwas verwirrt, da der Schaltplan ja etwas anderes
gezeigt hat.
Das hab ich auch in der aktuellen Problematik öfter in Frage gestellt.
Aber dadurch, dass ich es gerade mit (0x27 << 1) am laufen hatte, ist es
jetzt wieder eindeutig.
Pete V. schrieb:> Holm T. schrieb:>> Falls es irgend Jemand braucht, Zuordnung der LCD Pins zu 8574T auf der>> China Platine:>>>> P0 -> RS>> P1 -> R/W>> P2 -> E>> P3 -> Background Light>> P4 -> DB4>> P5 -> DB5>> P6 -> DB6>> P7 -> DB7>> Hallo Holm,>> ich musste auch erst suchen bei der Erstinbetriebnahme.> Habe dann irgendwo den Schaltplan (siehe Anhang) gefunden.>> Dass die Adresse des Displays bei den unteren Bits (A3-A0) eine 0x07> ist, hat mich auch etwas verwirrt, da der Schaltplan ja etwas anderes> gezeigt hat.
Nuja, Dein Schaltplan lügt ganz einfach. Auf der Platine sind 3
Lötbrücken..wenn die offen sind liegen halt die Eingänge vom PCV nicht
an Masse..damit wird die Sache klar. Ich hab die Verschaltung
ausgeklingelt, nur einen "Schaltplan" habe ich davon nicht gemalt.
>> Das hab ich auch in der aktuellen Problematik öfter in Frage gestellt.> Aber dadurch, dass ich es gerade mit (0x27 << 1) am laufen hatte, ist es> jetzt wieder eindeutig.
0x27<<1 ist 0x4e...
Ich habe aber bei mir noch einen I2C Pegelwandler mit 2 Stück 2N7002
dazwischen..sind die 3,3V am Display Dein Problem? Den 24C08 betreibe
ich mit 3v3, das Display mit 5V.
Gruß,
Holm
Den Pegelwandler mit dem FET hab ich auch gerade mal noch eingebaut.
Leider auch keine Veränderung an der aktuellen Situation...
Was kann es denn noch sein? ?
Pete V schrieb:> Den Pegelwandler mit dem FET hab ich auch gerade mal noch eingebaut.>> Leider auch keine Veränderung an der aktuellen Situation...>> Was kann es denn noch sein? ?
..ohne Logikanalyzer ist das eher schwer rauszubekommen.
Hast Du nicht so ein Discovery Board da um einen provisorischen LA zu
mimikrieren? Ich habe diverse alte LA's da, aber das Feature von
Pulseview Protokolle decodieren zu können hat mir mit dem 24C08 der erst
nicht wollte sehr geholfen und man braucht ja nicht mehr als 2 Eingänge.
Die Software auf dem PC ist dann die Selbe wie für Deinen mittlerweile
gekauften LA...
https://sysprogs.com/w/how-we-turned-8-popular-stm32-boards-into-powerful-logic-analyzers/
Gruß,
Holm
Leider habe ich ein solches Board nicht da.
Habe mir vor kurzem noch einen zweiten STM32 bestellt, sonst habe ich
"nur" AVRs und PICs, sowie den LPC1768 hier.
Ich habe gerade einmal die Frequenz auf dem I2C verlangsamt, den Slave
entfernt und eine Endlosschleife programmiert, die praktisch immer
das Start-Bit setzt und dann den Byte-Inhalt 0x4E sendet.
1
....
2
while(!success){
3
//Start-Condition
4
5
while(__I2C_BUSY);
6
7
__I2C_START;
8
9
while(!__I2C_START_SENT);
10
I2C1->DR = (Adr << 1); //Adresse ist 0x27 -> nach dem 'Schieben' ist der Byteinhalt 0x4E
11
12
success = true;
13
while(!__I2C_ADDR_SENT){
14
if((I2C1->SR1 & I2C_SR1_AF)){
15
__I2C_STOP;
16
I2C1->CR1 &=~ (I2C_CR1_PE);
17
I2C1->CR1 |= (I2C_CR1_PE);
18
success = false;
19
break;
20
}
21
}
22
}
23
...
Das habe ich mit dem Oszi aufgezeichnet.
Also, das was dort auf dem Bus geschieht, sieht jedenfalls gut aus.
Das gibt Mut, dass die HW tatsächlich intakt ist.
gelb = SCL
rot = SDA
Pete V. schrieb:> setGPIORegister(GPIOB,0x06,6); //GPIO, OpenDrain, LowSpeed> setGPIORegister(GPIOB,0x06,7); //GPIO, OpenDrain, LowSpeed>> __I2C_SCL(true);> __I2C_SDA(true);
Du hast eine seltsame Herangehensweise.
Also, ich würde an deiner Stelle zu allererst mal folgendes machen:
Pre-Requisites:
USB anwerfen und Kommandoprogramm in die Firmware, damit du mit deinem
µC überhaupt kommunizieren kannst. Alternativ Semihosting, ist mir aber
nicht sympathisch.
So, und dann:
1. Die beiden Portpins aufsetzen
2. beide Portpins per Kommando mit deinen Makros ausprobieren, ob sie
tatsächlich sich so verhalten, wie du es dir gedacht hast.
3. bei Portpins = high auch durch Zurücklesen sicherstellen, daß du den
tatsächlichen Pin-Zustand erfaßt hast und nicht versehentlich den
Zustand der Output-Register geliefert kriegst. Das sollte beim STM32F103
kein Thema sein, gilt aber als Stolperfalle bei anderen µC, z.B. beim
LPC1114. Aber Nachprüfen ist besser als dran glauben.
So, noch ein Wort zu deinen Makros: Der I2C ist eine langsame Sache,
also braucht man auch nicht auf Hochgeschwindigkeit zu achten. Mach dir
lieber für einen Software-I2C sowas:
void SCL_Low(void);
void SCL_High(void);
void SDA_Low(void);
void SDA_High(void);
bool Lies_SDA(void);
Der Aufruf solcher Funktionen ist ne recht sparsame Sache und die Zeit
dafür hast du allemal. Du müßtest zusätzlich auch ne Wartefunktion
vorsehen, um soviel Zeit durch Trampeln zu verplempern, daß die
Geschwindigkeit von SCL nicht höher kommt als etwa 400 kHz.
Und wenn du den eingebauten I2C-Peripherie-Core benutzen willst, dann
kannst du dir sämtliche diesbezüglichen Makros komplett sparen, denn
dann solltest du überhaupt nicht dirkt auf SCL und SDA zugreifen. Aber
soweit ich mich erinnere, ist gerade der I2C beim o.g. Controller ein
eher schwieriges Kind. Ich hab deshalb auf diesem Controller schlichtweg
nur nen Software-I2C laufen. Den hatte ich schonmal gepostet.
W.S.
Pete V. schrieb:> Leider habe ich ein solches Board nicht da.> Habe mir vor kurzem noch einen zweiten STM32 bestellt, sonst habe ich> "nur" AVRs und PICs, sowie den LPC1768 hier.>> Ich habe gerade einmal die Frequenz auf dem I2C verlangsamt, den Slave> entfernt und eine Endlosschleife programmiert, die praktisch immer> das Start-Bit setzt und dann den Byte-Inhalt 0x4E sendet.>>
1
> ....
2
> while(!success){
3
> //Start-Condition
4
>
5
> while(__I2C_BUSY);
6
>
7
> __I2C_START;
8
>
9
> while(!__I2C_START_SENT);
10
> I2C1->DR = (Adr << 1); //Adresse ist 0x27 -> nach dem 'Schieben' ist
11
> der Byteinhalt 0x4E
12
>
13
> success = true;
14
> while(!__I2C_ADDR_SENT){
15
> if((I2C1->SR1 & I2C_SR1_AF)){
16
> __I2C_STOP;
17
> I2C1->CR1 &=~ (I2C_CR1_PE);
18
> I2C1->CR1 |= (I2C_CR1_PE);
19
> success = false;
20
> break;
21
> }
22
> }
23
> }
24
> ...
25
>
>> Das habe ich mit dem Oszi aufgezeichnet.> Also, das was dort auf dem Bus geschieht, sieht jedenfalls gut aus.> Das gibt Mut, dass die HW tatsächlich intakt ist.>> gelb = SCL> rot = SDA
Hab Dir mal angehangen wie das aussehen sollte... das ist die
Kommunikation zum PCF8574T. Ich habe so lange gebraucht weil ich
Pulseview neu bauen und erst wieder konfigurieren mußte...
Muß jetzt zum Nachbarn.
Gruß,
Holm
Holm T. schrieb:> Hab Dir mal angehangen wie das aussehen sollte... das ist die> Kommunikation zum PCF8574T. Ich habe so lange gebraucht weil ich> Pulseview neu bauen und erst wieder konfigurieren mußte...>> Muß jetzt zum Nachbarn.>> Gruß,>> Holm
Danke für die ausführliche Darstellung. Das ist sehr nett von Dir, dass
Du Dir die Arbeit gemacht hast.
Hatte gestern mal die beiden Scopes miteinander verglichen und vom
Signalverlauf her passte das auch.
Hatte auch gestern den Bus kurz am laufen - ich konnte auf jeden Fall im
Sekundentakt die Hintergrundbeleuchtung des Displays ein- und
ausschalten.
Leider ist das ganze konstrukt noch sehr instabil - das ist wohl der
Punkt, an dem man merkt, dass der I2C auf dem Chip tatsächlich eine
Mimose zu sein scheint.
Ich werde nun folgendes tun (um nicht noch mehr Zeit zu investieren):
Ich programmiere nun einen Soft-I2C, nutze die Pins des IC21 als GPIO
und Route diese auch entsprechend auf dem Board, das ich gerade designe.
Wenn dann mein LogicAnalyzer kommt, steige ich noch einmal tiefer ein
und gehe der Sache dann noch einmal auf den Grund.
Bis dahin danke ich Euch allen für Eure Hilfe.
Ich melde mich die Tage noch einmal, was die Analyse mit LA ergeben hat.
Damit der nächste, der ein ähnliches Problem hat, evtl. Abhilfe findet.
Allen einen entspannten Sonntag!
Pete V. schrieb:> Holm T. schrieb:>> Hab Dir mal angehangen wie das aussehen sollte... das ist die>> Kommunikation zum PCF8574T. Ich habe so lange gebraucht weil ich>> Pulseview neu bauen und erst wieder konfigurieren mußte...>>>> Muß jetzt zum Nachbarn.>>>> Gruß,>>>> Holm>> Danke für die ausführliche Darstellung. Das ist sehr nett von Dir, dass> Du Dir die Arbeit gemacht hast.> Hatte gestern mal die beiden Scopes miteinander verglichen und vom> Signalverlauf her passte das auch.>> Hatte auch gestern den Bus kurz am laufen - ich konnte auf jeden Fall im> Sekundentakt die Hintergrundbeleuchtung des Displays ein- und> ausschalten.> Leider ist das ganze konstrukt noch sehr instabil - das ist wohl der> Punkt, an dem man merkt, dass der I2C auf dem Chip tatsächlich eine> Mimose zu sein scheint.>> Ich werde nun folgendes tun (um nicht noch mehr Zeit zu investieren):> Ich programmiere nun einen Soft-I2C, nutze die Pins des IC21 als GPIO> und Route diese auch entsprechend auf dem Board, das ich gerade designe.> Wenn dann mein LogicAnalyzer kommt, steige ich noch einmal tiefer ein> und gehe der Sache dann noch einmal auf den Grund.>>> Bis dahin danke ich Euch allen für Eure Hilfe.> Ich melde mich die Tage noch einmal, was die Analyse mit LA ergeben hat.> Damit der nächste, der ein ähnliches Problem hat, evtl. Abhilfe findet.>> Allen einen entspannten Sonntag!
Mach mal langsam, ich werde Dir die Initailisierungsteile für den I2C
Bus und die Routinen für den EEPROM und das Display hier rein kopieren.
Ich bastele an einen Nonprofit Projekt für einen Freund, der will ne
Teufenanzeige für einen Fahrkorb in einem alten Bergwerksschacht.
Auf dem Fotos siehst Du den Absolutwertgeber und die großen Displays für
die Anzeige. Ich habe mir den I2C Code hier auch nur im Netz
zusammenkopiert, der Kram benutzt die HardwareI2C Schnittstelle, IMHO
SPI3..
Gruß,
Holm
So, ich habe Dir hier mal was zusammenkopiert, wie schon gesagt ist das
nicht Alles auf meinem Mist gewachsen. Nimm Dir raus was Du brauchst.
This is "work in progress" ..and has no warranty for nothing, may kill
your dog ..etc.
Gruß,
Holm
Hallo Holm,
tausend Dank =)
Ich habe mir die Dateien in meiner Code-Sammlung abgelegt und werde mir
diese mal nacheinander ansehen.
Es ist immer wertvoll für mich, die Handschrift und die Umsetzungsweise
anderer Programmierer einsehen zu dürfen.
Noch einmal vielen Dank!
Nun noch einmal zu meinem "Problem..."
Ich habe mir gerade eben einmal den Soft-I2C Code zusammengeschrieben
und auf den Chip geladen.
Das Display ließ sich direkt ansprechen und hat alle Befehle
entgegengenommen.
Hab dazu meine "Lib" genommen, die ich seiner Zeit mal für den AVR
erstellt hatte und auf den ARM umgeschrieben.
Jetzt kommt das kuriose:
Nachdem ich das Display per Soft-I2C angesprochen habe, habe ich noch
einmal den Code vom HW-I2C in den Controller geladen und siehe da.
Jetzt gehts...
Manche Dinge muss man glaube ich nicht direkt verstehen.
Räume jetzt meine Funktionen auf und dann geht's zum nächsten Schritt.
Der I2C läuft jetzt mit PCLK1 auf 36MHz und CCR auf (36M/100k), also mit
50kHz stabil.
Hab den Controller jetzt zig mal neu gestartet, neu geflasht, etc. - der
Bus scheint immer noch stabil zu laufen.
Danke an alle Experten.
Wenn ich eine Erklärung für dieses Phänomen habe, lasse ich es euch
wissen!
Pete V. schrieb:> Nachdem ich das Display per Soft-I2C angesprochen habe, habe ich noch> einmal den Code vom HW-I2C in den Controller geladen und siehe da.> Jetzt gehts...> Manche Dinge muss man glaube ich nicht direkt verstehen.
Wenn der I²C Bus blockiert, muss man manchmal die Stromversorgung vom
Master und Slave komplett aus schalten, um da wieder raus zu kommen.
Ich habe deswegen schon mal erwägt, einen Power-Reset Knopf in meinen
USB Hub einzubauen.