Forum: Mikrocontroller und Digitale Elektronik STM32 UART TMC2209 Bit-banging


von Brom B. (schrori)


Lesenswert?

Hallo zusammen,

ich versuche einen TMC2209 über einen STM32 mit UART anzusteuern. leider 
will das ganze nicht so wirklich.

Zunächst habe ich versucht über die HAL Bibliothek zu gehen aber hier 
bekomme ich nichtmal einen Output..

Nun auf dem Weg der Fehlersuche habe ich Timer Interrupts erstellt, eine 
Baudrate von 10000 eingestellt und möchte das ding erstmal mit 
Bitbanging zum drehen bringen :) Hier kommt am Oszi zumindest schonmal 
was raus (Habe Uart deaktiviert GPIO gesetzt etc.)

Laut Oszi kommt alles an. Nur der TMC macht nichts... setze ich die bits 
in der falschen reihenfolge??

Ich sende die Bytes von Data64[0] nach 8 und jeweils von links nach 
rechts also im grunde wie in dem Kommentar. nach jedem Byte ein stopbit 
und ein Start bit als 10... Kann mir jemand helfen? :(

LG
1
uint8_t swuart_calcCRC (volatile uint8_t * datagram, uint8_t datagramLength) {
2
  int i, j;
3
  volatile uint8_t *crc = datagram + (datagramLength - 1);   // CRC located in last byte of message
4
  uint8_t currentByte;
5
  *crc = 0;
6
  for (i = 0; i < (datagramLength - 1); i++) {      // Execute for all bytes of a message
7
      currentByte = datagram[i];                    // Retrieve a byte to be sent from Array
8
      for (j = 0; j < 8; j++) {
9
          if ((*crc >> 7) ^ (currentByte & 0x01)) { // update CRC based result of XOR operation
10
              *crc = (*crc << 1) ^ 0x07;
11
          }
12
          else {
13
              *crc = (*crc << 1);
14
          }
15
          currentByte = currentByte >> 1;
16
      }         // for CRC bit
17
  }             // for message byte
18
  return datagram[datagramLength - 1];
19
}
20
// <= CRC wrapper
21
22
    //10.10100000.10.01000000.10...
23
24
void tmc2209_calcInt64(uint8_t address, int32_t value)
25
{
26
  //static uint8_t data[8];
27
28
  data64[0] = 0b00000101;              //00000101
29
  data64[1] = 0b00000010;              //00000010
30
  data64[2] = address | 0x80;      //10100010 0x22 + write
31
  data64[3] = (value >> 24) & 0xFF;
32
  data64[4] = (value >> 16) & 0xFF;
33
  data64[5] = (value >> 8 ) & 0xFF;
34
  data64[6] = (value      ) & 0xFF;
35
  data64[7] = swuart_calcCRC(data64, 8);
36
}

von Brom B. (schrori)


Lesenswert?

1
else if (dataswitch == 2) {
2
      //HAL_GPIO_WritePin(OUT_LED3_GPIO_Port, OUT_LED3_Pin,1);
3
4
      //HAL_GPIO_WritePin(TMC2209_PDN_Uart_SingleWire_GPIO_Port, TMC2209_PDN_Uart_SingleWire_Pin, (data32 >> bitcount) & 1);
5
      if (bitcount == 9) {
6
        HAL_GPIO_WritePin(TMC2209_PDN_Uart_SingleWire_GPIO_Port, TMC2209_PDN_Uart_SingleWire_Pin, 1);
7
        //HAL_GPIO_WritePin(OUT_LED1_GPIO_Port, OUT_LED1_Pin, 1);
8
         bitcount = 0;
9
          bytecount ++;
10
          if (bytecount == 0) {
11
            bytecount = 0;
12
13
            dataswitch = 0;
14
          }
15
         //HAL_GPIO_WritePin(OUT_LED3_GPIO_Port, OUT_LED3_Pin,0);
16
         return;
17
      }
18
19
20
21
      if (bitcount == 0) {
22
        HAL_GPIO_WritePin(TMC2209_PDN_Uart_SingleWire_GPIO_Port, TMC2209_PDN_Uart_SingleWire_Pin, 0);
23
          bitcount++;
24
          return;
25
      }
26
27
28
      HAL_GPIO_WritePin(TMC2209_PDN_Uart_SingleWire_GPIO_Port, TMC2209_PDN_Uart_SingleWire_Pin, (data64[(bytecount)] >> ((bitcount -1))) & 1);
29
      bitcount ++;
30
       return;
31
    }

von Harry L. (mysth)


Lesenswert?

So geht UART mit HAL und Interrupts:
Beitrag "[STM32/HAL] simples U(S)ART-Library"

von Brom B. (schrori)


Lesenswert?

Hallo Harry Super vielen Dank werde ich mir auf jedenfall zu genüge 
führen :)

Aber in welcher Reihenfolge ich die Bits und Bytes senden muss weiß ich 
leider noch nicht ^^

Am verwirrensten finde ich das im Datenblatt und in der API (welche 
nicht vollständig ist da externe Funktionen schlicht deklariert aber 
nicht definiert sind) Wiedersprüche sind. :/

von Brom B. (schrori)


Lesenswert?

Harry L. schrieb:
> So geht UART mit HAL und Interrupts:
> Beitrag "[STM32/HAL] simples U(S)ART-Library"

Ausserdem muss ich das ganze im Halfduplex machen weil Singlewire :/ Da 
die HAL hier laut mehreren nutzern Probleme macht bin ich überhaupt erst 
auf das Manuelle gegangen.

LG

von Harry L. (mysth)


Lesenswert?

Brom B. schrieb:
> Ausserdem muss ich das ganze im Halfduplex machen weil Singlewire

Weil das Ding nur Daten empfängt aber nicht sendet.
Das geht also mit jeder 0815-Standard-Schnittstelle ohne weitere 
Maßnahmen.
Ausserdem ist die serielle Schnittstelle optional.
Die brauchst du zum Betrieb üblicherweise gar nicht.
Die Ansteuerung geschieht über die Step- und Direction-Eingänge.

von Brom B. (schrori)


Lesenswert?

Harry L. schrieb:
> Brom B. schrieb:
>> Ausserdem muss ich das ganze im Halfduplex machen weil Singlewire
>
> Weil das Ding nur Daten empfängt aber nicht sendet.
> Das geht also mit jeder 0815-Standard-Schnittstelle ohne weitere
> Maßnahmen.
> Ausserdem ist die serielle Schnittstelle optional.
> Die brauchst du zum Betrieb üblicherweise gar nicht.
> Die Ansteuerung geschieht über die Step- und Direction-Eingänge.

Da liegst du leider falsch.
Ich kann und möchte aus auslesen über UART. Er hat leider nur einen 
Anschluss der auf Halb Duplex geht. Man sendet 32bit also wie beim write 
und erhält anschließend eine Antwort.

Wie die Ansteuerung üblicherweise funktioniert weiß ich, dennoch möchte 
ich die erweiterten nutzen (Strom einstellen, Coolstep, Stallguard usw.)

Ohne UART läuft er ja. aber das ist nicht Ansatzweise das Ziel...

von Brom B. (schrori)


Lesenswert?

Harry L. schrieb:
> Brom B. schrieb:
>> Ausserdem muss ich das ganze im Halfduplex machen weil Singlewire
>
> Weil das Ding nur Daten empfängt aber nicht sendet.
> Das geht also mit jeder 0815-Standard-Schnittstelle ohne weitere
> Maßnahmen.
> Ausserdem ist die serielle Schnittstelle optional.
> Die brauchst du zum Betrieb üblicherweise gar nicht.
> Die Ansteuerung geschieht über die Step- und Direction-Eingänge.

Und außerdem ist mir beim Bitbanging die Schnittstelle schnurz mit dem 
oszi kommt ja alles an. Nur reagiert er nicht und DAS ist mein Problem.

Nicht das UART und auch nicht die Schnittstelle...

von Brom B. (schrori)


Lesenswert?

Brom B. schrieb:
> Laut Oszi kommt alles an. Nur der TMC macht nichts... setze ich die bits
> in der falschen reihenfolge??

Guggst du Fragge :)

von Harry L. (mysth)


Lesenswert?

Brom B. schrieb:
> Da liegst du leider falsch.

Ja, hast recht.Man kann auch Parameter lesen.
Aber auch das ist ja kein Hexenwerk.

In Kapitel 4 steht:
1
The UART single wire interface allows control of the TMC2209 with any microcontroller UART. It shares transmit and receive line like an RS485 based interface.
Das kann man bei den meisten MCUs in CubeMX passend konfigurieren.

Und Beispiel-Code für die CRC-Berechnung ist ja auch vorhanden.

von Brom B. (schrori)


Lesenswert?

Harry L. schrieb:
> Brom B. schrieb:
>> Da liegst du leider falsch.
>
> Ja, hast recht.Man kann auch Parameter lesen.
> Aber auch das ist ja kein Hexenwerk.
>
> In Kapitel 4 steht:
>
1
> The UART single wire interface allows control of the TMC2209 with any 
2
> microcontroller UART. It shares transmit and receive line like an RS485 
3
> based interface.
4
>
> Das kann man bei den meisten MCUs in CubeMX passend konfigurieren.
>
> Und Beispiel-Code für die CRC-Berechnung ist ja auch vorhanden.

Richtig habe ich ja alles gemacht und auch gepostet nur tut sich nichts. 
:/
Also am Pin kommt alles an (oszi gemessen). Aber offensichtlich die 
falsche Reihenfolge baud 10000 sollte auch kein Problem sein.

von Brom B. (schrori)


Lesenswert?

Brom B. schrieb:
> Harry L. schrieb:
>> Brom B. schrieb:
>>> Da liegst du leider falsch.
>>
>> Ja, hast recht.Man kann auch Parameter lesen.
>> Aber auch das ist ja kein Hexenwerk.
>> In Kapitel 4 steht:
>
>> The UART single wire interface allows control of the TMC2209 with any
>
>> microcontroller UART. It shares transmit and receive line like an RS485
>
>> based interface.
.

Bzw. Durch die falsche Reihenfolge kommt auch eine falsche CRC raus 
daran hänge ich vermutlich

von Brom B. (schrori)


Lesenswert?

Fällt dir aufgrund meines Codes und des Datenblattes etwas auf das 
falsch ist?

Timer Interrupt ist bei 64MhZ Prescale 4 Periode 1599 also 10k Baud. 
9sind laut Datenblatt die mindestenpfehlung

von Harry L. (mysth)


Lesenswert?

Brom B. schrieb:
> baud 10000 sollte auch kein Problem sein.
Ich wäre mir nicht so sicher, daß das Ding beliebige Baudraten kann.
Nimm besser ein Vielfaches von 9600 Baud (9600 werden als niedigste 
Baudrate explizit erwähnt.)
Also 9600, 19200 oder 38400 usw.

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Harry L. schrieb:
> Brom B. schrieb:
>> baud 10000 sollte auch kein Problem sein.
> Ich wäre mir nicht so sicher, daß das Ding beliebige Baudraten kann.
> Nimm besser ein Vielfaches von 9600 Baud (9600 werden als niedigste
> Baudrate explizit erwähnt.)
> Also 9600, 19200 oder 38400 usw.

OK nehme ich mit auf
Dachte mir halt 10 ist ein glatter Teiler zu beiden Taktraten (12mhz 
64mhz)

Könntest du bitte trotzdem mal drüber Gehen? Vielleicht ist es ja was 
ganz banales :)

Lg

von C-hater (c-hater)


Lesenswert?

Brom B. schrieb:

> werde ich mir auf jedenfall zu genüge
> führen :)
>
> Aber in welcher Reihenfolge ich die Bits und Bytes senden muss weiß ich
> leider noch nicht ^^

Wer's noch nicht bemerkt hat: Das ist ein Troll.

von Brom B. (schrori)


Lesenswert?

C-hater schrieb:
> Brom B. schrieb:
>
>> werde ich mir auf jedenfall zu genüge
>> führen :)
>>
>> Aber in welcher Reihenfolge ich die Bits und Bytes senden muss weiß ich
>> leider noch nicht ^^
>
> Wer's noch nicht bemerkt hat: Das ist ein Troll.

Nein ich bin kein Troll!

Wenn du so super schlau hilf doch lieber! -.-

von Harry L. (mysth)


Lesenswert?

Halte dich einfach genau an das Frameformat wie in 4.1.1 und 4.1.2 
beschrieben!
Jeder Frame besteht aus 8 Byte, im letzten Byte befindet sich die CRC 
und die CRC wird über die ersten 7 Byte gebildet.

Dann wird das auch funktionieren.

von Brom B. (schrori)


Lesenswert?

C-hater schrieb:
> Brom B. schrieb:
>
>> werde ich mir auf jedenfall zu genüge
>> führen :)
>>
>> Aber in welcher Reihenfolge ich die Bits und Bytes senden muss weiß ich
>> leider noch nicht ^^
>
> Wer's noch nicht bemerkt hat: Das ist ein Troll.

In der API von AD fehlen die Funktionen die das Array zum senden und 
empfangen, sowie das senden selbst übernehmen.

Die ersten Bits werden scheinbar von Rechts nach links?? Eingelesen die 
Value Bits aber 1:1 übernommen.

Außerdem wird eine eigene CRC Funktion benutzt (tmc2209_crc8) die aber 
ebenfalls nicht auffindbar und damit leider auch nicht nutzbar ist...

von Brom B. (schrori)


Lesenswert?

Harry L. schrieb:
> Halte dich einfach genau an das Frameformat wie in 4.1.1 und 4.1.2
> beschrieben!
> Jeder Frame besteht aus 8 Byte, im letzten Byte befindet sich die CRC
> und die CRC wird über die ersten 7 Byte gebildet.
>
> Dann wird das auch funktionieren.

Ja das habe ich vor. Und Dachte ich auch zu tun.

Nur eben ohne Erfolg...

Es heißt ja die Bytes werden LSB nach MSB gesendet aber das höchste Byte 
zuerst.

Im Datenblatt fängt er aber links bei 0 an...

Also das ich mit dem linken Bit starte ist klar daran erkennt er ja die 
baudrate.

Aber muss ich dann von vorne oder von hinten Starten also 00000101 oder 
10100000 und ist das bei den Values das gleiche oder umgekehrt?

Denn in der API ist es wie gesagt verdreht...

Ist es dem CRC egal was wo steht??

von Harry L. (mysth)


Lesenswert?

Brom B. schrieb:
> Aber muss ich dann von vorne oder von hinten Starten also 00000101 oder
> 10100000 und ist das bei den Values das gleiche oder umgekehrt?

Wenn du die UART-Funktionen nutzt, passt das.
Bei der eigentlichen Payload (die 4 Bytes vor der CRC) wird das 
niederwertigste Byte zuerst gesendet, aber das musst du bei der 
CRC-Berechnung nicht berücksichtigen.
Das entspricht auch genau der Speicherreihenfolge eines int beim STM32.

Die CRC-Berechnung wird immer von Links nach Rechts über die ersten 7 
Bytes durchgeführt.
Die Reihenfolge ist dabei natürlich nicht egal.

Für die CRC-Berechnung ist der Beispielcode ja dabei:
1
// C-CODE EXAMPLE FOR CRC CALCULATION
2
void swuart_calcCRC(UCHAR* datagram, UCHAR datagramLength)
3
{
4
 int i,j;
5
 UCHAR* crc = datagram + (datagramLength-1); // CRC located in last byte of message
6
 UCHAR currentByte;
7
 *crc = 0;
8
 for (i=0; i<(datagramLength-1); i++) { // Execute for all bytes of a message
9
 currentByte = datagram[i]; // Retrieve a byte to be sent from Array
10
 for (j=0; j<8; j++) {
11
 if ((*crc >> 7) ^ (currentByte&0x01)) // update CRC based result of XOR operation
12
 {
13
 *crc = (*crc << 1) ^ 0x07;
14
 }
15
 else
16
 {
17
 *crc = (*crc << 1);
18
 }
19
 currentByte = currentByte >> 1;
20
 } // for CRC bit
21
 } // for message byte
22
}

datagram ist dabei ein Pointer auf deine empfangenen Bytes und 
datagramLength ist natürlich 8. (gesamtes Paket inkl. CRC)

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Okay verstehe und das Niederwertigste ist bei 0b0110101X das X ist also 
immer Bit 0 eines jeden Byte?

Das heißt ich sende stets von rechts nach links (binär gedacht) richtig?

Nur im Datenblatt steht alles andersrum drin??

von Brom B. (schrori)


Lesenswert?

Ich meine die richtige Reihenfolge wäre dann ja... Moment genau wie im 
Datenblatt.
Aber die Values muss ich von rechts beginnend senden...

Ich schlafe mal ne Nacht drüber und melde mich morgen nochmal danke 
schonmal:)

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.