Forum: Mikrocontroller und Digitale Elektronik C > Anzahl an Words von übergebenen Bytes berechnen?


von Jan H. (janiiix3)


Lesenswert?

Nabend,

kleine Verständnisfrage an euch:
Was genau soll diese Berechnung machen?
Soll sie ermitteln wie viel Words aus den übergebenen Bytes gebildet 
werden können?
1
  uint32_t words = (bytes + 3) / 4;  //16 max

1
static void __spiTransferBytes(spi_t *spi, const uint8_t *data, uint8_t *out, uint32_t bytes) {
2
  if (!spi) {
3
    return;
4
  }
5
  uint32_t i;
6
7
  if (bytes > 64) {
8
    bytes = 64;
9
  }
10
11
  uint32_t words = (bytes + 3) / 4;  //16 max
12
13
  uint32_t wordsBuf[16] = {
14
    0,
15
  };
16
  uint8_t *bytesBuf = (uint8_t *)wordsBuf;
17
18
  if (data) {
19
    memcpy(bytesBuf, data, bytes);  //copy data to buffer
20
  } else {
21
    memset(bytesBuf, 0xFF, bytes);
22
  }
23
24
  spi->dev->mosi_dlen.usr_mosi_dbitlen = ((bytes * 8) - 1);
25
  spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1);
26
27
  for (i = 0; i < words; i++) {
28
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
29
    spi->dev->data_buf[i].val = wordsBuf[i];  //copy buffer to spi fifo
30
#else
31
    spi->dev->data_buf[i] = wordsBuf[i];  //copy buffer to spi fifo
32
#endif
33
  }
34
35
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2)
36
  spi->dev->cmd.update = 1;
37
  while (spi->dev->cmd.update);
38
#endif
39
  spi->dev->cmd.usr = 1;
40
41
  while (spi->dev->cmd.usr);
42
43
  if (out) {
44
    for (i = 0; i < words; i++) {
45
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
46
      wordsBuf[i] = spi->dev->data_buf[i].val;  //copy spi fifo to buffer
47
#else
48
      wordsBuf[i] = spi->dev->data_buf[i];  //copy spi fifo to buffer
49
#endif
50
    }
51
    memcpy(out, bytesBuf, bytes);  //copy buffer to output
52
  }
53
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan H. schrieb:
> uint32_t words = (bytes + 3) / 4;  //16 max
>
> Soll sie ermitteln wie viel Words aus den übergebenen Bytes gebildet
> werden können?
Ja, sie ermittelt, wieviele 32-Bit-Worte für eine bestimmte Anzahl Bytes 
nötig sind. Spiel das doch einfach mal mit ein paar Werten für bytes 
(z.B. von 0..12) durch und denk daran: bei der Integerdivision /4 wird 
einfach der Rest abgeschnitten.
1
bytes   |   words
2
--------+---------
3
  0     |    0
4
  1     |    1
5
  2     |    1
6
  3     |    1
7
  4     |    1
8
  5     |    2
9
  6     |    2
10
  :     |    :

: Bearbeitet durch Moderator
von Jan H. (janiiix3)


Lesenswert?

Lothar M. schrieb:
> Jan H. schrieb:
>> uint32_t words = (bytes + 3) / 4;  //16 max
>> Soll sie ermitteln wie viel Words aus den übergebenen Bytes gebildet
>> werden können?
>
> Ja, sie ermittelt, wieviele 32-Bitworte für eine bestimmte Anzahl Bytes
> nötig sind. Spiel das doch einfach mal mit ein paar Werten für bytes
> (z.B. von 0..12) durch und denk daran: bei der Integerdivision /4 wird
> einfach der Rest abgeschnitten.

Habe ich schon gemacht jedoch bin ich bei einer ungeraden Zahl an Bytes 
stutzig geworden.
Wenn ich jetzt z.B 3 Bytes übertragen möchte, errechnet die Funktion ja 
nur ein Word was ja auch richtig ist, in der for Schleife wird dann das 
dritte Byte nicht mehr beachtet oder habe ich da einen Denkfehler?

von Achim M. (minifloat)


Lesenswert?

Jan H. schrieb:
> in der for Schleife wird dann das dritte Byte nicht mehr beachtet oder
> habe ich da einen Denkfehler?

Im Fall von words == 3 zählt die for-Schleife 0,1,2 und das sind 3 
Schleifendurchläufe.

Informatiker am Bahnhof: 0,1,2 ... Mist, wo ist mein dritter Koffer!?

mfg mf

Beitrag #7796351 wurde vom Autor gelöscht.
von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Ich habe das eben noch mal mit dem "onlinegdb" durchgespielt.
Wenn ich der Funktion als bsp.
1
        uint8_t buff[] = {1,2,3,4};
2
        spi_write_bytes( buff, 4 );

übergebe, ist das gebildete Word "67305985 Dec."
Das währe dann in Bytes "0x04, 0x03, 0x02, 0x01 Hex."

Die Funktion zum schreiben der Daten auf dem SPI Bus ist auf MSB_First 
eingestellt. Das würde bedeuten das zuerst die "0x04" dann die "0x03" 
usw. gesendet werden müsste, richtig?

Jedoch ist komplett anders (siehe Foto)..
So wie ich das jetzt verstanden habe, passen meine zu sendenen Bytes in 
ein 32 Bit Word. Da das SPI Senderegister 32 Bit breit ist, sollte es 
eigentlich der o.g. Reihenfolge gesendet werden oder=

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Jan H. schrieb:
> Die Funktion zum schreiben der Daten auf dem SPI Bus ist auf MSB_First
> eingestellt.

Richtig, sie sendet das höherwertige Bit der übertragenen Bytes 
zuerst.

Jan H. schrieb:
> Das würde bedeuten das zuerst die "0x04" dann die "0x03"
> usw. gesendet werden müsste, richtig?

Nö, um das Umsortieren von Bytes müsstest Du Dich schon selbst kümmern, 
das hat mit SPI nichts mehr zu tun.

von Jan H. (janiiix3)


Lesenswert?

Harald K. schrieb:
> Jan H. schrieb:
>> Die Funktion zum schreiben der Daten auf dem SPI Bus ist auf MSB_First
>> eingestellt.
>
> Richtig, sie sendet das höherwertige Bit der übertragenen Bytes
> zuerst.
>
> Jan H. schrieb:
>> Das würde bedeuten das zuerst die "0x04" dann die "0x03"
>> usw. gesendet werden müsste, richtig?
>
> Nö, um das Umsortieren von Bytes müsstest Du Dich schon selbst kümmern,
> das hat mit SPI nichts mehr zu tun.

Wie "Nö"? Wenn meine 0x04 das MSB von uint32_t bildet, wird das doch 
zuerst gesendet?

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Habe gerade versucht einen uint32_t zu senden mit 0x000001.
Laut LA kommt 0x000100 an.
Scheint also irgendwas mit dem Registerzugriff nicht zu passen..
1
    while (1)
2
    {    
3
        //uint8_t buff[] = {1,2,3,4};
4
        //spi_write_bytes( buff, 4 );
5
6
          spi_write_dword( 0x000001 );
7
    }
1
void spi_write_dword( uint32_t _data )
2
{
3
  REG_WRITE( SPI_MS_DLEN_REG, 32 -1 );
4
  
5
  //#define REG_WRITE(_r, _b)      (*(volatile uint32_t*)(_r)) = (_b) 
6
  //##define SPI_Wn_REG(n)         SPI2_REG((0x98+(n*4))) 
7
  REG_WRITE( SPI_Wn_REG(0), _data );
8
9
  REG_SET_BIT( SPI_CMD_REG, SPI_UPDATE_bm );
10
  while ( REG_READ( SPI_CMD_REG ) & SPI_UPDATE_bm ){};
11
12
  REG_SET_BIT( SPI_CMD_REG, SPI_USR_bm );
13
  while ( REG_READ( SPI_CMD_REG ) & SPI_USR_bm ){};    
14
}

: Bearbeitet durch User
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.