Forum: Mikrocontroller und Digitale Elektronik CAN auf STM32F4


von RainerZufall24 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich möchte die CAN-Schnittstelle an meinem STM32F4Discovery nutzen.
Die Hardware sollte soweit passen...
Ich habe an einem STM32F4Discovery PD0/PD1 einen MCP2662 angeschlossen. 
Wenn ich ein funktionierenden Sensor an den Bus (H/L) anstecke, sehe ich 
mit dem Oszi wie zyklische Daten über die CANRx-Leitung zum  STM 
gesendet werden.
Ebenso kann ich etwas auf der CanTx-Leitung sehen wenn ich eine 
Nachricht sende.

Irgendwie klappt es aber aus meiner Sicht mit dem "lesen" nicht. Sprich, 
dass die Daten in mein uint8_t Array geschrieben werden.
Ich habe in dem Programm nichts weiter als eine LED-welche mit 0,5Hz 
getoggelt wird.

Das erste Ziel wäre da eine Nachricht zu senden und im LoopBack wieder 
zu lesen.

Es geht jedenfalls nicht so ...

Die Funktion "HAL_CAN_GetRxMessage" hat den Rückgabewert 1.
HAL_CAN_GetError gibt "2097152"
HAL_CAN_GetRxFifoFillLevel gibt den Wert 0 zurück.

Ich merke zunehmend wie meine Suche mehr  einem "stochern" ähnelt.
Die Änderungen in der HAL-Lib verwirren mich zusätzlich...
Es gibt ja schöne Beispiele im Netz wo die Rx/Tx-Header  mit im 
CAN-Handle untergebracht sind (hcan.pTxMsg = &TxMessage;hcan.pRxMsg = 
&RxMessage;). Das gibts aber offensichtlich in der verwendeten 
HAL-Version nicht mehr...

Ein bisschen hab die die Vermutung das ich mit den Pointern was falsch 
mache. Könnte mir bitte jemand einen Tipp geben?


Hier der Quellcode auszugsweise:
1
int main(void)
2
{  
3
  HAL_Init();
4
  SystemClock_Config();
5
  MX_GPIO_Init()
6
  __HAL_RCC_CAN1_CLK_ENABLE();
7
  __GPIOD_CLK_ENABLE();
8
  GPIOConf();
9
  uint8_t buffer[8];
10
  uint8_t txData[8];
11
  txData[0] = 50;
12
  txData[1] = 51;
13
  txData[2] = 52;
14
  txData[3] = 53;
15
  txData[4] = 54;
16
  txData[5] = 55;
17
  txData[6] = 56;
18
  txData[7] = 57;
19
  
20
  CAN_RxHeaderTypeDef *RxHead;
21
  CAN_TxHeaderTypeDef *TxHead;
22
  uint32_t *TxMailbox;
23
  HAL_CAN_Start(&hcan1);
24
  
25
//HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo,    //CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
26
  
27
HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0, &RxHead, buffer);
28
29
while(1){
30
HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_13);
31
HAL_Delay(500);
32
33
//HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef //*pHeader, uint8_t aData[], uint32_t *pTxMailbox)
34
HAL_CAN_AddTxMessage(&hcan1,&TxHead,txData,&TxMailbox);
35
36
}
37
}

von Programmierer (Gast)


Lesenswert?

Wo ist die Initialisierung des CAN und vor allem die der Filter-Banks? 
Funktionieren denn die Beispiele von ST?

von RainerZufall24 (Gast)


Lesenswert?

Die Funktion ist im Anhang (zusatz.txt).
Ich sehe gerade das ich vergessen hab die Zeile zu kopieren ...
Aufruf ist hier unter GPIOConmf();:
1
  GPIOConf();
2
  MX_CAN1_Init();

Ein passenden Beispiel habe ich leider nicht gefunden.
Das sind immer nur welche mit älteren HAL-Ständen.

von Programmierer (Gast)


Lesenswert?

Der Filter ist deaktiviert. So kommt nichts durch.

sFilterConfig.FilterActivation = DISABLE;

von RainerZufall24 (Gast)


Lesenswert?

OK.
Ich hatte irgendwo gelesen, dass dann alle Nachrichten durchkommen (bei 
DISABLE).

Dann müsste ich auch die FilterIdHigh & FilterIdLow richtig 
konfigurieren.

Stimmt es dann, dass alle Nachrichten passieren wenn beide auf 0x0000 
stehen?

von Programmierer (Gast)


Lesenswert?

RainerZufall24 schrieb:
> Ich hatte irgendwo gelesen, dass dann alle Nachrichten durchkommen (bei
> DISABLE).

Normalerweise kommt gar nichts durch, und du musst Filter Banks so 
einstellen und aktivieren, dass das Gewünschte durch kommt.

RainerZufall24 schrieb:
> Stimmt es dann, dass alle Nachrichten passieren wenn beide auf 0x0000
> stehen?

Ich meine schon. Lies das nochmal im Reference Manual durch und schau 
dir den Quellcode der HAL an, um festzustellen, was du da hinschreiben 
musst, damit das richtige in der Hardware ankommt. Die HAL ist an der 
Stelle etwas komisch, man muss das quasi rückwärts machen. Alternativ 
die HAL einfach gar nicht benutzen, dann entfällt dieser Schritt...

von RainerZufall24 (Gast)


Lesenswert?

Ansich ist die HAL schon gut zu verwenden ...
Ohne die wird's vermutlich nicht viel einfacher.

Wo finde ich den eine Erläuterung zu den HAL-Error?

von Programmierer (Gast)


Lesenswert?

RainerZufall24 schrieb:
> Ansich ist die HAL schon gut zu verwenden ...
> Ohne die wird's vermutlich nicht viel einfacher.
>
> Wo finde ich den eine Erläuterung zu den HAL-Error?

Im HAL-Sourcecode. Den muss man mangels vernünftiger Doku immer parat 
haben...

von RainerZufall24 (Gast)


Lesenswert?

Ja, habs nun auch gefunden.
Der Fehler ist 0x 200000 -> 200000   -> HAL_CAN_ERROR_PARAM

Dazu gab es schon Mal einen Beitrag: 
Beitrag "STM32F103 STM32CubeF1 Version 1.7 Problem mit HAL_CAN_AddTxMessage()"

Leider aber noch keine Erfolgsmeldung.


Was kann man nun tun? -> Vermutlich doch ohne HAL probieren.

von Louis (Gast)


Lesenswert?

Hallo,
ich habe noch nie CAN mit der HAL verwendet, aber folgende Dinge fallen 
mir schnell mal auf:
* Beim Senden musst Du irgendwo festlegen welcher Frametyp (Remote, 
Data), welche ID (SID oder EID) und wieviele Datenbytes Du senden 
möchtest.
Sehe ich in Deinem Code nirgends.
* Soweit ich Deine Schleife verstehe prüfst Du nur einmalig, vor wem 
while() ob ein Frame empfangen wurde, danach nie wieder

lg
Louis

von RainerZufall24 (Gast)


Lesenswert?

Mist. Wieder nicht genug kopiert.
Zum Hintergrund: Ich habe das letzt Mal eine kleine Rüge bekommen weil 
der zitierte Code zu lang war. Daher dacht ich mir, ich kürze ein und 
hänge die wichtigen Funktionen an.

Hier die fehlenden Zeilen:
1
 TxHead->StdId  = 0x100;
2
  TxHead->ExtId  = 0x01;
3
  TxHead->RTR = CAN_RTR_DATA;
4
  TxHead->IDE = CAN_ID_STD;
5
  TxHead->DLC = 8;


Das Abfragen innerhalb der while() hatte ich auch schon versucht...
Klappte auch nicht.

Gibt es irgendwo ein Programmbeispiel für CAN ohne die HAL?

Viele Dank für die Hilfe

von Programmierer (Gast)


Lesenswert?

RainerZufall24 schrieb:
> Das sind immer nur welche mit älteren HAL-Ständen.

Ich habe gerade nur das STM32CubeF1 installiert, und da gibt es:
~/STM32Cube/Repository/STM32Cube_FW_F1_V1.7.0/Projects/STM3210E_EVAL/Exa 
mples/CAN/

Beim STM32CubeF4 müsste es etwas ähnliches geben. Das sollte doch zur 
gleichzeitig installierten HAL passen.

von RainerZufall24 (Gast)


Lesenswert?

Gibt es da vielleicht ein Dokument? Wie bei der HAL?

Das ist ziemlich zäh sich das aus Beispielen rauszusaugen...

von Programmierer (Gast)


Lesenswert?

Wie, "wie bei der HAL"? Diese Beispiele sind auf Basis der HAL.

von RainerZufall24 (Gast)


Lesenswert?

Sorry, jetzt war ich total verwirrt.

Ich wollte eigentlich "Louis (Gast)" fragen ob das eine Doku zu den 
LL-CAN Funktionen gibt. In dem HAL- Dokument ist da nichts aufgeführt.

von Martin L. (maveric00)


Lesenswert?

Hallo,

der PARAM-Error wird bei HAL_CAN_GetRxMessage gesetzt, wenn in 
angegebenen FiFo noch nichts empfangen wurde. in HAL_CAN_AddTxMessage 
wird der Fehler gesetzt, wenn keine Senden-FiFo mehr frei ist.

Ersteres kann an Deinen Filtern liegen, letzteres an einem Bus-Error 
(kein Empfänger sendet Ack, der Controller ist im Bus-Off o. ä.).

Allerdings schreibst Du auch, dass Du am Anfang des Programms eine 
Nachricht senden möchtest um dann in der Schleife regelmäßig eine 
Nachricht zu empfangen. Erstens mach das Programm es anders herum (es 
versucht erst eine zu empfangen und sendet dann regelmäßig eine) und 
zweitens kannst Du nicht regelmäßig eine Botschaft "empfangen" (also aus 
dem CAN-Controller herauslesen), da das Timing vom Sender bestimmt wird 
und jede gesendete/empfangene Botschaft nur einmal gelesen werden kann.


Was Du machen kannst ist entweder regelmäßig nachzusehen, ob eine neue 
Nachricht angekommen ist die nur dann verarbeitet wird (mit dem Risiko, 
dass Deine Empfangs-FiFo vollläuft wenn Du nicht oft genug nachsiehst), 
oder Du speicherst jede empfangene Nachricht in einem Interrupt in eine 
feste "Mailbox" und verwendest die Daten dann regelmäßig im 
Hauptprogramm (Achtung: Daten-Konsistenz der Mailbox muss dann extra 
gewährleistet werden, da sonst der Empfangs-Interrupt mitten in der 
Verarbeitung die Daten verfälschen kann).

Schöne Grüße,
Martin

von Louis (Gast)


Lesenswert?

Hallo,

ich habe genug LL Code, leider keinen den ich posten könnte..

Hast Du den CAN Mode wirklich auf CAN_MODE_LOOPBACK gesetzt 
(zusatz.txt)?
In dem Fall solltest Du eigentlich alle Nachrichten die Du sendest 
jedenfalls selbst empfangen können.
Tatsächlich senden / empfangen kannst Du im Loopback Mode aber nicht, 
dazu brauchst Du CAN_MODE_NORMAL.
Zum Testen kann es auch hilfreich sein, bei der Initialisierung NART 
("no automatic retransmit") auf true zu setzen, ansonsten kann es 
schnell passieren dass Du nach dem Senden einer Nachricht in einen 
Fehlerzustand kommst wenn kein Empfänger die Nachricht bestätigt.

Ansonsten wäre mein erster Tipp wenn die Kommunikation mit einem anderen 
Gerät nicht klappt, nocheinmal alle Werte zum Timing durchzurechnen, man 
kann da sehr schnell einen Fehler machen.
Vielleicht auch mit dem Oszilloskop die min. Bitbreite auf Plausi 
überprüfen.

lg
Louis

von Mee (Gast)


Lesenswert?

Du solltest die HAL_CAN_GetRxMessage() in der ISR nur im Falle des 
Empfangs nutzen (Callback). Sonst scheppert es immer ERRORs.

Error_Handler() implementieren (GPIO toggel, LED an, sonst was).

Mit dem Filter bestimmst du in welchen der 2 RX-FIFOs von CAN1 die 
Nachricht geht.

[Für dual CAN experience: Es gibt insgesamt 4 RX-FIFOs (2 für CAN1 und 2 
für CAN2). Dankenswerter Weise (Ironie) gibt es aber nur Callbacks für 
FIFO0 und FIFO1. Nicht vergessen im jeweiligen Callback nachzuschauen ob 
CAN1 oder CAN2 ausgelöst hat!]

Kannst du irgendwie dein Projekt *.zip machen und hochladen?

von RainerZufall24 (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank nochmal für eure Hilfe.
Ich habe das Projekt nochmal neu aufgesetzt ... und nun funktioniert es.
-> siehe Anhang.

Keine Ahnung was ich falsch gemacht habe.

Weiterhin habe ich nochmal die Doku der HAL angefügt.
Die ist zwar vom STM32F1  ... passt aber soweit denke ich.
Jedenfalls habe ich mich daran gehalten (Stichwort: "How to use this 
driver" -> Seite 92) und nun geht's .

Das Abarbeiten via ISR kommt als nächstest.

Nochmals vielen Dank.
RainerZufall24

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.