CAN auf STM32F4

Gast #6139751
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
}
Angehängte Dateien:
Gast #6139773
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.
Gast #6139793
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?
Gast #6139797
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...
Gast #6139850
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
Gast #6139877
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
#6140158
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
Gast #6140255
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
Gast #6140285
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?
Gast #6140726
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
Angehängte Dateien:

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