Forum: Mikrocontroller und Digitale Elektronik STM32F767ZIT: CAN-Probleme


von Martin R. (mme)


Lesenswert?

Hallo,

ich habe mich mit einem STM23F103RBT in CAN eingearbeitet und es hat 
soweit gut funktioniert.

Nun möchte ich CAN in meinem Projekt mit einem STM32F767ZIT verwenden. 
Ich verwende hier ebenfalls HAL-Treiber. Beim Initialisieren bringt er 
einen HAL-Error. Er wird an folgender Stelle generiert:
1
  /* Check Sleep mode leave acknowledge */
2
  while ((hcan->Instance->MSR & CAN_MSR_SLAK) != RESET)
3
  {
4
    if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
5
    {
6
      /* Update error code */
7
      hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;
8
9
      /* Change CAN state */
10
      hcan->State = HAL_CAN_STATE_ERROR;
11
12
      return HAL_ERROR;
13
    }
14
  }

Mir ist allerdings nicht ganz klar, wie der Timeout geprüft wird. Kann 
der Fehler daran liegen, daß aktuell noch kein CAN-Transceiver an den 
Prozessorports angeschlossen ist? Bei dem kleinen STM32 war einer 
bereits am Testboard von Olimex bestückt. Ich muß mir erst einen 
Transceiver beschaffen.

Gruß
Martin

: Bearbeitet durch User
von John Doe (Gast)


Lesenswert?

Martin R. schrieb:
> Mir ist allerdings nicht ganz klar, wie der Timeout geprüft wird. Kann
> der Fehler daran liegen, daß aktuell noch kein CAN-Transceiver an den
> Prozessorports angeschlossen ist? Bei dem kleinen STM32 war einer
> bereits am Testboard von Olimex bestückt. Ich muß mir erst einen
> Transceiver beschaffen.


PullUp an Can RX, solange kein Transceiver dranhängt.

von Martin R. (mme)


Lesenswert?

John Doe schrieb:
> PullUp an Can RX, solange kein Transceiver dranhängt.

Danke, das war das Problem!

von Martin R. (mme)


Lesenswert?

Gibt es für den STM32F767ZIT Beispielprogramme für CAN? Ich habe per 
Google-Suche nichts vernünftiges gefunden.

Das Ganze ist schon deutlich anders (komplexer) als beim kleinen 
STM23F103RBT. Auf Anhieb habe ich es noch nicht verstanden, wie es beim 
STM32F767ZIT funktioniert. Fängt schon damit an, daß es dort in der 
Rx-/Tx-Struktur keine Datenbytes gibt.

Gruß
Martin

von Pieter (Gast)


Lesenswert?

moin,

>>Das Ganze ist schon deutlich anders (komplexer) als beim kleinen
STM23F103RBT.

glaub ich nicht, warum auch?
Ich benutze für 103/303/405/407 da selbe CAN-Modul...allerdings in 
PASCAL.

Setze Bit 30 im BTR Register, damit wird der LoopBack eingeschaltet.

Peter

von Guest (Gast)


Lesenswert?

Die haben irgendwann mal für die größeren CPUs die HAL Treiber umgebaut 
und das nach und nach für alle gemacht. Kann es sein das das das auf dem 
F1 noch nicht angekommen ist? Ich hab ewig nicht mehr mit der F1 Serie 
gearbeitet. Auf dem F2 ist es seit kurzem.

von Guest (Gast)


Lesenswert?

Hier mal ein einfaches Beispiel, damit solltest du eigentlich Sachen 
verschicken und empfangen können. Ich weiß ja nicht wie deine use case 
aussieht. Das CAN_Send könnte man im TX Complete Callback aufrufen um 
neue Daten zu verschicken. Ich hab das bei mir mit einer dynamischen 
Liste gelöst zu der neue Frames hinzugefügt werden und die wird dann in 
den Callbacks abgearbeitet. Der code geht natürlich nur wenn du einen 
CAN benutzt, wenn du mehrere hast musst du in de Callbacks entsprechend 
zuordnen.
1
//Global
2
//---------------------------------
3
CAN_TxHeaderTypeDef TXHeader;
4
uint32_t usedMailbox;
5
uint8_t RXdata[8];
6
uint16_t RXid;
7
//---------------------------------
8
9
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){
10
  
11
  RXid = can->rxFrame0.header.StdId; 
12
  RXdata[0] = can->rxFrame0.data[0];
13
  RXdata[1] = can->rxFrame0.data[1];
14
  RXdata[2] = can->rxFrame0.data[2];
15
  RXdata[3] = can->rxFrame0.data[3];
16
  RXdata[4] = can->rxFrame0.data[4];
17
  RXdata[5] = can->rxFrame0.data[5];
18
  RXdata[6] = can->rxFrame0.data[6];
19
  RXdata[7] = can->rxFrame0.data[7];
20
}
21
22
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
23
  RXid = can->rxFrame0.header.StdId; 
24
  RXdata[0] = can->rxFrame1.data[0];
25
  RXdata[1] = can->rxFrame1.data[1];
26
  RXdata[2] = can->rxFrame1.data[2];
27
  RXdata[3] = can->rxFrame1.data[3];
28
  RXdata[4] = can->rxFrame1.data[4];
29
  RXdata[5] = can->rxFrame1.data[5];
30
  RXdata[6] = can->rxFrame1.data[6];
31
  RXdata[7] = can->rxFrame1.data[7];
32
}
33
34
HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan){
35
        //zu verschickende Daten handhaben
36
        CAN_Send (uint16_t id, uint8_t * data, uint8_t dlc);
37
}
38
39
HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan){
40
        //zu verschickende Daten handhaben
41
        CAN_Send (uint16_t id, uint8_t * data, uint8_t dlc);
42
}
43
44
HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan){
45
        //zu verschickende Daten handhaben
46
        CAN_Send (uint16_t id, uint8_t * data, uint8_t dlc);
47
}
48
49
void CAN_Init(){
50
51
  HAL_CAN_Start(hcan);
52
53
  HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
54
  HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO1_MSG_PENDING);
55
  HAL_CAN_ActivateNotification(hcan, CAN_IT_TX_MAILBOX_EMPTY);
56
  HAL_CAN_ActivateNotification(hcan, CAN_IT_ERROR_PASSIVE);
57
  HAL_CAN_ActivateNotification(hcan, CAN_IT_ERROR_WARNING);
58
  HAL_CAN_ActivateNotification(hcan, CAN_IT_BUSOFF);
59
  HAL_CAN_ActivateNotification(hcan, CAN_IT_LAST_ERROR_CODE);
60
  HAL_CAN_ActivateNotification(hcan, CAN_IT_ERROR);
61
62
}
63
64
void CAN_Send (uint16_t id, uint8_t * data, uint8_t dlc) {
65
66
  TXHeader.StdId = id;
67
  TXHeader.DLC = dlc;
68
69
  HAL_CAN_DeactivateNotification(hcan, CAN_IT_TX_MAILBOX_EMPTY);
70
71
  if (HAL_CAN_GetTxMailboxesFreeLevel(hcan)) {
72
    HAL_CAN_AddTxMessage(hcan, &TXHeader, data, &usedMailbox);
73
  }
74
  HAL_CAN_ActivateNotification(can->IO.hcan, CAN_IT_TX_MAILBOX_EMPTY);
75
}

von Martin R. (mme)


Lesenswert?

Guest schrieb:
> void CAN_Init(){
>
>   HAL_CAN_Start(hcan);
>
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO1_MSG_PENDING);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_TX_MAILBOX_EMPTY);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_ERROR_PASSIVE);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_ERROR_WARNING);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_BUSOFF);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_LAST_ERROR_CODE);
>   HAL_CAN_ActivateNotification(hcan, CAN_IT_ERROR);

Danke für die Infos. Ich habe schon das Problem, daß die Initialisierung 
nicht geht:

CAN_HandleTypeDef hcan1;
HAL_CAN_Start(hcan1);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_RX_FIFO1_MSG_PENDING);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_TX_MAILBOX_EMPTY);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_ERROR_PASSIVE);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_ERROR_WARNING);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_BUSOFF);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_LAST_ERROR_CODE);
HAL_CAN_ActivateNotification(hcan1, CAN_IT_ERROR);


Es kommt die Compilermeldung:
* incompatible type for argument 1 of 'HAL_CAN_Start'
* incompatible type for argument 1 of 'HAL_CAN_ActivateNotification'

Was gefällt ihm an hcan1 nicht?

von Guest (Gast)


Lesenswert?

Du musst ihm die Adresse übergeben:

HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
HAL_CAN_AddTxMessage(&hcan1,...)
...

Damit sollte das klappen. Ich habe den Code bei mir raus kopiert da 
stand das in Funktionen drin die schon Pointer bekommen das hab ich beim 
kopieren vergessen :(

von Mirco (Gast)


Lesenswert?

Hi.

Ich würde einfach die HAL weglassen und die CAN Register selber 
einstellen. Guck dir mal das Reference Manual an. Da ist eig auf 30 
Seiten jede Einstellung und Funktion beschrieben. Zumindest bei STM32F4. 
Wird ja vermutlich ähnlich sein.

Ich bin auch einen Tag lang mit der Hal nicht wirklich weitergekommen, 
weil die ja sehr bescheiden kommentiert ist. Im nachhinein hab ich es 
einfach selber gemacht. Das ist wirklich relativ einfach.

Die Can Perepherie setzt fast alles in HW um man muss nur ein paar 
Einstellungen vornehmen und die Mailboxen abfragen.

von Guest (Gast)


Lesenswert?

Mirco schrieb:
> Ich bin auch einen Tag lang mit der Hal nicht wirklich weitergekommen,
> weil die ja sehr bescheiden kommentiert ist.

Es gibt für so gut wie alles Beispiele in den HAL Treibern die CubeMX 
runterlädt. In der Zeit in der du Register suchst und das Manual liest 
hast du das mit der HAL 3 mal gemacht oder ist es zu schwer 3 Funktionen 
zu verwenden?

von Martin R. (mme)


Lesenswert?

Nun bin ich endlich wieder dazu gekommen, das Ganze zu testen. Nun kommt 
folgende Fehlermeldung:

    invalid type argument of '->' (have 'struct can_def')


bei
1
RXid = can->rxFrame0.header.StdId; 
2
  RXdata[0] = can->rxFrame0.data[0];
3
  RXdata[1] = can->rxFrame0.data[1];
4
  RXdata[2] = can->rxFrame0.data[2];

wie hast du die Struktur "can" angelegt?

Gruß
Martin

von Martin R. (mme)


Lesenswert?

Guest schrieb:
> Es gibt für so gut wie alles Beispiele in den HAL Treibern die CubeMX
> runterlädt

Bei mir finde ich keine Beispiele im CubeMX-Pfad. Wo sollen die sein?

von Guest (Gast)


Lesenswert?

Martin R. schrieb:
> wie hast du die Struktur "can" angelegt?

das ist der Pointer auf die CAN Instanz die im RX Callback mit übergeben 
wird. Das müsste demnach:

RXdata[0] = hcan->rxFrame0.data[0];
etc.

heißen. Wie gesagt habe das aus meiner lib kopiert da ist das teilweise 
in eigenen Structs gelandet ich habe da beim copy paste etwas verkackt 
sry. :D


Martin R. schrieb:
> Bei mir finde ich keine Beispiele im CubeMX-Pfad. Wo sollen die sein?

Unter Windows:
C:\Users\"UserName"\STM32Cube\Repository

da sind die Firmware Files und innerhalb der Ordner für die Firmware der 
einzelnen MCUs gibt es den Ordner Projects und da drin sind dann für 
verschiedenen Nucleo / Discovery Boards Ordner und in denen sind dann 
unter „Examples“ für verschiedenen Peripherie Beispiele. Es gibt nicht 
bei jedem alles daher sucht man am besten im Projects Ordner nach der 
Peripherie „CAN, ADC, DMA, DAC etc.“

von STK500-BEsitzer (Gast)


Lesenswert?

John Doe schrieb:
> PullUp an Can RX, solange kein Transceiver dranhängt.

Oder die Schnittstelle auf Loop-Back konfigurieren.

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.