Forum: Mikrocontroller und Digitale Elektronik Problem mit CAN Interface MCP2515/2551


von Tobias K. (tobias_k73)


Angehängte Dateien:

Lesenswert?

Hallo zusammen!

Ich habe mir ein CAN Bus Interface mit den Chips MCP2515 und MCP2551 
gebaut. Dieses Interface spreche ich mit einem Arduino Mega 2560 Board 
über SPI an, dazu ist es mit den Anschlüssen CS, SCK, MOSI und MISO 
verbunden. Der Anschluß "Mode" geht auch zu einem Pin auf dem Arduino 
Board, spielt aber jetzt noch keine Rolle. Die +5V Versorgung kommt auch 
vom Board.

Zu Beginn des Programms auf dem Arduino sende ich einen Reset Befehl an 
den MCP2515. Allerdings bleibt dieser scheinbar immer im "Normal Mode" 
und wechselt nicht in den "Configuration Mode", daher scheiter ich an 
dieser Stelle schon: beim Auslesen des CANSTAT Registers stehen die 
OPMOD Bits immer auf 000, egal was ich tue. Das gleiche gilt, wenn ich 
statt des Reset Befehls die REQOP Bits im CANCTRL Register manuell 
setze.

Ich möchte erst mal ausschließen, dass mit der Schaltung irgendwas nicht 
stimmt, ob ich da irgendwas übersehen habe oder ob die Werte vielleicht 
nicht stimmen. Könnte da jemand mal drüber schauen?

Bitte nicht erschlagen, falls ich nicht exakt die richtigen Symbole oder 
so im Schaltplan verwendet habe. Das ist der erste Schaltplan, den ich 
mit Eagle erstellt habe...

Ich hoffe ich hab alles richtig erklärt, ist alles noch Neuland für 
mich.

Kann mir einer helfen?

von Thomas (kosmos)


Lesenswert?

ohne dein Programm zu sehen wird dir keiner helfen können. Du gehst ja 
davon aus das die SPI-Verbingung funktioniert aber vielleicht ist ja 
hier der Hund begraben.

von Tobias K. (tobias_k73)


Lesenswert?

Ok, ich dachte mir, man könnte erst mal so erkennen, ob es ein 
grundlegendes Problem mit der Schaltung gibt.
Hier ist dann auch noch der Code, steht aber noch nicht viel drin:

Wie gesagt, jedesmal, wenn ich canStatus ausgebe, bekomme ich "0" raus.

1
#include <SPI.h>
2
3
const byte READ = 0x03;
4
const byte WRITE = 0x02;
5
const byte RESET = 0xC0;
6
const byte CANSTAT = 0x0E;
7
const byte CANCTRL = 0x0F;
8
const int MISO = 50;
9
const int MOSI = 51;
10
const int SCK = 52;
11
const int SLAVESELECT = 53;
12
const int modePin = 49;
13
byte canStatus;
14
int i;
15
int counter;
16
17
void setup()
18
{
19
  Serial.begin(9600);
20
  Serial.println("--- START SETUP ---");
21
  SPI.begin();
22
  delay(100);
23
  Serial.println("--- SETUP FINISHED ---");
24
}
25
26
void loop()
27
{
28
  Serial.print("--- START LOOP --- ");
29
  Serial.println(counter, DEC);
30
  
31
  Serial.println("Reading MCP2515 status:");
32
  digitalWrite(SLAVESELECT, LOW);
33
  SPI.transfer(READ);
34
  SPI.transfer(CANSTAT);
35
  canStatus = SPI.transfer(0);
36
  digitalWrite(SLAVESELECT, HIGH);
37
  
38
  Serial.print("MCP2515 Status: ");
39
  Serial.println(canStatus, BIN);
40
  
41
  Serial.println("Trying to reset MCP2515");
42
  digitalWrite(SLAVESELECT, LOW);
43
  SPI.transfer(RESET);
44
  digitalWrite(SLAVESELECT, HIGH);
45
  delay(200);
46
  
47
  Serial.println("Reading MCP2515 status:");
48
  digitalWrite(SLAVESELECT, LOW);
49
  SPI.transfer(READ);
50
  SPI.transfer(CANSTAT);
51
  canStatus = SPI.transfer(0);
52
  digitalWrite(SLAVESELECT, HIGH);
53
  
54
  Serial.print("MCP2515 Status: ");
55
  Serial.println(canStatus, BIN);
56
  
57
  Serial.println("Setting to configuration mode");
58
  digitalWrite(SLAVESELECT,LOW);
59
  SPI.transfer(WRITE); 
60
  SPI.transfer(CANCTRL);
61
  SPI.transfer(0b10000000);
62
  digitalWrite(SLAVESELECT,HIGH);
63
  delay(200);
64
  
65
  Serial.println("Reading MCP2515 status:");
66
  digitalWrite(SLAVESELECT, LOW);
67
  SPI.transfer(READ);
68
  SPI.transfer(CANSTAT);
69
  canStatus = SPI.transfer(0xFF);
70
  digitalWrite(SLAVESELECT, HIGH);
71
  
72
  Serial.print("MCP2515 Status: ");
73
  Serial.println(canStatus, BIN);
74
  
75
  Serial.println("Setting to listen only mode");
76
  digitalWrite(SLAVESELECT,LOW);
77
  SPI.transfer(WRITE); 
78
  SPI.transfer(CANCTRL);
79
  SPI.transfer(0b01100000);
80
  digitalWrite(SLAVESELECT,HIGH);
81
  delay(200);
82
  
83
  Serial.println("Reading MCP2515 status:");
84
  digitalWrite(SLAVESELECT, LOW);
85
  SPI.transfer(READ);
86
  SPI.transfer(CANSTAT);
87
  canStatus = SPI.transfer(0xFF);
88
  digitalWrite(SLAVESELECT, HIGH);
89
  
90
  Serial.print("MCP2515 Status: ");
91
  Serial.println(canStatus, BIN);
92
  
93
  Serial.println("Setting to normal mode");
94
  digitalWrite(SLAVESELECT,LOW);
95
  SPI.transfer(WRITE); 
96
  SPI.transfer(CANCTRL);
97
  SPI.transfer(0b00000000);
98
  digitalWrite(SLAVESELECT,HIGH);
99
  delay(200);
100
  
101
  Serial.println("Reading MCP2515 status:");
102
  digitalWrite(SLAVESELECT, LOW);
103
  SPI.transfer(READ);
104
  SPI.transfer(CANSTAT);
105
  canStatus = SPI.transfer(0xFF);
106
  digitalWrite(SLAVESELECT, HIGH);
107
  
108
  Serial.print("MCP2515 Status: ");
109
  Serial.println(canStatus, BIN);
110
  
111
  Serial.println("--- LOOP FINISHED ---");
112
  counter = counter + 1;
113
  delay(1000);
114
}

von soundso (Gast)


Lesenswert?

vergessenen Pullups an den SPI Leitungen ???

von H.Joachim S. (crazyhorse)


Lesenswert?

Hm, mit der Software kann ich erstmal nicht viel anfangen...
Zur Hardware:
sieht richtig aus, bis auf den Int-Ausgang, den solltest du auf jeden 
Fall noch zum Controller häkeln. Kann mir nicht vorstellen, wie du 
sinnvoll ohne Interrupt arbeiten kannst (hat aber nichts mit deinen 
momentanen Problemen zu tun)
Kontrollier als erstes mal mit einem Scope den clkout-Pin, nach reset 
müssen dort 1MHz anliegen.

von Anyone (Gast)


Lesenswert?

Wo wird der CS gesetzt bzw. nach Masse gezogen?
In den SPI-Funktionen?

von Anyone (Gast)


Lesenswert?

Sehs gerade, sry.

von Tobias K. (tobias_k73)


Lesenswert?

soundso schrieb:
> vergessenen Pullups an den SPI Leitungen ???

Das wird ja schon durch den Befehl
1
SPI.begin();

erledigt. Oder meinst du richtige Hardware Pullups in der Schaltung?

von Tobias K. (tobias_k73)


Lesenswert?

H.joachim Seifert schrieb:
> Kontrollier als erstes mal mit einem Scope den clkout-Pin, nach reset
> müssen dort 1MHz anliegen.

Gut, das werde ich heute Abend mal versuchen. Gott sei Dank hab ich ja 
noch das Osziloskop von meinem Vater zu Hause :-)

Noch ne Sache: Während meinen letzten Tests war an den CANH und CANL 
Leitungen vom MCP2551 nichts angeschlossen. Ich dachte mir, das brauch 
ich nicht unbedingt, um den MCP2515 zum laufen zu bringen. Ist das 
richtig?

von Thomas F. (igel)


Lesenswert?

Ich habe den Reset des MCP2515 mit dem Reset des Atmega verbunden. Dazu 
die übliche R und C Resetschaltung. Das funktioniert inzwischen bei 
mehreren Platinen problemlos.

von Tobias K. (tobias_k73)


Lesenswert?

H.joachim Seifert schrieb:
> Kontrollier als erstes mal mit einem Scope den clkout-Pin, nach reset
> müssen dort 1MHz anliegen.

Also ich hab mal gemessen. Am clkout Pin liegt keine Frequenz an, der 
Pin ist immer auf 0. Nur etwa eine halbe Sekunde (schätz ich mal) direkt 
nach dem einschalten liegt da eine Frequenz an, die ich aber leider 
nicht genauer bestimmen kann.
Was bedeutet das jetzt? Ist der Chip an sich einfach kaputt?

Thomas Forster schrieb:
> Ich habe den Reset des MCP2515 mit dem Reset des Atmega verbunden. Dazu
> die übliche R und C Resetschaltung. Das funktioniert inzwischen bei
> mehreren Platinen problemlos.

Okay, das probier ich dann einfach auch mal.

von Thomas (kosmos)


Lesenswert?

wenn man 2 IC am dort anschließt würde ich auf jedenfall die Fuses so 
setzen das die Pause zu Beginn etwas größer ist. Wobei ich meine µC 
immer mit der größten Verzögerung starte.

von H.Joachim S. (crazyhorse)


Lesenswert?

Tobias Kohnen schrieb:
> Also ich hab mal gemessen. Am clkout Pin liegt keine Frequenz an, der
> Pin ist immer auf 0. Nur etwa eine halbe Sekunde (schätz ich mal) direkt
> nach dem einschalten liegt da eine Frequenz an, die ich aber leider
> nicht genauer bestimmen kann.
> Was bedeutet das jetzt? Ist der Chip an sich einfach kaputt?

Nö, das ist ganz gut so.
Es bedeutet wahrscheinlich, dass der Oszillator + Stromversorgung 
funktioniert und auch deine SPI-Verbindung. Durch deine Schreiberei in 
den Chip wird dann der clkout abgeschaltet. Da du das gar nicht 
beabsichtigt hast, liegt entweder eine falsche Registeradressierung vor 
oder auch nur eine falsche Initialisierung der SPI-Schnittstelle.
Hier mal eine funktionierende SPI-Init (allerdings Mega88, kann gut 
sein, dass da Unterschiede zu deinem Prozessor sind. Und ja, das könnte 
man lesbarer schreiben, aber wenn es der wizard so funktionsfähig 
erzeugt, lass ich es auch so :-)

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2000,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x50;
SPSR=0x01;

von H.Joachim S. (crazyhorse)


Lesenswert?

nochmal nachgeschaut, passt auch für den 2560.
Ausserdem müssen DDRB.0, DDRB.1 und DDRB.2 als Ausgang gesetzt sein.

von Tobias K. (tobias_k73)


Lesenswert?

H.joachim Seifert schrieb:
> // SPI initialization
> // SPI Type: Master
> // SPI Clock Rate: 2000,000 kHz
> // SPI Clock Phase: Cycle Half
> // SPI Clock Polarity: Low
> // SPI Data Order: MSB First
> SPCR=0x50;
> SPSR=0x01;

Also, ich habe jetzt versucht die SPI Schnittstelle mit sämtlichen 
Kombinationen von Clock Rate, Clock Phase, Clock Polarity und Data Order 
zu initialisieren. Jedesmal mit dem gleichen Ergebnis, dass der MCP2515 
nicht in einen anderen Modus wechselt und ich immer 000 zurück bekomme.

Die Registeradressierung übernimmt die SPI library, die beim Arduino 
schon dabei ist, und die ist auch korrekt.

Hat jetzt noch jemand eine Idee, wo der Fehler liegen könnte?

von Tobias K. (tobias_k73)


Angehängte Dateien:

Lesenswert?

Sooooooo, ich habs geschafft!
Habe jetzt alles mögliche ausprobiert. Letztendlich habe ich ein paar 
Bauteile ausgetauscht und anders dimensioniert. Und, ja, auch den INT 
Ausgang habe ich mir noch zum Controller "gehäkelt", danke für den 
Hinweis Joachim ;-)!

Und jetzt funktioniert es tatsächlich!!! Softwareseitig lag kein Problem 
vor, das war alles von Anfang an richtig.

Vielen Dank nochmal für die Tipps und Ideen von euch!

Bis demnächst!

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.