Forum: Mikrocontroller und Digitale Elektronik CAN mit STM32F4Discovery und MCP2551: MCP lässt nichts von CANBus zu Rx durch


von Markus B. (markus001)



Lesenswert?

Hallo zusammen,

habe in den letzten Tagen versucht, mit dem STM32F4Discovery-Board und 
dem MCP2551 als CAN-Transceiver, CAN in Betrieb zu nehmen.

Irgendwo scheitert es aber, da der MCP2551 scheinbar nichts vom CAN-Bus 
zum Rx-Pin des MCPs/STMs druchlässt. Zweiter Teilnehmer ist CANoe 
(CANCardXL), welches nur zuhört.

Sofern der STM im Silent-Loopback sendet, funktioniert der Empfang der 
gesendeten Nachricht problemlos.
Wenn der STM im Normal-Mode betrieben wird, liegt der CAN-Frame auch 
scheinbar richtig auf dem Bus (manuelles Auslesen mit Oszi) und CANoe 
bestätigt alles mit nem ACK.

Komischerweise taucht dieses ACK nie am Rx-Pin des MCPs auf, sodass der 
STM immer wieder erneut den Frame auf den Bus gibt (wird an sich nur 
einmal in der main.c versendet).


Nachfolgend der relevante Code:
can.c
1
// Structs
2
CanTxMsg CanTxMessage;
3
CanRxMsg CanRxMessage;
4
5
char std_id_buffer[5] = {'\0'};
6
7
/**
8
 * @brief  This function inits CAN 1 for operation in normal mode.
9
 * @param  none
10
 * @return none
11
 */
12
void init_can()
13
{
14
  // --------------------------
15
  // GPIO for CAN configuration
16
  // --------------------------
17
  GPIO_InitTypeDef GPIO_InitStructure;
18
  // Set clock signal for GPIOs
19
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
20
21
  // Map alternate function of CAN1 to specific pins:
22
  // PD0 for CAN1_RX, PD1 for CAN1_TX
23
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
24
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
25
26
  // Init the GPIOs
27
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
28
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
29
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
30
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
31
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
32
  GPIO_Init(GPIOD, &GPIO_InitStructure);
33
34
  // -------------------
35
  // CAN 1 configuration
36
  // -------------------
37
  CAN_InitTypeDef CAN_InitStructure;
38
  // Set clock signal for CAN1
39
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
40
41
  // Init the CAN module
42
  CAN_DeInit(CAN1);
43
  CAN_InitStructure.CAN_ABOM = DISABLE;
44
  CAN_InitStructure.CAN_AWUM = DISABLE;
45
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
46
  CAN_InitStructure.CAN_NART = DISABLE;
47
  CAN_InitStructure.CAN_RFLM = DISABLE;
48
  CAN_InitStructure.CAN_SJW  = CAN_SJW_2tq;
49
  CAN_InitStructure.CAN_TTCM = DISABLE;
50
  CAN_InitStructure.CAN_TXFP = DISABLE;
51
52
//  // CAN Baudrate = 125 kBps (CAN clocked at 42 MHz)
53
//  // CAN Baudrate = APB1 / (BRP * (1 + BS1 + BS2))
54
//  //              = 42 MHz / (16 * (1 + 14 + 6))
55
//  //              = 125 kBit/s
56
//  // Sample point: 15/21 =(approx)= 71 %
57
//  CAN_InitStructure.CAN_BS1 = CAN_BS1_14tq;
58
//  CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq;
59
//  CAN_InitStructure.CAN_Prescaler = 16;
60
//  CAN_Init(CAN1, &CAN_InitStructure);
61
62
63
  // CAN Baudrate = 100 kBps (CAN clocked at 42 MHz)
64
  // CAN Baudrate = APB1 / (BRP * (1 + BS1 + BS2))
65
  //              = 42 MHz / (20 * (1 + 14 + 6))
66
  //              = 100 kBit/s
67
  // Sample point: 15/21 =(approx)= 71 %
68
  CAN_InitStructure.CAN_BS1 = CAN_BS1_14tq;
69
  CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq;
70
  CAN_InitStructure.CAN_Prescaler = 20;
71
  CAN_Init(CAN1, &CAN_InitStructure);
72
73
  // Init the CAN filter
74
  CAN_FilterInitTypeDef CAN_FilterInitStructure;
75
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
76
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
77
  CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
78
  CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
79
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
80
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
81
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
82
  CAN_FilterInitStructure.CAN_FilterNumber = 0;
83
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
84
  CAN_FilterInit(&CAN_FilterInitStructure);
85
86
  // Init interrupts
87
  NVIC_InitTypeDef NVIC_InitStructure;
88
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
89
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
90
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
91
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
92
  NVIC_Init(&NVIC_InitStructure);
93
94
  // Enable "FIFO 0 message pending" interrupt
95
  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
96
}
97
98
/**
99
 * @brief  This function sends a dummy message on CAN 1.
100
 * @param  none
101
 * @return none
102
 */
103
void send_can_dummy()
104
{
105
  // Init CanTxMessage
106
  clear_CanTxMessage();
107
  clear_CanRxMessage();
108
109
  CanTxMessage.StdId = 0x00F;    // 0...0x7FF
110
  CanTxMessage.RTR = CAN_RTR_DATA;
111
  CanTxMessage.IDE = CAN_ID_STD;
112
  CanTxMessage.DLC = 8;
113
114
  CanTxMessage.Data[0] = 'H';
115
  CanTxMessage.Data[1] = 'i';
116
  CanTxMessage.Data[2] = ' ';
117
  CanTxMessage.Data[3] = 'C';
118
  CanTxMessage.Data[4] = 'A';
119
  CanTxMessage.Data[5] = 'N';
120
  CanTxMessage.Data[6] = '1';
121
  CanTxMessage.Data[7] = '\0';
122
123
  CAN_Transmit(CAN1, &CanTxMessage);
124
}
125
126
/**
127
 * @brief  This is the IRQ-handler for message reception on CAN1
128
 * @param  none
129
 * @return none
130
 */
131
void CAN1_RX0_IRQHandler()
132
{
133
  // Check CAN1_Rx status
134
  if( CAN_GetITStatus(CAN1, CAN_IT_FMP0))
135
  {
136
    // Send data to PC
137
    trigger_uart_PC_send((char*)CanRxMessage.Data);
138
139
    // Clear CAN buffer
140
    clear_CanRxMessage();
141
  }
142
}
143
144
/**
145
 * @brief  This function clears the CanTxMessage struct.
146
 * @param  none
147
 * @return none
148
 */
149
void clear_CanRxMessage()
150
{
151
  unsigned char i;
152
  CanRxMessage.StdId = 0x000;
153
  CanRxMessage.ExtId = 0;
154
  CanRxMessage.RTR = CAN_RTR_DATA;
155
  CanRxMessage.IDE = CAN_ID_STD;
156
  CanRxMessage.DLC = 0;
157
  CanRxMessage.FMI = 0;
158
159
  for(i=0; i < 8; i++)
160
  {
161
    CanRxMessage.Data[i] = 0;
162
  }
163
}

main.c
1
int main(void)
2
{
3
  init_can();
4
5
  send_can_dummy();
6
7
  while(1);
8
9
  return 0;
10
}

Des weiteren sind noch vier Bilder angehängt:

1) Die Verschaltung des MCP2551:
Der 5V-Pin des Discovery-Boards gibt 4,56V aus (laut Datenblatt 
akzeptiert der MCP2551 4,5V <= VDD <= 5,5V. An dem SUB-D9 Stecker wird 
die CANCardXL angeschlossen.

2) Oszi-Aufnahme: Was am CAN-Bus anliegt (CAN_H und CAN_L).

3) Oszi-Aufnahme: Vergleich zwischen CAN_H und Rx-Pin von MCP/STM. Man 
sieht hier, dass der gesendete CAN-Frame wieder (mit erhöhter Amplitude) 
zurückgegeben wird am Rx-Pin, das ACK von CANoe aber nicht.

4) Oszi-Aufnahme: Was der MCP auf Tx vom STM bekommt und was er auf Rx 
wieder an den STM zurückgibt.


Offene Fragen meinerseits:

1) Invertiert der MCP2551 CAN_L vor der Differenzbildung (also CAN_H - 
(-CAN_L) )? Falls nicht, dann wär die Pegeldifferenz ca. 2V. Falls ja, 
wäre sie ca. 3V.
CANoe liefert laut Oszi ein ACK mit ca. 4,4V auf CAN_H, wie auch auf 
CAN_L. Falls der MCP nichts invertiert, dann wär die Differenz des ACKs 
0...

2) Ist es normal, dass der MCP2551 am Rx-Pin eine Signalamplitude 
ungefähr seiner Versorgungsspannung  zurückgibt? Laut DM00037051.pdf 
sind PD0 und PD1 5V-tolerant. Im Idle ist der Rx-Pin vom MCP auf High.

3) Persönlich war ich bisher der Auffassung, dass sich CAN über die 
differenzielle Signalübertragung definiert. Jedoch hab ich letztens auch 
etwas über Single-Wire-CAN gelesen. Gibt es so etwas wie ein 
Single-Wire-CAN, bei welchem CAN_H und CAN_L das gleiche Signal (auch 
vom Pegel her) führen und somit Redundanz erreicht wird?

Eine Bemerkung:
CANoe ist hier nicht auf meinem Rechner installiert, sondern mir wurde 
ein Rechner, auf dem es läuft, geliehen. Vermerk: "CANoe ist als Zuhörer 
konfiguriert. Sollte passen."


Jegliche Anworten und Tipps sind willkommen!

von H.Joachim S. (crazyhorse)


Lesenswert?

>CAN_H_gelb__und_CAN_L_blau_.gif
Da stimmt doch schon was grundlegendes nicht.

Normalerweise haben beide Leitungen in etwa halbe Betriebsspannung und 
auf jeden Fall nur eine kleine Differenzspannung. Beim dominanten Pegel 
geht dann CANH Richtung +, CANL Richtung Masse -> nennenswerte 
Differenzspannung.

von Niklas G. (erlkoenig) Benutzerseite


Angehängte Dateien:

Lesenswert?

Dein 2. Oszi-Bild (CAN_H_gelb__und_CAN_L_blau_.gif) sieht komisch aus.

Ich habe eine ähnliche Konfiguration am Laufen - STM32F373 + SN65HVD1050 
CAN Transceiver (Platine+Schaltung aber nicht von mir) + 
CANcaseXL(CANoe). Bei mir sehen die CAN-Pegel wie im Anhang gezeigt aus 
(Gelb=CANH, Rot=CANL, Grün=invertierte Differenz=CANL-CANH). Der 
empfangende CAN-Transceiver muss also nur die Differenz bilden 
(CANH-CANL) und erhält das Signal.
Ich kenn deinen Transceiver jetzt nicht, aber vielleicht solltest du 
dessen Beschaltung nochmal überprüfen... Und du brauchst auch noch einen 
Terminierungswiderstand (120Ω) an der CANcard.

Stelle das CANoe eventuell mal auf Senden ein (Konfiguration->Generator 
Block hinzufügen->Fantasienachricht eingeben, oder so ähnlich), lass 
dessen CAN-Anschluss offen und schau dir dessen Pegel an.

von H.Joachim S. (crazyhorse)


Lesenswert?

RS direkt an Masse habe ich auch noch nie gesehen. Da gehört 
üblicherweise ein Widerstand hin. Kann sein, dass deshalb dein 
Transceiver nicht korrekt funktioniert.

von Beobachter (Gast)


Lesenswert?

>Da stimmt doch schon was grundlegendes nicht.
Wieso? Sieht doch gut aus.

Kapitel 2.2:
D10 VO(CANH) CANH dominant output voltage 2.75 4.5 V VTXD = 0.8V
D11 VO(CANL) CANL dominant output voltage 0.5 2.25 V VTXD = 0.8V

Wären 2.25V Hub. Auf dem Oszi-Bild hat er etwa 2.0V

von Markus B. (markus001)


Lesenswert?

H.Joachim Seifert schrieb:
>>CAN_H_gelb__und_CAN_L_blau_.gif
> Da stimmt doch schon was grundlegendes nicht.
>
> Normalerweise haben beide Leitungen in etwa halbe Betriebsspannung und
> auf jeden Fall nur eine kleine Differenzspannung. Beim dominanten Pegel
> geht dann CANH Richtung +, CANL Richtung Masse -> nennenswerte
> Differenzspannung.

Danke. So würde es auch für mich mehr Sinn machen.


Niklas Gürtler schrieb:
> Dein 2. Oszi-Bild (CAN_H_gelb__und_CAN_L_blau_.gif) sieht komisch aus.
>
> Ich habe eine ähnliche Konfiguration am Laufen - STM32F373 + SN65HVD1050
> CAN Transceiver (Platine+Schaltung aber nicht von mir) +
> CANcaseXL(CANoe). Bei mir sehen die CAN-Pegel wie im Anhang gezeigt aus
> (Gelb=CANH, Rot=CANL, Grün=invertierte Differenz=CANL-CANH). Der
> empfangende CAN-Transceiver muss also nur die Differenz bilden
> (CANH-CANL) und erhält das Signal.
> Ich kenn deinen Transceiver jetzt nicht, aber vielleicht solltest du
> dessen Beschaltung nochmal überprüfen... Und du brauchst auch noch einen
> Terminierungswiderstand (120Ω) an der CANcard.
>
> Stelle das CANoe eventuell mal auf Senden ein (Konfiguration->Generator
> Block hinzufügen->Fantasienachricht eingeben, oder so ähnlich), lass
> dessen CAN-Anschluss offen und schau dir dessen Pegel an.

Danke für die Erklärung. Bei dir sieht die Aufnahme weit besser aus.
Die Schaltung ist bei mir auf nem Breadboard aufgesteckt. Habe auch 
bereits den MCP2551 gegen einen anderen getauscht; verhalten sich aber 
bei gleich. Die Verschaltung habe ich jetzt schon mehrmals kontrolliert 
und auch einmal komplett neu aufgebaut. Ich bin auch nicht der Erste mit 
dieser Kombination: Beitrag "CAN am stm32f4, Ratlosigkeit macht sich breit"

Den Abschlusswiederstand kann ich morgen noch dran löten und auch deinen 
Vorschlag bzgl. CANoe testen. Bin heut nicht vor Ort.

Mir gehen einfach die Ideen aus, wo das Problem liegen könnte.

von Beobachter (Gast)


Lesenswert?

Mal ne Frage am Rande (ohne jetzt den Thread kapern zu wollen): Sind die 
Transceiver gewissermaßen intelligent genug zu erkennen was ein 
Telegramm ist und quittieren selbstständig, so wie auf dem Bild oben 
mitte? Oder was erzeugt diese Nadel am ende des Telegramms?

von Markus B. (markus001)


Lesenswert?

H.Joachim Seifert schrieb:
> RS direkt an Masse habe ich auch noch nie gesehen. Da gehört
> üblicherweise ein Widerstand hin. Kann sein, dass deshalb dein
> Transceiver nicht korrekt funktioniert.

Danke.
Hier wurde darüber schon mal diskutiert: 
Beitrag "CAN am stm32f4, Ratlosigkeit macht sich breit"
Aber ich werde es morgen einmal testen.

Beobachter schrieb:
>>Da stimmt doch schon was grundlegendes nicht.
> Wieso? Sieht doch gut aus.
>
> Kapitel 2.2:
> D10 VO(CANH) CANH dominant output voltage 2.75 4.5 V VTXD = 0.8V
> D11 VO(CANL) CANL dominant output voltage 0.5 2.25 V VTXD = 0.8V
>
> Wären 2.25V Hub. Auf dem Oszi-Bild hat er etwa 2.0V

Danke. Also doch nicht so falsch.

von Markus B. (markus001)


Lesenswert?

Beobachter schrieb:
> Mal ne Frage am Rande (ohne jetzt den Thread kapern zu wollen): Sind die
> Transceiver gewissermaßen intelligent genug zu erkennen was ein
> Telegramm ist und quittieren selbstständig, so wie auf dem Bild oben
> mitte? Oder was erzeugt diese Nadel am ende des Telegramms?

Diese Nadel am Ende ist das ACK von CANoe. Bedeutet, dass CANoe die 
Nachricht erkannt hat und auch den CRC-Check bestätigt hat.

Die Transceiver übersetzen wirklich nur von differenziellem Signal 
(CAN-H, CAN-L) auf einfaches Signal (Tx und Rx).

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Markus P. schrieb:
> Danke. Also doch nicht so falsch.
Allerdings ist dein CANH irgendwie invertiert; es sollte im Ruhezustand 
doch auf "High" sein, auf deinem Bild ist es aber verkehrt?!

Beobachter schrieb:
> Sind die
> Transceiver gewissermaßen intelligent genug zu erkennen was ein
> Telegramm ist
Nein, die Transceiver sind nur "analoge" Pegelwandler, das ACK und die 
Telegramm-Verarbeitung machen komplett die CAN-Controller (die zB im µC 
integriert sind).

von Markus B. (markus001)


Lesenswert?

Niklas Gürtler schrieb:
> Markus P. schrieb:
>> Danke. Also doch nicht so falsch.
> Allerdings ist dein CANH irgendwie invertiert; es sollte im Ruhezustand
> doch auf "High" sein, auf deinem Bild ist es aber verkehrt?!

In dem Punkt dacht ich aber auch wie H.Joachim Seifert (crazyhorse), 
dass CAN-H bei dominant auf High geht und bei rezessiv auf nem 
"Ruhe-Pegel" verweilt (seiner Meinung nach 0,5 * VDD, was bei mir hier 
nicht der Fall ist).

von H.Joachim S. (crazyhorse)


Lesenswert?

Ein Standard-CAN-Signal hat so auszusehen:
http://commons.wikimedia.org/wiki/File:Canbus_levels.svg

Und so macht es auch der 2551, wenn der Bus in Ordnung ist. Sprich - am 
Transceiver oder an der Busverdrahtung ist was faul.

von Markus B. (markus001)



Lesenswert?

H.Joachim Seifert schrieb:
> Ein Standard-CAN-Signal hat so auszusehen:
> http://commons.wikimedia.org/wiki/File:Canbus_levels.svg
>
> Und so macht es auch der 2551, wenn der Bus in Ordnung ist. Sprich - am
> Transceiver oder an der Busverdrahtung ist was faul.

Ein Standard-"High-Speed"-CAN-Signal sieht so aus.


Hatte gestern nach langer Recherche einen Verdacht, der sich heute 
bestätigt hat:

Ein "Low-Speed-CAN" an Stelle eines "High-Speed-CAN"-Kabels ist an der 
CANCardXL angeschlossen gewesen.
Die Unterschiede kann man hier gut nachlesen (vorher ein CanCab 1054, 
jetzt ein CanCab 251opto):
(Seite 36 und 42)
http://vector.com/portal/medien/cmc/manuals/Interfaces_Accessories_Manual_DE.pdf

Der Zusammenschluss von High-Speed und Low-Speed kann nicht richtig 
funktionieren:
http://digital.ni.com/public.nsf/allkb/84210794086E9C0886256C1C006BE6AE


Ein Dokument, welches mich auf den richtigen Weg gebracht hat, war 
dieses (generell sehr gutes Dokument für den MCP2551):
http://ww1.microchip.com/downloads/en/AppNotes/00228a.pdf

Man sieht auf Seite 8 etwas sehr ähnliches wie ich anfangs auf dem Bus 
hatte: nen Ground-Offset.
Der sollte allerdings nur so wirklich auftreten, wenn auf den 
gemeinsamen GND zzgl. zu CAN-H und CAN-L verzichtet wird. Da dieser bei 
mir aber vorhanden war, suchte ich genauer nach diesen Vector-Kabeln und 
kam auf die Idee.
Den Terminierungswiderstand seitens des D9-Steckers hab ich wieder dran 
gelötet. Auf nen Widerstand an RS hab ich derzeit noch verzichtet, da 
ich derzeit keinen passenden zur Hand habe. Werde damit aber demnächst 
noch experimentieren.


Anbei sind noch zwei Bilder eines CAN-Frames, wie es jetzt aussieht 
(entspricht weit mehr der Norm eines High-Speed-CAN).


Danke nochmal an alle, der kurze Austausch gestern hat definitiv 
geholfen!

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.