Forum: Mikrocontroller und Digitale Elektronik 32 Bit in 4 Byte umwandeln und 16 Bit Buffer schreiben


von paule (Gast)


Lesenswert?

Hallo,

habe folgendes Problem, ich habe einen Buffer vom Typ uint_t16.
Über diesen Berechne ich eine CRC Summe:
1
void CRC_append(uint16_t* buf, const int len)
2
{
3
  uint32_t *buf32 = (uint32_t*)buf;
4
  uint8_t *buf8 = (uint8_t*)buf;
5
  uint32_t CRC_sum;
6
  CRC_ResetDR();
7
8
  for(int i=0; i< len>>1 ;i++)                                                  
9
    CRC->DR = buf32[i];
10
11
  buf32[len>>1] = CRC->DR;
12
}

Hier wird zur Zeit noch der uint32_t in den Buffer geschrieben, jedoch 
füllt er dann 2 16 Bit Zellen meines Buffers. Ich möchte aber den 32 Bit 
Wert als 4 Bytes auffassen und in dementsprechend 4 16 Bit Zellen 
schreiben.
Ich hoffe ich konnte das einigermaßen erklären.

zur Zeit:

buf[4] 0x616D
buf[5] 0xF037

soll:

buf[4] 0x0061
buf[5] 0x006D
buf[6] 0x00F0
buf[7] 0x0037

Hintergund ist, dass ich den 16 Bit Buffer brauch um in einer Zelle 1 
Bit für eine 9 Bit Uart setze und das funktioniert mit einem uint_t8 
Buffer so ja nicht.

Gruß
paule

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann musst Du nur die Zuweisung
1
  buf32[len>>1] = CRC->DR;
anpassen.
1
  buf16[0] = CRC->DR & 0xFF;
2
  buf16[1] = (CRC->DR >> 8) & 0xFF;
3
  buf16[2] = (CRC->DR >> 16) & 0xFF;
4
  buf16[3] = (CRC->DR >> 24) & 0xFF;

(Die Reihenfolge musst Du noch Deinen Anforderungen und der "endianness" 
Deines Controllers anpassen)


Wobei ich mich frage, welchen Sinn diese Schleife hat:
1
  for (int i = 0; i < len >> 1; i++)
2
    CRC->DR = buf32[i];

Was soll das werden?

von paule (Gast)


Lesenswert?

Diese Schleife berechnet die CRC über dem Datenpuffer so lange bis das 
Ende des Puffers erreicht ist, da immer nur 32 Bit ins Register rein 
können.

von Peter D. (peda)


Lesenswert?

> for (int i = 0; i < len >> 1; i++)
>     CRC->DR = buf32[i];

Macht nur:
1
   CRC->DR = buf32[len/2-1];


Peter

von Vlad T. (vlad_tepesch)


Lesenswert?

wie soll das denn einen CRC berechnen, hier wird nur was kopiert und am 
Ende der zuletzt kopierte Wert wieder ausgelesen.
(vorrausgesetzt wir reden hier über C und nicht über C++ mit überladenem 
Zuweisungsoperator)

An sich scheint mir das Design von CR ziemlich fragwürdig.
Das scheint mit internen globalen Variablen zu arbeiten - pfui

von Ralf (Gast)


Lesenswert?

Dass die Funktion 'CRC_append()' keine Prüfsumme berechnet, wurde schon 
festgestellt.
Außerdem würde ich mir die Prüfsumme als Funktionsergebnis zurückgeben 
lassen. Die soll ja nach einer Übertragung irgendwo kontrolliert werden. 
Da muss man sie nur wissen und nicht eintragen.
Sollen die 32-Bit-Werte nur für eine Datenübertragung mit Prüfsumme 
aufbereitet werden? Dann setzt man (ich zumindest ;-) ) einfach einen 
8-Bit-Zeiger auf den Puffer und los geht's. Für 'richtige' Berechnungen 
könnte es schwieriger werden (Byte-Order!).

von paule (Gast)


Lesenswert?

Hallo,

wie berechne ich denn dann eine CRC richtig.
Mein STM32 hat eine CRC Einheit, die man mit 32 Bit beschreiben kann und 
mir dann einen 32Bit Wert zurückgibt. Ich sehe jetzt gerade selber das 
ich quasi nur den letzten Wert aus dem CRC Register als Prüfsumme nehme.

Ich will ja am Ende nur eine CRC Summe haben, die aus 32Bit besteht.

Gruß

von Ralf (Gast)


Lesenswert?

paule schrieb:
> wie berechne ich denn dann eine CRC richtig.

So, wie's im Datenblatt steht. Die Prüfsumme berechnet die 'CRC 
calculation unit'. Einfach nur Reset, dann 'CRC_DR' (sollte CRC->DR das 
bedeuten??) mit Daten füttern (32 Bit!!!), wenn fertig: auslesen.

von paule (Gast)


Lesenswert?

Hallo,

ja das soll es bedeuten, ich füttere die Unit per CRC->DR mit 32 Bit und 
bekomme dann die Checksummer zurück. Nur dann ist mir nicht klar, wie 
ich diese verarbeite, wenn ich mehr als 32 Bit Datenn habe?

Wie bilde ich dann die Checksummer über ein Vielfaches von 32 Bit?

von Ralf (Gast)


Lesenswert?

_Datenblatt_:
3.3 CRC functional description
The CRC calculation unit mainly consists of a single 32-bit data 
register, which:
● is used as an input register to enter new data in the CRC calculator 
(when writing into
the register)
● holds the result of the previous CRC calculation (when reading the 
register)
Each write operation into the data register creates a combination of the 
previous CRC value
and the new one (CRC computation is done on the whole 32-bit data word, 
and not byte per
byte).
The write operation is stalled until the end of the CRC computation, 
thus allowing back-toback
write accesses or consecutive write and read accesses.
The CRC calculator can be reset to FFFF FFFFh with the RESET control bit 
in the CRC_CR
register. This operation does not affect the contents of the CRC_IDR 
register.

von paule (Gast)


Lesenswert?

● holds the result of the previous CRC calculation (when reading the
register)
Each write operation into the data register creates a combination of the
previous CRC value
and the new one (CRC computation is done on the whole 32-bit data word,
and not byte per
byte).

das sagt mir doch, das ich meine CRC Berechnung richtig mache, wenn der 
alte wert behalten wird.

von Ralf (Gast)


Lesenswert?

Ja, bloß:
1. mit den falschen Werten, bzw. umständlich
2. was ist CRC->DR?
             -^^
Ich (Achtung: Hobby-Programmierer) würde das so machen (nicht getestet):
1
uint32_t getCRC(uint32_t* buf, uint32_t len)   // 32Bit ist doch sowieso Standard, oder??
2
{
3
 uint32* p=buf;
4
 CRC_CR|=1 << RESET;                           // sollte die Berechnung 'resetten'
5
 while (len--)
6
  CRC_DR=*p++;
7
 return CRC_DR;
8
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Es sieht so aus, als ob der hier verwendete Controller CRC in Hardware 
berechnen kann, und daß die Struktur "CRC" die Register der hierfür 
zuständigen CRC-Berechnungshardware abbildet.

Das Member "DR" ist dann wohl das Datenregister, und damit ist die mir 
merkwürdig erscheinende Schleife
1
  for (int i = 0; i < len >> 1; i++)
2
    CRC->DR = buf32[i];

wohl tatsächlich korrekt, weil CRC->DR in ein Register der Hardware 
schreibt.

Das muss einem aber auch gesagt werden.

von Ralf (Gast)


Lesenswert?

Nur, wenn 'CRC->DR' richtig ist, sollte da in dieser Struktur/ Klasse 
nicht noch fix so eine Funktion zur Berechnung 'dabei' sein?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ralf schrieb:
> Nur, wenn 'CRC->DR' richtig ist, sollte da in dieser Struktur/ Klasse
> nicht noch fix so eine Funktion zur Berechnung 'dabei' sein?

Nein, das macht die Hardware so. Die muss initialisiert werden, dann 
werden nacheinander die Daten 'reingeprügelt und danach kann 
--anscheinend-- aus demselben Register das Ergebnis gelesen werden.

Ob das alles wirklich so funktioniert, ist ohne Studium des zugehörigen 
Datenblatt/Benutzerhandbuch des Controllers natürlich nicht 
herauszufinden.

von Ralf (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Ob das alles wirklich so funktioniert, ist ohne Studium des zugehörigen
> Datenblatt/Benutzerhandbuch des Controllers natürlich nicht
> herauszufinden.

So verstehe ich das auch.
Ich hab' mir das Datenblatt mal durchgelesen, denn mit dem STM32 habe 
ich sonst nichts zu tun. Aber dort heißen die Register CRC_DR, CRC_IDR, 
CRC_CR.
Wenn jetzt über eine Struktur/ Klasse darauf zugegriffen wird, muss doch 
irgendwo eine Bibliothek dazu existieren. Da kann man doch gleich noch 
was dazubasteln.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ralf schrieb:
> Wenn jetzt über eine Struktur/ Klasse darauf zugegriffen wird, muss doch
> irgendwo eine Bibliothek dazu existieren.

Nicht zwingend.

Angenommen, die Register CRC_DR, CRC_IDR,
CRC_CR

lägen direkt hintereinander im Speicher, dann könnte eine entsprechende 
Struktur diese direkt so deklarieren und nutzen:
1
typedef struct 
2
{
3
  uint32_t DR;
4
  uint32_t IDR;
5
  uint32_t CR;
6
} CRC_REGISTER;
7
8
9
CRC_REGISTER* CRC;
10
11
CRC = (CRC_REGISTER *) 0x1234000;  
12
13
CRC->DR = 14;

(Angenommen, die Basisadresse des CRC-Registersatzes läge bei 
0x12340000)

Auf Prozessorarchitekturen mit memory-mapped I/O kann man das so 
machen.

von Ralf (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> dann könnte eine entsprechende
> Struktur diese direkt so deklarieren und nutzen

Ja, könnnnte. Wer weiß aber, was später mal so alles geändert wird. 
Diese Zugriffsidee gibt's ja auch für die AVR-Register PORTx, PINx, DDRx 
...

Ich dachte eher an eine ordentliche Klasse, die gleich so eine 
Berechnungsfunktion zur Verfügung stellt (Wenn man schon die Register in 
einer Struktur 'versteckt').

von Vlad T. (vlad_tepesch)


Lesenswert?

Ralf schrieb:
> Ja, könnnnte. Wer weiß aber, was später mal so alles geändert wird.
> Diese Zugriffsidee gibt's ja auch für die AVR-Register PORTx, PINx, DDRx
> ...

diese Idee gefällt mir.
Ich kannte bisher nur die Variante mit Makros
GETDDR(PORTA)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ralf schrieb:
> Ich dachte eher an eine ordentliche Klasse, die gleich so eine
> Berechnungsfunktion zur Verfügung stellt

C kennt keine Klassen.

von Ralf (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> C kennt keine Klassen.

Stimmt. Ich dachte auch, für den STM32 gibt's eine etwas 'gehobenere' 
Programmierumgebeung...

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.