Forum: Mikrocontroller und Digitale Elektronik STM32F7Discovery CAN-Bus


von Lega (Gast)


Lesenswert?

Einen freundlichen Gruß an die Gemeinde!
Ich versuche seit ein paar Tagen mein STM32F7Disco in Betrieb zu nehmen. 
Speziell den CAN-Bus mit HAL-Driver. Das Verschicken der Nachricht 
funktioniert soweit.
Nun zu meiner Frage:  Wie kann ich einen CAN-Receiv-Interrupt auslösen, 
bzw. abfangen.  Bei ST32F4Doscovery konnte man ja 
“CAN1_RX0_IRQHandler(void)“ nutzen um auf die ankommende Nachrichten zu 
reagieren. Womit kann ich bei HAL-Basiertem Programm abfabgen?
Meine Initialisierung sieht wie folgt aus:
1
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2
void stm32F7_HAS_CAN_GPIO_Init(){
3
  //~~~~~~~~~~~~  HAL_GPIO_Init(); ~~~~~~~~~~~~~~~~~~~~~~~~
4
5
      GPIO_InitTypeDef GPIO_InitStruct;
6
7
      GPIO_InitStruct.Pin = CAN1_TX | CAN1_RX;
8
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
9
      GPIO_InitStruct.Pull = GPIO_NOPULL;
10
      GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
11
      GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
12
13
      HAL_GPIO_Init(CAN1_PORT, &GPIO_InitStruct);
14
}
15
16
17
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18
19
void stm32F7_HAS_CAN_Init(){
20
21
      CANx_CLK_ENABLE();
22
      CANx_GPIO_CLK_ENABLE();
23
24
25
    stm32F7_HAS_CAN_GPIO_Init();
26
27
    CAN_FilterConfTypeDef sFilterConfig;
28
29
    /*##-1- Configure the CAN peripheral #######################################*/
30
    CanHandle.Instance = CAN1;
31
    CanHandle.pTxMsg = &TxMessage;
32
    CanHandle.pRxMsg = &RxMessage;
33
34
35
36
    CanHandle.Init.TTCM = DISABLE;
37
    CanHandle.Init.ABOM = DISABLE;
38
    CanHandle.Init.AWUM = DISABLE;
39
    CanHandle.Init.NART = DISABLE;
40
    CanHandle.Init.RFLM = DISABLE;
41
    CanHandle.Init.TXFP = DISABLE;
42
//    CanHandle.Init.Mode = CAN_MODE_NORMAL;
43
    CanHandle.Init.Mode = CAN_MODE_LOOPBACK;
44
    CanHandle.Init.SJW = CAN_SJW_1TQ;
45
    CanHandle.Init.BS1 = CAN_BS1_7TQ;
46
    CanHandle.Init.BS2 = CAN_BS2_2TQ;
47
    CanHandle.Init.Prescaler = 10;           //500 Mbps
48
49
    /*##-2- Configure the CAN Filter ###########################################*/
50
    sFilterConfig.FilterNumber = 0;
51
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
52
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
53
    sFilterConfig.FilterIdHigh = 0x0000;
54
    sFilterConfig.FilterIdLow = 0x0000;
55
    sFilterConfig.FilterMaskIdHigh = 0x0000;
56
    sFilterConfig.FilterMaskIdLow = 0x0000;
57
    sFilterConfig.FilterFIFOAssignment = 0;
58
    sFilterConfig.FilterActivation = ENABLE;
59
    sFilterConfig.BankNumber = 14;
60
61
62
63
    /*##-3- Configure Transmission process #####################################*/
64
    CanHandle.pTxMsg->StdId = 0x321;
65
    CanHandle.pTxMsg->ExtId = 0x01;
66
    CanHandle.pTxMsg->RTR = CAN_RTR_DATA;
67
    CanHandle.pTxMsg->IDE = CAN_ID_STD;
68
    CanHandle.pTxMsg->DLC = 8;
69
70
    HAL_CAN_Init(&CanHandle);
71
    HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig);
72
73
    HAL_CAN_Transmit(&CanHandle, 500);
74
75
76
    HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 3, 0);
77
    HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
78
79
80
}
81
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
83
{
84
  RxMsgCNT++;
85
86
}
Und obwohl einige Nachrichten auf dem Bus sind, wird die 
„HAL_CAN_RxCpltCallback“- Routine nicht ausgelöst.
Kann mir jemand sagen was ich übersehen oder falsch gemacht habe?

Gruß
  Lega

von STM Apprentice (Gast)


Lesenswert?

Lega schrieb:
> Womit kann ich bei HAL-Basiertem Programm abfabgen?

Aus meiner beschränkten Sichtweise heraus würde ich sagen
man richtet einen Receive Interrupt ein, aktiviert den
NVIC für diesen Interrupt und schon wird bei Eintreffen
von Daten der relevante IRQ-Handler angesprungen.

von Lega (Gast)


Lesenswert?

Ich dachte mit
1
    HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 3, 0);
2
    HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
hätte ich es getan.
und mit
1
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle){}
würde ich ihn abfangen.

von Stefan K. (stefan64)


Lesenswert?

Lega schrieb:
> sFilterConfig.BankNumber = 14;

Ich denke, für CAN1 muss hier 0 stehen. 14 ist für CAN2.

Gruß, Stefan

von Lega (Gast)


Lesenswert?

Hallo Stefan,

danke für deinen Hinweis, aber gerade ausprobiert: leider  keine 
Auswirkung.

Ich habe  „CanHandle.Init.Mode = CAN_MODE_NORMAL“ gesetzt, somit kann 
ich die Nachrichten mit „HAL_CAN_Receive(&CanHandle,CAN_FIFO0,10)“ 
abholen. Das funktioniert sowohl mit BankNumber=14 als auch mit 
BankNumber=0…

Die Routine “HAL_CAN_Receive_IT” kann ausgeführt werden, bei der ersten 
ankommenden Nachricht hängt sich aber der Kontroller auf.  So wie ich es 
verstanden habe, stößt „HAL_CAN_Receive_IT“ die Interrupt gesteuerte 
Nachrichtenempfang. Also fehlt da ein Interrupthander, oder?

Bin für jede Idee dankbar!
Gruß
Lega

von uint32_t clean_code = 0; (Gast)


Lesenswert?

Lega schrieb:
> bei der ersten
> ankommenden Nachricht hängt sich aber der Kontroller auf

Haengt er sich tatsaechlich auf, oder wird nur nichts mehr empfangen? 
Wie sieht deine Applikation aus? Kann man davon ausgehen, das die 
Bitrate (500 kbps) bei allen teilnehmenden Nodes richtig eingestellt 
ist?

Deine Funktion HAL_CAN_RxCpltCallback wird aus CAN_Receive_IT aufgerufen 
(siehe stm32f4xx_hal_can.c). Dort wird der State des Handles entweder 
auf BUSY_TX oder READY gesetzt. Auch das FIFO0 message pending interrupt 
wird disabled. Das wird erst wieder in HAL_CAN_Receive_IT enabled.

Kann es sein, dass nach Empfangen einer Message letztgenannte Funktion 
stets erneut aufgerufen werden muss?
1
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
2
{
3
  RxMsgCNT++; 
4
  (void)HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0);
5
}

von Lega (Gast)


Lesenswert?

Hallo,

uint32_t clean_code = 0; schrieb:
> Haengt er sich tatsaechlich auf, oder wird nur nichts mehr empfangen?

Der hängt sich wirklich auf, die „main“-Schleife wird auch nicht mehr 
abgearbeitet.
Es gibt nur noch einen aktiven Teilnehmer und der läuft mit 500kbps, 
sonst nur noch der CANalyser.

Mit dem „HAL_CAN_Receive_IT“- Aufruf in „HAL_CAN_RxCpltCallback“- 
Funktion werde ich mal ausprobieren. Auf jeden Fall: vielen Dank für die 
Anregung! Melde mich dann.

Gruß
  Lega

von Christopher J. (christopher_j23)


Lesenswert?

Im Standard-Startup-Code den CubeMX ausspuckt zeigen die ganzen 
Interrupt- und Exception-Handler per "weak" auf den Default-Handler, 
d.h. wenn du den Interrupt scharf schaltest aber keinen Handler 
implementierst, dann landet der Controller im Default-Handler, was eben 
eine simple Endlosschleife ist. Das verhalten ist eben genau das gleiche 
wie standardmäßig bei den ganzen Fault-Handlern und es sieht so aus als 
ob sich der Controller aufgehängt hätte.

Im Klartext heißt das, dass du irgendwo eine Funktion 
CAN1_RX0_IRQHandler() implementieren musst, bzw. eine mit dem Namen, der 
zu dem passt was in deinem Startup-Code steht.

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.