Forum: Mikrocontroller und Digitale Elektronik STM32: I2C-Master setzt ARLO-Flag (arbitration lost)


von Andreas E. (andrerf)



Lesenswert?

Hallo,
ich habe ein Problem mit der I2C Schnittstelle im STM32 F103C8T6 (Blue 
Pill).
Und zwar kann ich damit keine I2C Kommunikation starten. Beim Versuch, 
Daten (z. B. eine Slave-Adresse) zu senden, wird das ARLO-Bit im SR1 
Register gesetzt und MSL-Bit (im SR2 Register) geht auf 0. Dies passiert 
in dem Moment, wenn das Datenregister DR beschrieben wird. Dies habe 
durch Debugging herausbekommen.

Hier der relevante Code-Ausschnitt:
1
  errata_2_14_7_workaround();
2
  LL_I2C_GenerateStartCondition(I2C1);
3
  while(!LL_I2C_IsActiveFlag_SB(I2C1)){};
4
  (void) I2C1->SR1;   //read SR1 register
5
6
  LL_I2C_TransmitData8(I2C1, (0x27 << 1));      
7
                            //0x27 is the address of the Slave
8
                            //ARLO=1, MSL=0
9
  while(!LL_I2C_IsActiveFlag_ADDR(I2C1) && !LL_I2C_IsActiveFlag_AF(I2C1))
10
  {
11
  };  //the program hangs here

Wie man sieht, verwende ich die LL-Library. Die Funktion
void LL_I2C_TransmitData8(I2C_TypeDef *I2Cx, uint8_t Data)
hat folgenden Inhalt:
1
{
2
  MODIFY_REG(I2Cx->DR, I2C_DR_DR, Data);
3
}

Normalerweise kann das ARLO-Bit nur gesetzt werden, wenn es mehrere 
Master gibt. Es bedeutet nämlich, dass unser Master die Kontrolle über 
den Bus an einen anderen Master verloren hat. Unser Master merkt das an 
einer Änderung von SDA oder SCL, die er nicht selbst verursacht hat.

In meinem Fall liegt aber nur ein Master vor, und ich habe es auch ohne 
angeschlossenen Slave probiert und gedebuggt (selbes Ergebnis).

Ich habe die Datei main.c und Bilder der Konfiguration sowie ein 
Oszilloskop-Signalverlauf meines Programms angehängt.

Der Oszilloskop-Signalverlauf entsteht größtenteils durch die 
errata_2_14_7_workaround() Funktion, da dort die Pins manipuliert und 
das I2C neugestartet wird (um einen anderen Fehler zu beseitigen). Bei 
der Transmit-Funktion passiert nichts, die Datenbits (Adressbits) werden 
nicht auf den SDA gelegt.

Vielleicht übersehe ich etwas oder habe etwas falsch konfiguriert. Ich 
wäre dankbar für jede Hilfe!

von jo mei (Gast)


Lesenswert?

Andreas E. schrieb:
> Ich wäre dankbar für jede Hilfe!

Ein wichtiges Detail fehlt: ein authentischer Schaltplan.
Aber bitte keinen Prosa-Schaltplan.

Andreas E. schrieb:
> und ich habe es auch ohne
> angeschlossenen Slave probiert und gedebuggt

Da ist dann schon ein Fehler versteckt.

von jo mei (Gast)


Lesenswert?

jo mei schrieb:
> Da ist dann schon ein Fehler versteckt.

Wollte sagen, ein offener I2C Bus ohne Partner macht nur Mist.
Die beiden Leitungen floaten nämlich vor sich hin.

von Andreas E. (andrerf)


Angehängte Dateien:

Lesenswert?

Danke für die schnelle Antwort.

Ich werde gleich mit Oszilloskop den Verlauf an den PB6 (SCL) und PB7 
(SDA) Pins messen bei abgeschlossenem Slave. ARLO wird gesetzt sowohl 
mit angeschlossenem Slave, als auch ohne.

Mein Schaltplan: nur das Blue Pill Board STM32F103C8T6, nichts dran 
angeschlossen. Strom von USB.

Schaltplan des Blue Pill Boards: 
[[Datei:Vcc-gnd.com-blue-pill-schematic-stm32f103c8t6.pdf]]

von Andreas E. (andrerf)


Lesenswert?


von jo mei (Gast)


Lesenswert?

Andreas E. schrieb:
> Mein Schaltplan: nur das Blue Pill Board STM32F103C8T6, nichts dran
> angeschlossen. Strom von USB.

Ein I2C Bus braucht Pullups, sonst

jo mei schrieb:
> Die beiden Leitungen floaten nämlich vor sich hin.

Lese und verstehe!

von Andreas E. (andrerf)


Lesenswert?

jo mei schrieb:
> Ein I2C Bus braucht Pullups

Normalerweise kann ich in STM32CubeIDE bei den GPIO Settings aussuchen, 
ob ich interne Pull-Ups / Pull-Downs oder Open Drain verwenden möchte. 
Wenn ich die Pins für I2C verwende, kann ich das nicht. Also dachte ich, 
das tut das Board oder die IDE automatisch.

Kann ich einen Pullup-Widerstand auch extern anschließen? Welchen 
Widerstandswert soll er haben und wo genau soll ich ihn anschließen?

von dummschwaetzer (Gast)


Lesenswert?

>Kann ich einen Pullup-Widerstand auch extern anschließen? Welchen
ja, musst du meist unbedingt, da die internen pull-up zu groß sind
>Widerstandswert soll er haben und wo genau soll ich ihn anschließen?
siehe I2C Spezifikation, pauschal 2,2 kOhm nach VCC

von Andreas E. (andrerf)


Lesenswert?

dummschwaetzer schrieb:
> ja, musst du meist unbedingt

Habe bisher in keiner Anleitung zu Blue Pill & I2C gesehen, dass externe 
Pull-Ups angeschlossen werden. Aber ich probiere das mal aus.

von dummschwaetzer (Gast)


Lesenswert?

beim Arduino ist es meist auf den Zubehörplattinen, häufig 10k.

von jo mei (Gast)


Lesenswert?

Andreas E. schrieb:
> Habe bisher in keiner Anleitung zu Blue Pill & I2C gesehen, dass externe
> Pull-Ups angeschlossen werden.

Du kannst dich ruhig weiterhin beratungsresistent zeigen, dann
kommst du sicherlich zum Ziel bzw. zum Erfolg.

Du fragst hier, willst aber Antworten die dir passen. Na dann,
das wird lustig!

von Andreas E. (andrerf)


Angehängte Dateien:

Lesenswert?

jo mei schrieb:
> u kannst dich ruhig weiterhin beratungsresistent zeigen, dann
> kommst du sicherlich zum Ziel bzw. zum Erfolg.

Das ist ein Missverständnis. Ich habe mich nur gewundert, warum in den 
Anleitungen kein externer Pull-Up verwendet wird. Eure Ratschläge nehme 
ich gerne an!

Habe auch schon den Signalverlauf mit angeschlossenem Slave (PCF8574T) 
ohne externen Pull-Up gemessen. Dasselbe Ergebnis.
Signalverlauf: oben SDA, unten SCL.

Werde jetzt die I2C Spezifikation überfliegen und es mit externem 
Pull-Up versuchen.

von dummschwaetzer (Gast)


Lesenswert?

für eine HW-I2C sieht das aber sehr komisch aus.

von jo mei (Gast)


Lesenswert?

dummschwaetzer schrieb:
> für eine HW-I2C sieht das aber sehr komisch aus.

Ja, ich kann da auch keinen typischen I2C Clock erkennen.
Messfehler oder falsche Konfiguration.

von Andreas E. (andrerf)


Lesenswert?

dummschwaetzer schrieb:
> für eine HW-I2C sieht das aber sehr komisch aus.

Wie bereits in der Frage beschrieben, der Signalverlauf kommt 
größtenteils von der Funktion errata_2_14_7_workaround, welche die SDA 
und SCL Pins manipuliert und das I2C-Modul neustartet (für 
Funktionsdefinition siehe main.c unten). Ich habe das aufgrund eines 
anderen Fehlers implementiert (Fehler wird in Errata Sheets 2.14.7 
beschrieben).

von Andreas E. (andrerf)


Lesenswert?

jo mei schrieb:
> Ja, ich kann da auch keinen typischen I2C Clock erkennen.
> Messfehler oder falsche Konfiguration.

Ich vermute, wenn der Master einen ARLO setzt und somit zum Slave wird, 
dass er auch die SCL nicht mehr steuert. Das passiert zum Zeitpunkt der 
Transmit-Funktion. (Vorher findet noch das errata_2_14_7_workaround und 
die Start Condition statt.)

von dummschwaetzer (Gast)


Lesenswert?

errata_2_14_7_workaround();
hier SCL und SDA high!
  LL_I2C_GenerateStartCondition(I2C1);

  LL_I2C_TransmitData8(I2C1, (0x27 << 1));
                            //0x27 is the address of the Slave
                            //ARLO=1, MSL=0
hier SCL: 9 mal Low-> High->Low gleichlange Zeiten,SDA Wechsel nur wenn 
SCL low.

SCL und SDA unbedingt im Open-Drain Modus lassen!

>errata_2_14_7_workaround()
was macht die genau?

Warum nimmst du nicht entsprechende HAL-Funktionen?

von jo mei (Gast)


Lesenswert?

Andreas E. schrieb:
> Ich vermute, wenn der Master einen ARLO setzt und somit zum Slave wird,
> dass er auch die SCL nicht mehr steuert.

Ja mag sein ....

Ich habe sooo oft von solchen Macken gehört. Für mich wieder
mal ein Grund das Ganze in Software (Soft-I2C) zu lösen. Ich
habe das von Anfang an nie anders gemacht, einfach die vom AVR
existierenden Soft-Routinen auf STM32 angepasst. Funktioniert
für mich seit Jahren. YMMV.

von Andreas E. (andrerf)


Lesenswert?

dummschwaetzer schrieb:
> SCL und SDA unbedingt im Open-Drain Modus lassen!

Meinst du damit keine externen Pull-Ups anschließen?

dummschwaetzer schrieb:
>>errata_2_14_7_workaround()
> was macht die genau?
>
> Warum nimmst du nicht entsprechende HAL-Funktionen?

Ich hatte den Fehler, dass der Busy-Flag die ganze Zeit gesetzt war.
Ich habe die in
https://www.st.com/resource/en/errata_sheet/cd00190234-stm32f101x8b-stm32f102x8b-and-stm32f103x8b-mediumdensity-device-limitations-stmicroelectronics.pdf
auf Seite 26 beschriebenen Schritte befolgt. In main.c unten ist die 
Definition der Funktion. Dies hat den BUSY-Fehler beseitigt.

Wusste nicht, dass es schon fertige HAL- oder LL-Funktionen dafür gibt.

von Andreas E. (andrerf)


Lesenswert?

jo mei schrieb:
> Für mich wieder
> mal ein Grund das Ganze in Software (Soft-I2C) zu lösen. Ich
> habe das von Anfang an nie anders gemacht, einfach die vom AVR
> existierenden Soft-Routinen auf STM32 angepasst.

Kannst du mir einen Link schicken? Ich höre davon zum ersten Mal, kann 
mir nicht vorstellen wie man das macht. Wenn es mit den externen 
Pull-Ups nicht klappt, möchte das versuchen.

von dummschwaetzer (Gast)


Lesenswert?

>Wenn es mit den externen Pull-Ups nicht klappt, möchte das versuchen
Die externen Pull-Ups sind Teil des I2C-Standart! Ohne die geht es nicht 
standartkonform!
Die soft-I2C ist doch pillepalle. Clock entsprechend setzen, SDA setzen 
oder einlesen und ein bischen bitgeschubse. Fals dein Slave 
Clock-Stretch kann auch clock einlesen und prüfen. und natürlich einige 
delays(), allerdings nicht im millisekundenbereich.
Insgesammt geht es aber mit HW deutlich einfacher:
senden:
/**
  * @brief  Transmits in master mode an amount of data in blocking mode.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  DevAddress Target device address: The device 7 bits address 
value
  *         in datasheet must be shifted to the left before calling the 
interface
  * @param  pData Pointer to data buffer
  * @param  Size Amount of data to be sent
  * @param  Timeout Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, 
uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
empfangen:
/**
  * @brief  Receives in master mode an amount of data in blocking mode.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  DevAddress Target device address: The device 7 bits address 
value
  *         in datasheet must be shifted to the left before calling the 
interface
  * @param  pData Pointer to data buffer
  * @param  Size Amount of data to be sent
  * @param  Timeout Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, 
uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)

von Andreas E. (andrerf)



Lesenswert?

So, ich habe jetzt die externen Pull-Ups drangelötet. Einen 2,2 kOhm 
zwischen 5V und SCL und einen 2,6 kOhm zwischen 5V und SDA.

Zunächst konnte ich am Signalverlauf keinen Unterschied feststellen und 
beim Debugging kam wieder das ARLO.
Dann habe ich den Aufruf der errata_2_14_7_workaround Funktion 
auskommentiert - und siehe da, das Programm funktioniert nun (fast) wie 
gewünscht!

Wie kann man nun das erklären?

Zusammenfassung:
1) keine externen Pull-Ups, kein errata_2_14_7_workaround:
 - zufällig: BUSY-Flag wird gesetzt und lässt sich nicht rücksetzen
 - ansonsten: ARLO-Flag wird gesetzt, MSL rückgesetzt
2) keine externe Pull-Ups, mit errata_2_14_7_workaround:
 - BUSY-Flag-Fehler tritt nicht mehr auf
 - ARLO-Flag wird gesetzt, MSL rückgesetzt
3) mit externen Pull-Ups, mit errata_2_14_7_workaround:
 - wie 2)
4) mit externen Pull-Ups, ohne errata_2_14_7_workaround:
 - kein BUSY-Flag-Fehler (könnte zufällig auftreten?)
 - kein ARLO-Flag-Fehler!
 - AF wird gesetzt (Acknowledge Failure, obwohl Slave angeschlossen ist 
und 0x27 die richtige Adresse ist).

Habe auch den Signalverlauf von 4) beigefügt. Man sieht nun, wie die 
Bitfolge 01001110 auf SDA gelegt wird (entspricht 0x4e also 0x27 << 1).

Anscheinend verursacht meine errata_2_14_7_workaround Funktion den 
ARLO-Flag-Fehler, wobei er bei 1) auch auftrat. Ich muss mal eine HAL- 
oder LL-Funktion probieren die das Workaround für den zufälligen 
BUSY-Flag-Fehler hat.

Der nächste Schritt wäre also, dem AF auf den Grund zu gehen.

Vielen Dank für die Hilfe an euch beide, ich wäre nicht allein auf die 
Idee gekommen, externe Pull-Ups zu verwenden (aufgrund mangelnder 
I2C-Kenntnisse).

von Andreas E. (andrerf)


Lesenswert?

Sollte ich nicht zuerst die Stop-Condition generieren, bevor ich auf 
ADDR oder AF warte?

von Andreas E. (andrerf)


Lesenswert?

Andreas E. schrieb:
> Sollte ich nicht zuerst die Stop-Condition generieren, bevor ich auf
> ADDR oder AF warte?

Habe gerade in die Spezifikation geschaut, die Stop-Condition kommt nach 
dem Acknowledge.

von Andreas E. (andrerf)


Lesenswert?

Mir fällt gerade auf, ADDR Bit wird nicht gesetzt, heißt, Adresse wird 
nicht gesendet. Obwohl sie an SDA ist, wie man am Signalverlauf sieht.

von neuer PIC Freund (Gast)


Lesenswert?

Du schaltest den Treiber von OC auf PP. Deswegen schwebt das Ack auch so 
schön bei 1.5V, wenn Treiber gegen Treiber arbeitet.

von dummschwaetzer (Gast)


Lesenswert?

jep, das Bild sieht deutlich besser aus, aber
>Einen 2,2 kOhm zwischen 5V und SCL und einen 2,6 kOhm zwischen 5V und SDA.
Laut deinem Oszi Bild ist da aber noch ein aktiver High. Das darf nicht!
SDA und SCL sollten die 5V als High haben. Deine Flanken low->high sehen 
zu gut aus. Irgendjemand am Bus( wahrscheinlich der Master) ist da nicht 
auf openDrain konfiguriert! Wieso eigentlich 5V? Der STM kann nur max 
3,6! Bist du sicher, dass deine für die i2c verwendeten Ports 
5V-kompatibel sind?

von dummschwaetzer (Gast)


Lesenswert?

>Mir fällt gerade auf, ADDR Bit wird nicht gesetzt, heißt, Adresse wird
>nicht gesendet. Obwohl sie an SDA ist, wie man am Signalverlauf sieht.
deine pegel stimmem nicht! Das ist Lotterie ob das ACK von deinem master 
as solches erkannt wird, und damit sind auch die Statusflags Zufall.

von Andreas E. (andrerf)


Lesenswert?

neuer PIC Freund schrieb im Beitrag #6633005:
> Du schaltest den Treiber von OC auf PP.

Wie, wo? Habe ich nicht ganz verstanden...

dummschwaetzer schrieb:
> Bist du sicher, dass deine für die i2c verwendeten Ports
> 5V-kompatibel sind?

Ja, siehe Pin Details Bild weiter oben, PB6 und PB7. An dem PCF8574T ist 
ein LCD-Display dran, wenn ich nur 3,3 V anschließe, zeigt das Display 
keine Rechtecke an. Bei 5 V werden die Rechtecke deutlich gezeigt. Ich 
habe auch einen Atmega328PB, dort funktioniert dieses PCF8574T-Display 
auch über 5 V.

dummschwaetzer schrieb:
> Irgendjemand am Bus( wahrscheinlich der Master) ist da nicht
> auf openDrain konfiguriert!

In der MX_I2C1_Init()-Funktion werden die beiden Pins (PB6 und PB7) als 
OpenDrain konfiguriert (siehe main.c). Danach wird an dieser 
Konfiguration nichts mehr geändert.

von Andreas E. (andrerf)


Lesenswert?

Ich habe es jetzt mit 3,3 V probiert, der Acknowledge Failure kommt 
ebenfalls.

von Andreas E. (andrerf)


Lesenswert?

dummschwaetzer schrieb:
> SDA und SCL sollten die 5V als High haben.

Laut I2C-Spezifikation sollte High 70% von Vcc und Low 30% von Vcc sein.

von Andreas E. (andrerf)


Lesenswert?

Andreas E. schrieb:
> Laut I2C-Spezifikation sollte High 70% von Vcc und Low 30% von Vcc sein.

Habe mir gerade das Thema zu den Logikpegeln in der Spezifikation 
genauer angeschaut. Tatsächlich, die 30/70% von Vcc sind nur zur 
Interpretierung seitens der I2C-Partner da und am Oszilloskop sollte die 
Spannung 0 und Vcc betragen (Fig. 38). Also in meinem Fall 5V. Werden 
aber nur 3,3V angezeigt.

von Stefan F. (Gast)


Lesenswert?

Andreas E. schrieb:
> Ich habe mich nur gewundert, warum in den
> Anleitungen kein externer Pull-Up verwendet wird.

Welche sind denn "die" Anleitungen? In meinen steht es sehr deutlich 
drin und auch in allen anderen die ich in Erinnerung habe.

Wenn man verstanden hat, wie der BUS grundsätzlich funktioniert, dann 
ist das mit den Widerständen allerdings sonnenklar. Ich denke daher dass 
du dich hier auf das sehr dünne Brett begeben hast, einen Bus zu 
verwenden ohne dich über seine Funktionsweise informiert zu haben.

Das solltest du dringend nachholen.

Andreas E. schrieb:
> Habe auch schon den Signalverlauf mit angeschlossenem Slave (PCF8574T)
> ohne externen Pull-Up gemessen.

Kein Wunder! Sag mal liest du überhaupt die Antworten?

von Stefan F. (Gast)


Lesenswert?

Andreas E. schrieb:
> Wie bereits in der Frage beschrieben, der Signalverlauf kommt
> größtenteils von der Funktion errata_2_14_7_workaround, welche die SDA
> und SCL Pins manipuliert und das I2C-Modul neustartet

Lies nochmal das Errata und implementiere es so, wie dort beschrieben. 
ich habe es gemacht und es funktionierte auf Anhieb sauber ohne derart 
seltsame Signale zu erzeugen. Falls du abgucken willst: 
http://stefanfrings.de/stm32/stm32f1.html#i2c

Da sollte man aber noch Abbrüche nach Timeout einbauen.

von Stefan F. (Gast)


Lesenswert?

jo mei schrieb:
> Ich habe sooo oft von solchen Macken gehört. Für mich wieder
> mal ein Grund das Ganze in Software (Soft-I2C) zu lösen.

Eine verlockende Idee, aber dadurch verzichtest du auch auf die analogen 
I²C spezifischen Filter im IC. Bei langen Leitungen sind die durchaus 
nützlich.

von Stefan F. (Gast)


Lesenswert?

dummschwaetzer schrieb:
> Wieso eigentlich 5V? Der STM kann nur max. 3,6!

Das ist nicht richtig. PB6 und PB7 sind 5V tolerant.

Ich stimme dir aber zu, dass der Wechsel von 5V nach 3,3V im 
Oszilloskopbild auf den Fehler hinweist, dass irgednwer die HIGH Pegel 
aktiv treibt, was nicht sein darf.

Die 1,5V beim ACK sind ein Folgefehler dessen, das Resultat eine 
Kurzschlusses.

Für den PCF8574 Chip braucht er 5V. Mit 3,3V als HIGH funktioniert der 
Chip nicht zuverlässig bzw. nur mit Glück.

von dummschwaetzer (Gast)


Lesenswert?

Debug halt mit oszi, um die Stelle, an der deine SDA SCL von 5V auf 3,3V 
geht, einzugrenzen. Das kann eigentlich nur vom STM kommen!
Und das bevor du dein START sendest!

von dummschwaetzer (Gast)


Lesenswert?

Was macht deine SW zu dem Zeitpunkt "Oszi Bild blau 1.000V"
Da stimmen 2 Sachen nicht: Pegel von 5V auf 3,3V und SCL und SDA gehen 
auf low, ohne dass ein START kam.

von Peter D. (peda)


Lesenswert?

Andreas E. schrieb:
> Der Oszilloskop-Signalverlauf entsteht größtenteils durch die
> errata_2_14_7_workaround() Funktion

Die errata 2.14.7 ist ja wirklich ein dicker Hund:
"The I2C analog filters embedded in the I2C I/Os may be tied to low 
level, whereas SCL and SDA lines are kept at high level."
...
"This issue occurs randomly."

Für mich heißt das, klopp das HW-I2C in die Tonne und mache I2C in SW 
mit Pinwackeln.
I2C wird ja wohl nicht den Großteil der CPU-Zeit benötigen.
Die anderen 6 I2C-Fehler habe ich mir nicht auch noch angesehen.

von Andreas E. (andrerf)


Angehängte Dateien:

Lesenswert?

dummschwaetzer schrieb:
> Debug halt mit oszi, um die Stelle, an der deine SDA SCL von 5V auf 3,3V
> geht, einzugrenzen. Das kann eigentlich nur vom STM kommen!
> Und das bevor du dein START sendest!

Das passiert in der MX_I2C1_Init-Funktion.

Beim Aufruf

LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

geht es von 5V auf 0V runter, danach

LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

von 0V auf 3,3V.

von dummschwaetzer (Gast)


Lesenswert?

>&GPIO_InitStruct
zeig mal, insbesonders der bitbrei, der für alternate function output 
open drain verantwortlich ist.
kannst du da die reihenfolge ändern?
erst clock an, dann port init.

von Andreas E. (andrerf)


Angehängte Dateien:

Lesenswert?

Ich habe mir gerade die LL_GPIO_Init Funktion angeschaut (siehe Anhang). 
Dort gibt es zum Schluss einen Aufruf

      /* Pull-up Pull-down resistor configuration*/
      LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull);

Also wird hier ein interner Pull-Up konfiguriert...

von Andreas E. (andrerf)


Lesenswert?

dummschwaetzer schrieb:
> kannst du da die reihenfolge ändern?
> erst clock an, dann port init.
1
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
2
3
  GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
4
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
5
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
6
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
7
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

führt zum selben Ergebnis. 5V -> 0V -> 3,3V, AF

von Harry L. (mysth)


Lesenswert?

Warum zum Geier willst du das auf Biegen und Brechen mit den 
LL-Funktionen realisieren, wo du doch offensichtlich weder Erfahrungen 
mit I²C im Algemeinen noch mit HAL hast.

Mach es doch erstmal mit den normalen HAL-Funktionen!
Da ist das nämlich ganz einfach:

Schreiben:
1
uint8_t data, result;
2
3
    result = HAL_I2C_Master_Transmit(&hi2cx, PCF8574_ADR, &data, 1, 2);
4
    if (result != HAL_OK)
5
      {
6
        // Error
7
      }
8
    else
9
      {
10
         // everything fine
11
      }

Lesen:
1
uint8_t data, result;
2
3
    result = HAL_I2C_Master_Receive(&hi2cx, PCF8574_ADR, &data, 1, 2);
4
    if (result != HAL_OK)
5
      {
6
        // Error
7
      }
8
    else
9
      {
10
         // Data in data is valid
11
      }

: Bearbeitet durch User
von Andreas E. (andrerf)


Lesenswert?

Hatte es vorher mit HAL-Funktionen gemacht. Dann wollte ich dem Fehler 
auf den Grund gehen und habe dafür die LL-Library verwendet, da sie 
etwas kleinteiliger sind und man damit besser nachvollziehen kann was im 
Programm passiert.
Habe gerade eben nochmal ein Programm mit HAL-Bibliothek geschrieben und 
werde es gleich debuggen.

von Harry L. (mysth)


Lesenswert?

Andreas E. schrieb:
> Dann wollte ich dem Fehler
> auf den Grund gehen

Jaja..."dem Fehler"...
Kein Wunder wenn du die PullUps vergisst...mit Software hat das garnix 
zu tun.

von Andreas E. (andrerf)


Lesenswert?

Ich habe jetzt mein Programm zur Ansteuerung des LCD-Displays nach
https://www.youtube.com/watch?v=e-KgHsQPkwg
geschrieben.
Resultat:
lcd16x2_i2c_init(&hi2c1); wird erfolgreich ausgeführt
lcd16x2_i2c_printf("Hello World"); gebt den gewünschten Text nicht aus

Oszilloskop-Verlauf zeigt aber Spannungen von 0 und 5 V an, keine 3,3V!

von Andreas E. (andrerf)


Lesenswert?

Harry L. schrieb:
> Kein Wunder wenn du die PullUps vergisst

Ich hatte an die Pull-Ups gedacht, jedoch mich darauf verlassen dass sie 
schon intern gesetzt wurden. Und das war mein Fehler.

von dummschwaetzer (Gast)


Lesenswert?

>führt zum selben Ergebnis. 5V -> 0V -> 3,3V, AF
das genau dürfte nicht passieren. Der Port sollte von input,tristate 
nach AF output OD schalten, deine I2C-HW sollte "High" ausgeben. Im 
Oszi-Bild sollten da also horizontale Linien bei 5V zu sehen sein.

von Harry L. (mysth)


Lesenswert?

Hier hast du funktionierenden Code für dein Display mit HAL.
Wenn du PullUps angeschlossen hast, läuft der out-of-the-box.

Beitrag "Re: [STM32/HAL] generischer Treiber für die beliebten I²C-Text-Displays"

: Bearbeitet durch User
von jo mei (Gast)


Lesenswert?

Andreas E. schrieb:
> Ich hatte an die Pull-Ups gedacht, jedoch mich darauf verlassen dass sie
> schon intern gesetzt wurden.

Ich ahnte es .... schon vor ca 30 Jahren habe ich es gesagt:

jo mei schrieb:
> Ein I2C Bus braucht Pullups, sonst
>
> jo mei schrieb:
>> Die beiden Leitungen floaten nämlich vor sich hin.
>
> Lese und verstehe!

jo mei schrieb:
> Du kannst dich ruhig weiterhin beratungsresistent zeigen, dann
> kommst du sicherlich zum Ziel bzw. zum Erfolg.
>
> Du fragst hier, willst aber Antworten die dir passen. Na dann,
> das wird lustig!

von jo mei (Gast)


Lesenswert?

jo mei schrieb:
> Na dann, das wird lustig!

.... und es wurde lustig.

von Andreas H. (ahz)


Lesenswert?

Andreas E. schrieb:
> Ich habe jetzt mein Programm zur Ansteuerung des LCD-Displays nach
> https://www.youtube.com/watch?v=e-KgHsQPkwg
> geschrieben.
> Resultat:
> lcd16x2_i2c_init(&hi2c1); wird erfolgreich ausgeführt
> lcd16x2_i2c_printf("Hello World"); gebt den gewünschten Text nicht aus
>
> Oszilloskop-Verlauf zeigt aber Spannungen von 0 und 5 V an, keine 3,3V!

Die bentzen aber auch die HAL Funktionen, was Dir ja hier auch schon 
mehrere User vorgeschlagen hatten ...

Und wenn Du jetzt noch die Adresse DEINES I2C Slaves wieder in die 
Sourcen von MYaqoobEmbedded reinbaust, dann  sollte da auch Text kommen 
;)

/regards

von Andreas E. (andrerf)


Lesenswert?

jo mei schrieb:
> Andreas E. schrieb:
>> Ich hatte an die Pull-Ups gedacht, jedoch mich darauf verlassen dass sie
>> schon intern gesetzt wurden.

Ich rede über die Zeit, bevor ich diesen Thread gestartet habe und den 
Hinweis über externe Pull-Ups bekommen habe.

von Andreas E. (andrerf)


Angehängte Dateien:

Lesenswert?

Andreas H. schrieb:
> Und wenn Du jetzt noch die Adresse DEINES I2C Slaves wieder in die
> Sourcen von MYaqoobEmbedded reinbaust, dann  sollte da auch Text kommen

Danke für den Hinweis, das habe ich komplett vergessen! Da ich diese 
Bibliothek schon mal probiert hatte, war bei mir in der Init-Funktion 
alles umgekrempelt wegen der Fehlersuche. Habe sie jetzt wieder in 
Ordnung gebracht. Der Funktionsaufruf (in der Funktion lcd16x2_i2c_init)
HAL_I2C_IsDeviceReady(pI2cHandle, LCD_I2C_SLAVE_ADDRESS, 3, 100);
für die Adresse 0x27 liefert leider kein HAL_OK. Somit liefert die 
init-Funkion jetzt false.

von Andreas E. (andrerf)


Lesenswert?

So, Fehler gefunden! Habe nur noch in der Definition für die Adresse << 
1 ergänzt. Display zeigt jetzt gewünschten Text an!

Vielen Dank an alle für die Hilfe!

von Stefan F. (Gast)


Lesenswert?

Peter D. schrieb:
> Für mich heißt das, klopp das HW-I2C in die Tonne

Wieso das denn, das Errata beschreibt doch einen durchaus umsetzbaren 
Workaround.

Andreas E. schrieb:
> liefert leider kein HAL_OK. Somit liefert die init-Funkion jetzt false.

Sollen wir jetzt raten, wie die Signale aussehen?

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.