Forum: Mikrocontroller und Digitale Elektronik CAN am stm32f4, Ratlosigkeit macht sich breit


von Kris (Gast)


Lesenswert?

Hallo zusammen,
ich versuche seit mehreren Stunden, eine CAN-Übertragung zustande zu 
bekommen, aber irgendwie kriege ich nur ACK-errors. Dummerweise kann ich 
noch nichtmal sagen, ob's an der Hardware oder der Software hängt. Ich 
vermute allerdings einen der folgenden Fehler:

- Pin-Remap klappt nicht
- Bit-Timing stimmt nicht (bin nicht ganz sicher, welche Frequenz am 
APB1 anliegt)
- Can-Transceiver falsch verkabelt?
Ich poste hier mal meinen Code, vielleicht fällt ja jemandem direkt was 
auf. Habe mich stark an der ST-Lib orientiert, vielleicht habe ich bei 
den Änderungen einen Fehler gemacht oder sowas.
1
void CAN_Config(void)
2
{
3
  GPIO_InitTypeDef  GPIO_InitStructure;
4
5
  /* CAN GPIOs configuration **************************************************/
6
7
  /* Enable GPIO clock */
8
  RCC_AHB1PeriphClockCmd(CAN_GPIO_CLK, ENABLE);
9
10
  /* Connect CAN pins to AF9 */
11
  GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
12
  GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT);
13
14
  /* Configure CAN RX and TX pins */
15
  GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN | CAN_TX_PIN;
16
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
17
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
18
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
19
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
20
  GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
21
22
  /* CAN configuration ********************************************************/
23
  /* Enable CAN clock */
24
  RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
25
26
  /* CAN register init */
27
  CAN_DeInit(CANx);
28
29
  /* CAN cell init */
30
  CAN_InitStructure.CAN_TTCM = DISABLE;
31
  CAN_InitStructure.CAN_ABOM = DISABLE;
32
  CAN_InitStructure.CAN_AWUM = DISABLE;
33
  CAN_InitStructure.CAN_NART = DISABLE;
34
  CAN_InitStructure.CAN_RFLM = DISABLE;
35
  CAN_InitStructure.CAN_TXFP = DISABLE;
36
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
37
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
38
39
  /* CAN Baudrate = 500 kBps (CAN clocked at 36 MHz) */
40
  CAN_InitStructure.CAN_BS1 = CAN_BS1_12tq;
41
  CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
42
  CAN_InitStructure.CAN_Prescaler = 4;
43
  CAN_Init(CANx, &CAN_InitStructure);
44
45
  /* CAN filter init */
46
  CAN_FilterInitStructure.CAN_FilterNumber = 0;
47
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
48
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
49
  CAN_FilterInitStructure.CAN_FilterIdHigh = 0x7770;
50
  CAN_FilterInitStructure.CAN_FilterIdLow = 0x7730;
51
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
52
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
53
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
54
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
55
  CAN_FilterInit(&CAN_FilterInitStructure);
56
57
  /* Transmit Structure preparation */
58
  TxMessage.StdId = 0x321;
59
  TxMessage.ExtId = 0x01;
60
  TxMessage.RTR = CAN_RTR_DATA;
61
  TxMessage.IDE = CAN_ID_STD;
62
  TxMessage.DLC = 1;
63
64
  /* Enable FIFO 0 message pending Interrupt */
65
  CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
66
}
und aus der main.h:
1
#define USE_CAN1
2
3
#ifdef  USE_CAN1
4
  #define CANx                       CAN1
5
  #define CAN_CLK                    RCC_APB1Periph_CAN1
6
  #define CAN_RX_PIN                 GPIO_Pin_0
7
  #define CAN_TX_PIN                 GPIO_Pin_1
8
  #define CAN_GPIO_PORT              GPIOD
9
  #define CAN_GPIO_CLK               RCC_AHB1Periph_GPIOD
10
  #define CAN_AF_PORT                GPIO_AF_CAN1
11
  #define CAN_RX_SOURCE              GPIO_PinSource0
12
  #define CAN_TX_SOURCE              GPIO_PinSource1
13
#endif  /* USE_CAN1 */

STM32F4 Discovery, MCP2551. Auf welcher Frequenz sollte der APB1 laufen?
Vielleicht hilft mir das ja direkt weiter...
Falls ihr für ne brauchbare Antwort noch mehr Code-Ausschnitte braucht 
oder andere Fragen habt, werde ich das hier natürlich gerne noch 
ergänzen. Bin nur leider mittlerweile echt am verzweifeln und für jede 
Hilfe dankbar.

Besten Dank im Voraus!

von Hans (Gast)


Lesenswert?

Hast du deinen Sys Clock richtig konfiguriert?

Kennst du deinen Clock Speed und woher er kommt?

Hast du einen CAN Sender und CAN Empfänger gepaart (ev. mit CAN 
Analyser)?

Tut sich was auf den CAN Pins wenn du sendest (Osci)?

Falls ja mit welcher Frequenz?

Welche Entwicklungsumgebung?

von Kris (Gast)


Lesenswert?

Ui, gleich so viele Fragen auf einmal...

SystemCoreClock steht auf 168 Mhz, zumindest wird mir das in meiner 
Timer-Funktion so angezeigt, sollte also geklappt haben.

Wir basteln hier mit einer CANoe-Testumgebung rum, die Gegenstelle ist 
also ein Vector CanCase XL.

Gesendet habe ich bis jetzt noch nichts, das könnte ich aber mal mit dem 
Beispiel-Programm testen. Wäre wirklich mal ne gute Idee um zu gucken, 
ob der Remap funktioniert hat. Werd ich nochmal flott ausprobieren, wenn 
das sich nicht als zu aufwendig herausstellt (is ja kurz vor Feierabend 
und so ;))

Ach ja, ich arbeite mit Atollic TrueStudio Lite.

von turni (Gast)


Lesenswert?

Du hast schon ne Gegenstelle, oder?

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Welche Systemclocks tatsächlich eingestellt sind kannst Du mit 
"RCC_GetClocksFreq()" auslesen.

Damit siehst Du die Sysclocks und die Peripherieclocks.

von Hans (Gast)


Lesenswert?

Du mußt jetzt mal 2 CAN Teilnehmer paaren und dann senden und messen.
Vielleicht gehts ja schon lang. Aber dazu mußt du es ausprobieren.....

von Andreas G. (andreasgs)


Lesenswert?

Hi,

Im CANoe CAN - Treiber hast du ACK an? Standardmässig hört CANoe nämlich 
nur am Bus, ohne den Empfang einer Botschaft zu bestätigen (das sollten 
normal auch nur die anderen SG machen). Wenn du jetzt nur einen 
Busteilnehmer zu deiner Schaltung hast, muss der (also dein CANoe) in 
den ACK slot schreiben. Wenn nicht, bekommste einen ACK Fehler.

Grüßle
Andreas

von Kris (Gast)


Lesenswert?

Andreas Gassner schrieb:
> Im CANoe CAN - Treiber hast du ACK an? Standardmässig hört CANoe nämlich
> nur am Bus, ohne den Empfang einer Botschaft zu bestätigen (das sollten
> normal auch nur die anderen SG machen). Wenn du jetzt nur einen
> Busteilnehmer zu deiner Schaltung hast, muss der (also dein CANoe) in
> den ACK slot schreiben. Wenn nicht, bekommste einen ACK Fehler.

Ich versuch's ja eigentlich genau andersherum... ich will über CANoe was 
senden und mit dem uC empfangen. Und CANoe wirft ACK-Errors aus, weil 
vom uC nix zurück kommt.

von Andreas G. (andreasgs)


Lesenswert?

Hi,

Achso, sorum...

Ich geh mal davon aus, dass du einen Abschlusswiderstand hast? Ohne ist 
der CAN manchmal bockig, wenn die Kablelängen recht lang werden...

Grüßle
Andreas

von Kris (Gast)


Angehängte Dateien:

Lesenswert?

Andreas Gassner schrieb:
> Hi,
>
> Achso, sorum...
>
> Ich geh mal davon aus, dass du einen Abschlusswiderstand hast? Ohne ist
> der CAN manchmal bockig, wenn die Kablelängen recht lang werden...
>
> Grüßle
> Andreas

Ja, vor dem MCP hängen zwischen CANH und CANL 120Ohm. Daran dürfte es 
also eigentlich nicht hängen. Hab's im Grunde so verkabelt wie im Anhang 
gezeigt.

von Hans (Gast)


Lesenswert?

R2 brücken, dann gehts...

von Peter (Gast)


Lesenswert?

Weiss nicht warum, mit dem Widerstand hatte ich das gleiche Problem. 
Laut Datenblatt richtig, funktioniert aber nur als 0 Ohm.

von Kris (Gast)


Lesenswert?

Also R2 einfach komplett rausnehmen oder wie? Bin heute nicht vor Ort, 
kann's deswegen also nicht ausprobieren, aber werd das bei nächster 
Gelegenheit mal nachholen. Danke schonmal!

von Kris (Gast)


Lesenswert?

So, nur mal ein kleines Update hier:
habe R2 jetzt gebrückt, und noch schnell die Werte für's Bit-Timing 
angepasst (läuft offensichtlich auf 42MHz), und jetzt klappt es. Vielen 
Dank nochmal an alle für die Hilfe!

von Kris (Gast)


Lesenswert?

Okay, nächstes Problem:
Der Interrupt wird nicht ausgelöst, so dass zwar die Nachrichten 
empfangen werden, ich aber nix damit machen kann.
Nach dem bereits oben aufgeführten Code folgt die
1
void NVIC_Config(void)
2
{
3
  NVIC_InitTypeDef  NVIC_InitStructure;
4
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
5
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
6
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
7
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
8
  NVIC_Init(&NVIC_InitStructure);
9
}

Der Interrupt wird aber nie aufgerufen, obwohl die CAN-Nachrichten 
empfangen werden. Selbst bei offenem Filter passiert nix.

Jemand ne Idee, woran das liegen könnte?

von Andreas W. (geier99)


Lesenswert?

Kris schrieb:

> Jemand ne Idee, woran das liegen könnte?

beim stm32f10x machen ich immer noch folgendes:

  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

von Kris (Gast)


Lesenswert?

Andreas W. schrieb:
> beim stm32f10x machen ich immer noch folgendes:
>
>   CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);


Gute Idee, steht aber leider schon im Quelltext drin, siehe originales 
Posting...

Sonst vielleicht noch jemand eine Idee?

von Kris (Gast)


Lesenswert?

Okay, hab's rausgefunden:

die Struktur der RxMessage muß im Interrupthandler natürlich auch 
bekannt sein. D'oh!

von Mach F. (machfax)


Lesenswert?

Kris schrieb:
> die Struktur der RxMessage muß im Interrupthandler natürlich auch
> bekannt sein.

Hallo
Kannst Du bitte die Lösung posten, habe dasselbe Problem...

von Kris (Gast)


Lesenswert?

Hey, sehe leider jetzt erst, dass das Thema anscheinend wieder aktuell 
ist.
Falls es dir nach fast einem Monat noch hilft, hier mal was zum 
Interrupthandler:
1
void CAN1_RX0_IRQHandler(void) {
2
  CanRxMsg RxMessage;
3
4
  uint8_t i = 0;
5
6
  RxMessage.StdId = 0x00;
7
  RxMessage.ExtId = 0x00;
8
  RxMessage.IDE = 0;
9
  RxMessage.DLC = 0;
10
  RxMessage.FMI = 0;
11
  for (i = 0; i < 8; i++) {
12
    RxMessage.Data[i] = 0x00;
13
  }
14
15
  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
16
17
/* ... und dann natürlich noch eine Funktion, mit der du die Daten weiterverarbeitest...*/
18
}

Hoffe, das hilft dir weiter.

von Frydtz (Gast)


Lesenswert?

falls sich noch jmd fragt wie das Bit-Timing richtig konfiguriert wird - 
siehe da:
1
RCC_ClocksTypeDef clocks;
2
RCC_GetClocksFreq(&clocks);
3
4
CAN_InitStructure.CAN_BS1 = CAN_BS1_12tq; //~_1tq bis ~_16tq
5
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq; //~_1tq bis ~_8tq
6
CAN_InitStructure.CAN_Prescaler = 
7
    (u16) (clocks.PCLK1_Frequency / ((3 + CAN_InitStructure.CAN_BS1 + CAN_InitStructure.CAN_BS2) * BAUDRATE)) - 1;

gz.frydtz

von Frydtz (Gast)


Lesenswert?

1
CAN_InitStructure.CAN_Prescaler = 
2
    (u16) (clocks.PCLK1_Frequency / ((3 + CAN_InitStructure.CAN_BS1 + CAN_InitStructure.CAN_BS2) * BAUDRATE));

ist richtig - sry für den mistpost

gz.frydtz

von LM (Gast)


Lesenswert?

Moin,
die NVIC-initialisierung muss immer nach allen anderen stehen. Das hat 
bei mir häufig Probleme gemacht.
Hoffe das hilft...
Gruss LM

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.