STM32 UART TMC2209 Bit-banging

OP #7484493
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
}
OP #7484494
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
    }
OP #7484538
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. :/

#7484585
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.

OP #7484587
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...

OP #7484588
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...

#7484591
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.

OP #7484593
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.

OP #7484595
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

OP #7484605
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

OP #7484630
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...

OP #7484635
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??

#7484646
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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren