Hallo
Ich bin noch relativ neu im programmieren und hätte eine Frage.
Ich habe einen IC der per SPI (und STM32) durch verschiedene Register
angesprochen werden kann. Die Register sind alle 32bit groß und können
zum Teil beschrieben oder gelesen werden. Bis dato habe ich die Register
immer direkt geschrieben:
1
reg
2
R/Waddr<-------Daten-------->
3
|||||
4
Bsp.:0x810000010b10000001000000000000000000000001
5
6
uint32_tsendRegister=0x81000001
Mit der Zeit wird das aber ziemlich kryptisch und ich würde viel lieber
etwas in dieser Art schreiben:
Aber wie funktioniert das dass ich in meiner IDE (Eclipse) von dem "IC"
als Child sozusagen "IC_CONFIG" auswählen kann, mit diesem
"Rechtspfeil"? Ich weiß leider nicht die korrekte Bezeichnung.
Aber es soll dann so aussehen:
1
?
2
|
3
uint32_tsendRegister=IC->IC_CONFIG|IC_WRITE|DATA;
Und statt IC_CONFIG sollen dann natürlich auch die ganzen anderen
Register Adressen des IC ansprechbar sein.
Paul G. schrieb:> mit diesem "Rechtspfeil"?
Der "Rechtspfeil" ist nur eine Abkürzung.
1
foo->bar
steht für
1
(*foo).bar
Damit ist auch klar, dass "foo" ein Zeiger sein muss, der dereferenziert
wird. Derartige Zugriffe auf irgendwelche Register funktionieren also
nur dann, wenn diese memory mapped sind, d.h. die Hardware der CPU
bildet sie auf eine Speicheradresse ab.
Für irgendwelche Geräte, die nicht direkt auf einen Speicherbus
abgebildet werden (I²C, SPI, …) kann man diese Schreibweise folglich
nicht benutzen.
Jörg W. schrieb:> funktionieren also> nur dann, wenn diese memory mapped sind
Okay, verstehe. Genau da ist das mir auch begegnet... In den tiefen der
STM32 Firmware Header...
Jörg W. schrieb:> C++ hat das.
:) Okay, das ist aber bei meinem STM32 Projekt nicht drinn. Ich will
schon bei C bleiben.
Dann schreibe ich mir halt ein paar "defines" in den Header mit den
häufigsten Register Adressen die ich dann im Code noch "bitmathen" kann.
Paul G. schrieb:> uint32_t sendRegister = (IC | IC_WRITE | IC_CONFIG | DATA); //0x81000001Paul G. schrieb:> Dann schreibe ich mir halt ein paar "defines" in den Header mit den> häufigsten Register Adressen
Warum erstellst du nicht Funktionen, die das erledigen, was sie sollen.
IC_WRITE ist ja ein Schreib-Befehl und DATA ist ja je Register
unterschiedlich.
Dann könntest du es doch mittels Funktionen abstrahieren um nicht jedes
mal alles zusammenzusetzen.
und wenn du das schreiben und lesen erstmal von den Daten getrennt hast,
dann kannst du dir schon eine struct auf deine "Register" erzeugen.
1
structmy_ic_reg_data
2
{
3
uint32_treg_1;
4
uint32_treg_2;
5
// ...
6
}my_ic_reg_data;
7
8
structmy_ic_reg_dataic_data;
9
10
spi_read_all_register(&ic_data);
11
12
if(ic_data.reg_1==irgendwas)
13
do_something();
Edit:
Ich verstehe deine Herangehensweise nicht so wirklich.
Jörg W. schrieb:> Simon schrieb:>> Würde sowas gehen?>>> static const struct bla>> {>> uint8_t x = 0x01,>> uint8_t y = 0x02,>> uint8_t z = 0x04,>> };>>>>>> uint8_t reg = bla.x | bla.y | bla.z;>>>> Jein.> static const struct> {> uint32_t x, y, z> } bla = {> .x = 0x01,> .y = 0x02,> .z = 0x04,> };> // ...> uint32_t reg = bla.x | bla.y | bla.z;>> Die Definition des struct-Typs musst du schon von der Initialisierung> der (unveränderlichen) Variablen trennen.
Stimmt, das hatte ich mir etwas zu einfach vorgestellt:
Adam P. schrieb:> Ich verstehe deine Herangehensweise nicht so wirklich.
Ich manchmal auch nicht. Ich wollte es mir halt einfacher machen indem
ich nur IC. tippe und die IDE schlägt mir dann ein Dropdown aus
vordefinierten Registern vor, so wie es auch bei der STM32 Hardware
geht... RCC->CR ...
Dass das ganze aber nur bei bei Hardware Adressen geht wusste ich nicht
:)
Paul G. schrieb:> Ich manchmal auch nicht. Ich wollte es mir halt einfacher machen indem> ich nur IC. tippe und die IDE schlägt mir dann ein Dropdown aus> vordefinierten Registern vor, so wie es auch bei der STM32 Hardware> geht... RCC->CR ...>> Dass das ganze aber nur bei bei Hardware Adressen geht wusste ich nicht> :)
Ich glaube soetwas ähliches macht das Microchip Studio auch; da fußt das
Ganze tatsächlich auf einer struct-Struktur.
Paul G. schrieb:> Dass das ganze aber nur bei bei Hardware Adressen geht wusste ich nicht> :)
Jetz weiß ich was du wirklich meinst, jedoch würde ich das eher mit
Funktionen kapseln und nicht so umständlich mit den einzelnen Bits immer
zusammensetzen.
Bei der Hardware ist der struct Pointer auf eine Hardware-Adresse
gelegt,
und hat z.B. mehrere uint32_t Elemente, hier SPI-Abschnitt bei mir:
1
/** \brief Spi hardware registers */
2
typedefstruct{
3
__Ouint32_tSPI_CR;/**< \brief (Spi Offset: 0x00) Control Register */
__Iuint32_tSPI_RDR;/**< \brief (Spi Offset: 0x08) Receive Data Register */
6
__Ouint32_tSPI_TDR;/**< \brief (Spi Offset: 0x0C) Transmit Data Register */
7
//...
8
}Spi;
Das Problem bei dir ist, dass du nur eine 32-Bit Variable hast.
Somit müsstest du deine struct mit Bit-Variablen anlegen, da du nicht
auf mehrere 32-Bit Speicherstellen zugreifen willst, sondern nur auf
eine 32-Bit Variable die du Bit-manipulieren willst.
Simon schrieb:> So hat es übrigens nxp für einen I2C Sensor gelöst:>> https://mcuxpresso.nxp.com/api_doc/comp/101/mma865x_8h_source.html
Ja die haben ja die internen Register abgebildet,
das macht ja auch Sinn.
Aber der TO möchte ja nicht die internen Register abbilden, sondern
sogar schon den Zugriff, lesen oder schreiben, welches Register usw.
Das find ich halt ein wenig "too much".
Deshalb sagte ich ja auch, Register abbilden ist ja OK, den Zugriff
sollte man jedoch durch eindeutige Funktionen lösen.
Adam P. schrieb:> Deshalb sagte ich ja auch, Register abbilden ist ja OK, den Zugriff> sollte man jedoch durch eindeutige Funktionen lösen.
Ja, so mach ich das jetzt. Danke euch.