Forum: Compiler & IDEs SPI und MCP2515


von Lukas S. (irre)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich versuche mich zurzeit an einem CAN-Bus MCP2515, welcher über SPI 
angesprochen wird.

Ich möchte die SPI Kommunikation über Interrupts umsetzen. Es scheint 
aber ein Problem zu geben wenn die Interrupts global aktiviert sind, 
dass die MCU (ATmega128 16AU) jedes Mal einen Reset bekommt, wenn ich 
über SPI_MasterTransmitAndReceive(uint8_t) in "spi.h" ein BYTE 
übertragen möchte.
Hab das rausklamüsert: Der Fehler scheint bei der Abfrage zu liegen, ob 
SPIF gesetzt ist.
Ich blick da aber nicht zu 100% durch.
Wenn da jemand Ahnung von hat würd ich mich über ne Hilfestellung 
freuen.

Im Anhang befindet sie die die .c und .h Dateien, sowie 3 Bilder eines 
Logic-Analysers des SPI Interfaces.


LG
irre

edit: der richtige Ordner ist "SPI_und_CAN.zip"

von Stefan E. (sternst)


Lesenswert?

Lukas S. schrieb:
> dass die MCU (ATmega128 16AU) jedes Mal einen Reset bekommt, wenn ich
> über SPI_MasterTransmitAndReceive(uint8_t) in "spi.h" ein BYTE
> übertragen möchte.

Kein Wunder, wenn du den SPI-Interrupt einschaltest, aber gar nicht 
benutzt. Das Interrupt-Flag zu pollen ist etwas ganz anderes als "SPI 
Kommunikation über Interrupts umsetzen".

Darüber hinaus hat dein Code andere No-Gos und Merkwürdigkeiten. Z.B. 
hatte ich erst Schwierigkeiten, den Code überhaupt zu finden, weil er 
nämlich dort, wo er ist, ganz und gar nicht hin gehört, nämlich in 
Header-Files. Code gehört immer in C-Files (mit Ausnahmen, die dich im 
Augenblick aber nicht zu interessieren brauchen). In ein Header-File 
gehört nur das externe Interface. 
http://www.mikrocontroller.net/articles/FAQ#Header_File.2C_wie_geht_das.3F
Und was hat das
1
#define INT7_vect  _VECTOR(8)
in deinem Code zu suchen?

von Lukas S. (irre)


Lesenswert?

zu .h Dateien: hab mich bisher immer gefragt, wofür zusätzlich .c 
Dateien erstellt werden. Hab das eher als lästig empfunden und bisher 
auch noch nie Probleme gehabt.

zu den interrupts: wenn der MCP2515 eine Nachricht erhält, wird ein 
Interrupt über den INT-pin ausgelöst, welcher an meinem ATmega an 
INT7(PE7) angeschlossen ist. Dazu muss dann nur noch eine ISR gefertigt 
werden, welche dann den Buffer auslesen soll, oder nicht?
Das Interrupt-Flag poll ich deswegen, weil es gesetzt wird, wenn die 
Datenübertragung (SPI) abgeschlossen ist. Nur scheint eben da etwas 
nicht zu funktionieren.

von Stefan E. (sternst)


Lesenswert?

Lukas S. schrieb:
> zu den interrupts: wenn der MCP2515 eine Nachricht erhält, wird ein
> Interrupt über den INT-pin ausgelöst, welcher an meinem ATmega an
> INT7(PE7) angeschlossen ist. Dazu muss dann nur noch eine ISR gefertigt
> werden, welche dann den Buffer auslesen soll, oder nicht?

Das erklärt aber in keiner Weise, warum du dich dazu genötigt gefühlt 
hast, dieses Define in deinen Code zu schreiben.

Lukas S. schrieb:
> Das Interrupt-Flag poll ich deswegen, weil es gesetzt wird, wenn die
> Datenübertragung (SPI) abgeschlossen ist. Nur scheint eben da etwas
> nicht zu funktionieren.

Ich schrieb bereits, was nicht funktioniert, nämlich den Interrupt zu 
erlauben, ihn dann aber nicht zu benutzen. Wenn du nur Pollen willst 
(also gar keinen Interrupt haben willst), dann erlaube ihn auch nicht.

von Lukas S. (irre)


Lesenswert?

Stefan Ernst schrieb:
> Das erklärt aber in keiner Weise, warum du dich dazu genötigt gefühlt
> hast, dieses Define in deinen Code zu schreiben.

hab ihn rausgenommen

Stefan Ernst schrieb:
> Ich schrieb bereits, was nicht funktioniert, nämlich den Interrupt zu
> erlauben, ihn dann aber nicht zu benutzen. Wenn du nur Pollen willst
> (also gar keinen Interrupt haben willst), dann erlaube ihn auch nicht.

Wie kommst du darauf, dass ich den Interrupt nicht benutze?
Das SPIF hat nichts mit dem CAN controller zu tun, sondern nur mit dem 
SPI Interface.

Interrupt will ich nur dann benutzen, wenn der MCP2515 einer MCU eine 
neue Nachricht in einem der Buffer hat, und dieser Interrupt wird an 
INT7_vect ausgelöst. den code hab ich doch. und benutzen tue ich ihn 
doch auch. Ich glaub wir reden aneinander vorbei

Code ist folgendermaßen verändert:
1
ISR (INT7_vect)
2
{
3
  :...
4
5
}
und das #define ist weg

von Stefan E. (sternst)


Lesenswert?

Lukas S. schrieb:
> Wie kommst du darauf, dass ich den Interrupt nicht benutze?

Weil du das Flag pollst und keine ISR hast.
Wir reden hier vom SPI-Interrupt!

von Lukas S. (irre)


Lesenswert?

Natürlich hab ich ne ISR.
1
ISR (INT7_vect)
2
{
3
    ...
4
}
Und der INT-pin vom MCP2515 ist an INT7 angeschlossen.

Nein, SPIF soll gepollt werden.
Ich erhalte einen Interrupt, wenn der MCP2515 eine neue Nachricht 
erhählt. Erst dann wird SPI überhaupt in Anspruch genommen und dann darf 
der auch ruhig pollen bis die Nachricht verschickt ist. Ungünstig wäre 
es den MCP2515 stetig zu fragen ob er neue Nachrichten empfangen hat.

Um auf mein Problem zurückzukehren:
Meine MCU bekommt einen Reset wenn ich die Funktion
1
uint8_t SPI_MasterTransmitAndReceive(uint8_t data)
2
{
3
  SPDR=data;
4
  while (!(SPSR&(1<<SPIF)))
5
    ;
6
  
7
  return SPDR;
8
}
aufrufe. Jemand eine Idee warum?

von Stefan E. (sternst)


Lesenswert?

Lukas S. schrieb:
> Natürlich hab ich ne ISR.

Nochmal: wir reden hier vom SPI-Interrupt, NICHT vom INT7-Interrupt.

Du musst mal die Antworten, die du bekommst, ein bisschen sorgfältiger 
lesen. Ich habe schon im ersten Post geschrieben, dass es um den 
SPI-Interrupt geht. Das INT7_vect-Define lief nur unter "Darüber hinaus 
... Merkwürdigkeiten".

von Lukas S. (irre)


Lesenswert?

...vollkommen richtig. hab
1
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPIE);
in
1
SPCR = (1<<SPE)|(1<<MSTR);



das meintest du oder?


jetzt stürzt der zumindest nicht mehr ab, warum ist der denn vorher 
immer resetted?

Danke schonmal.

von Stefan E. (sternst)


Lesenswert?

Lukas S. schrieb:
> jetzt stürzt der zumindest nicht mehr ab, warum ist der denn vorher
> immer resetted?

http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

von Stefan (Gast)


Lesenswert?

Hallo Lukas S.,

was Dir Stefan Ernst - ich bin ein anderer Stefan - sagen wollte, dass 
Du ohne jetzt in Deinen Code zu schauen, das Flag im SPI aktiviert hast 
das einen Interrupt auslöst, wenn eine Transmission beendet wuurde.

Wenn dies der Fall ist, Du aber für diesen Fall keine ISR hast, dann ist 
im gcc standard den Controller zu neu zu starten. Du kannst mal nach 
bad_isr schauen und die in Deinen Code einbauen. Setze einen Breakpoint 
in diese ISR und schaue, ob Du da reinläufst.

Gruß
Stefan

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.