Lesen Sie einfach ein Register

Ich verwende einen STM32F103CBT6 als I2C-Master. Nach dem Senden der I2C-Adresse des Slaves muss ich das Addr-Bit im SR1-Register löschen. Das Datenblatt besagt:

"ADDR: Adresse gesendet (Master-Modus)/abgestimmt (Slave-Modus) Dieses Bit wird gelöscht, indem die Software das SR1-Register liest, gefolgt vom Lesen von SR2"

Daher habe ich zwei Zeilen nach der beschäftigten Warteschleife, die nach dem Bit wie folgt sucht:

uint16_t a = I2C1->SR1;
uint16_t b = I2C1->SR2;

Dies funktioniert gut und der Compiler optimiert die Lesevorgänge nicht, da die Register als deklariert sind volatile, aber es warnt mich, da die beiden Variablen niemals gelesen werden und daher nutzlos sind. Ich möchte diese Warnungen loswerden. Funktioniert es garantiert, wenn ich die Zeilen so ändere:

I2C1->SR1;
I2C1->SR2;

Oder sollte ich das Bit manuell löschen, ohne jemals SR2 zu lesen?

Vielen Dank im Voraus

Dies ist so ziemlich eine StackOverfow-Frage. Aber ja, wenn diese volatil sind, sollte es funktionieren. Alternativ können Sie (void)a; (void)b;den Hauptteil der Funktion einfügen, um die Warnungen stumm zu schalten.
Nicht wirklich. Es sieht so aus, als ob es nicht so funktioniert, wie Sie es vorschlagen: arm.godbolt.org/z/vljOTL . Wahrscheinlich, weil p;der Zugriffstyp nicht impliziert p(Lesen oder Schreiben).
Wenn ich ein Asterix vor dem p hinzufüge, wird eine ldr-Anweisung generiert.
Hm. Ja, das sollte so getestet werden. Ich bin mir immer noch nicht sicher, ob es garantiert in eine Leseanweisung übersetzt wird. Eine gültige und wahrscheinlich gute Frage für SO, wenn sie richtig formuliert ist.

Antworten (2)

Der übliche Weg, dies sicher und portabel zu tun:

volatile uint16_t dummy = I2C1->SR1;
(void)dummy;

Dies funktioniert normalerweise sogar auf dysfunktionalen Compilern. Wenn der Compiler immer noch warnt, müssen Sie einen Fehlerbericht an den Compiler-Anbieter senden.

Wenn Sie das Bit manuell löschen können, würde dies Ihren Code klarer machen. Wenn die einzige Möglichkeit zum Löschen des Bits darin besteht, die Register zu lesen, ist dies eine gute Möglichkeit:

//Reading SR1 and SR2 automatically clears the ADDR bit
(void)I2C1->SR1;
(void)I2C1->SR2;

was es für zukünftige Leser offensichtlich macht, dass Sie die Variable wirklich lesen und ihren Wert ignorieren möchten. Solange I2C1 ein Zeiger auf eine flüchtige Struktur ist (was es auch ist), wird der Compiler tun, was Sie erwarten.

Ich würde das nicht empfehlen - der C-Standard ist hier ziemlich vage und viele Compiler verhalten sich auch schlecht, wenn sie nur einen flüchtigen Bezeichner in einer einzelnen Zeile erhalten.