CAN-Bus Sender mit STM32CubeIDE für Blue Pill erstellen

OP #6653339
Lesenswert?

Ich mich kürzlich in das Thema "CAN-Botschaften mit Blue Pill senden" 
einarbeiten und habe festgestellt das sich in der HAL um 2018 rum wohl 
einiges geändert hat und praktisch alles was man so an Beispielen im 
Internet findet nicht mehr läuft. Z.B. fehlt die Typedef 
"CanTxMsgTypeDef" und auch das CAN-Handle hat andere Attribute.

Hat jemand der hier anwesenden vielleicht mal ein kleines Beispiel zur 
Hand wie man das mit der aktuellen HAL macht? Also einfach nur eine 
simple STD-ID mit DLC 8 alle 100 ms senden.
OP #6654940
Lesenswert?

Ich habe mich nun durchgewurschtelt. Da ist einiges anders seit dem 
HAL-API change in 2018...

Erste Herausforderung war die richtigen Timing-Parameter zu ermitteln. 
Folgendes habe ich nun für 125 kbit/s (MS-CAN) errechnet:
1
hcan.Init.Prescaler = 4;
2
hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
3
hcan.Init.TimeSeg2 = CAN_BS2_2TQ;

Zum senden dann:
1
CAN_TxHeaderTypeDef   TxHeader;
2
uint8_t               TxData[8];
3
uint32_t              TxMailbox;
4

5
TxHeader.ExtId = 0x01;
6
TxHeader.RTR = CAN_RTR_DATA;
7
TxHeader.IDE = CAN_ID_STD;
8
TxHeader.DLC = 8;
9
TxHeader.TransmitGlobalTime = DISABLE;
10
TxHeader.StdId = 0x200;
11

12
TxData[0] = 0x00;
13
TxData[1] = 0x11;
14
TxData[2] = 0x22;
15
TxData[3] = 0x33;
16
TxData[4] = 0x44;
17
TxData[5] = 0x55;
18
TxData[6] = 0x66;
19
TxData[7] = 0x77;
20

21
if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, TxData, &TxMailbox) != HAL_OK) {
22
  Error_Handler();
23
}

Man sendet also nicht synchron sondern schiebt das Datagramm in eine 
Ausgabewarteschlange (Mailbox). Der Rückgabewert der HAL-Funktion 
liefert einen Fehler wenn diese z.B. voll ist oder es Busprobleme gibt.

Was mir jetzt als nächstes fehlt ist eine Funktion um ein Datagramm 
regelmäßig zu senden. Ich stelle mir vor eine Subroutine zu erstellen 
welche die Daten einer global bekannten Struktur wie TxData regelmäßig 
sendet, z.B. alle 200 ms.

Für sowas sollten Timer gut sein. Also ein Timer welcher alle 200 ms 
einen Interrupt auslöst und meine o.g. Routine als ISR ausführt. Würde 
man das so machen?
OP #6655073
Lesenswert?

Da ich mehrere Botschaften habe welche periodisch gesendet werden 
sollen, aber mit unterschiedlichen IDs in unterschiedlichen Intervallen 
benötige ich noch etwas "drumherum".

Ich denke ich mache ein Struct welches die ID, die Daten und das 
Sendeintervall in Millisekunden enthält. Davon mache ich dann ein 
volatile Array welches sowohl in meiner Serverloop als auch im ISR 
verfügbar ist. In der Serverloop ändere ich die Datenbytes wenn das 
notwendig ist.

In der ISR erhöhe ich einen ebenfalls im Struct liegenden Zähler welcher 
bei jedem ISR-Aufruf (welcher dann z.B. alle 10 Millisekunde erfolgt) 
erhöht wird und sobald diese den Wert des Sendeintervalls erreicht hat, 
schicke ich die Botschaft in die TX-Mailbox und setze den Zähler wieder 
auf 0.

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