www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI Problem mit MCP2515


Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einige Module mit einem Mega8 und MCP2515 gebaut. Allerdings 
funktioniert die Kommunikation nur mit 125kbit/s (auf dem SPI).
Ich habe den Mega8 mit dem internen RC Oszillator auf 8MHz laufen, der 
MCP2515 hat einen 16 MHz Quarz.
Wenn ich nun den SPI Teiler auf 64 stelle funktioniert alles, aber 
sobald ich auf /32 gehe kann ich keine Register im MCP2515 mehr lesen.
Aufgebaut ist es auf verschiedenen Platinen (geätzt und Lochstreifen). 
Das SCK Signal sieht bei 250 kHz genauso sauber aus wie bei 125kHz (MOSI 
auch). Laut Datenblatt kann der SPI vom MCP2515 bis 10 MHz (125kHz wären 
ja auch nicht wirklich sinnvoll, wenn er CAN mit 1MBit/s machen soll :) 
)

Hat jmd ne Idee woran das liegen kann? Muss man evtl. den SPI am Mega 
noch anders konfigurieren?

Vielen Dank schonmal
Gruß Philipp

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe den MCP2515 in einigen Applikationen drin.
Im zeitkritischsten Fall (2x500kBit-CAN) läuft der Mega32 mit 16MHz, die 
SPI mit 8MHz. Übrigens völlig problemlos.

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

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, so hab ich meinen SPI auch konfiguriert (bis auf die Teiler, da hab 
ich schon alles Mögliche probiert).
Wenigstens weiß ich nun, dass es so passen sollte.

Vielen Dank
Gruß Philipp

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und was machst du mit dem CS?

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
CS hab ich auf 1 und bevor ich schreibe/lese ziehe ich CS auf 0 und am 
Ende wieder hoch. Wie gesagt bis 125kHz SPI Takt funzt es auch nur 
darüber nicht mehr

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja, so soll es ja auch sein. Aber ohne Schaltung und Software wird dir 
keiner weiterhelfen können...

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es bei allen funktioniert (9,x MHz), nur bei dir nicht, was sagt 
dir das?

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was sollte mir das sagen Andreas? Das es bis 10MHz gehen sollte hab ich 
bereits oben erwähnt, aber trotzdem vielen Dank für Deinen überaus 
hilfreichen Beitrag...

@crazy horse: Also die Schaltung besteht nur aus Mega8 und MCP2515 am 
CAN. CS vom MCP2515 ist an PB2 (das ist /SS am Mega8 sollte aber denke 
ich kein Problem sein, weil es als Ausgang konfiguriert ist), der Rest 
ist halt am HW SPI.

Die Software ist nach dem Beispiel von kijon:

void spi_init(void)
{
  DDR_SPI   |= (1<<P_SCK)|(1<<P_MOSI);
  PORT_SPI &= ~((1<<P_SCK)|(1<<P_MOSI)|(1<<P_MISO));
  DDR_CS   |= (1<<P_CS);
  PORT_CS  |= (1<<P_CS);
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1); //SPR1 gesetzt für clk/32
  SPSR = (1<<SPI2X);
}

uint8_t spi_putc( uint8_t data )
{
  SPDR = data;
  while( !( SPSR & (1<<SPIF) ) );
  return SPDR;
}

void mcp2515_write_register( uint8_t adress, uint8_t data )
{
  // /CS des MCP2515 auf Low ziehen
  PORT_CS &= ~(1<<P_CS);

  spi_putc(SPI_WRITE);
  spi_putc(adress);
  spi_putc(data);

  // /CS Leitung wieder freigeben
  PORT_CS |= (1<<P_CS);
}

uint8_t mcp2515_read_register(uint8_t adress)
{
  uint8_t data;
  PORT_CS &= ~(1<<P_CS);

  spi_putc(SPI_READ);
  spi_putc(adress);

  data = spi_putc(0xff);

  PORT_CS |= (1<<P_CS);
  return data;
}

Nach dem Einschalten mache ich einen Software Reset. Was daran etwas 
komisch ist, dass es bis zu einem bestimmten Takt funktioniert oder ist 
da evtl. ein Fehler der aus irgendwelchen Gründen bei kleinen Frequenzen 
nicht zum Tragen kommt?

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tja, das deckt sich im wesentlichen mit dem, was ich verwende.
Die Funktion read_register habe ich allerdings nie verwendet (und auch 
noch keine Verwendung dafür gehabt), da kann ich dir also nicht sagen, 
ob die so auch so funktioniert.
Ich benutze nur get_message (welche wiederum nur 
mcp2515_read_rx_status() benutzt), send_message, bit_modify und init.

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe eben mal die init routine auskommentiert und nur einfach den 
Soft Reset gesendet dann funktioniert es. Das Problem scheint also da zu 
liegen.

void mcp2515_init(void)
{
  // SPI Interface initialisieren
  spi_init();

  // MCP2515 per Software Reset zurücksetzten,
  // danach ist der MCP2515 im Configuration Mode
  PORTB &= ~(1<<SPI_CS);
  spi_putc( SPI_RESET );
  PORTB |= (1<<SPI_CS);

  // BRP = 7 für 125 kbit/s
  mcp2515_write_register( CNF1, (1<<BRP0)|(1<<BRP1)|(1<<BRP2) );

  // Prop Seg und Phase Seg1 einstellen
  mcp2515_write_register( CNF2, (1<<BTLMODE)|(1<<PHSEG11) );

  // Wake-up Filter deaktivieren, Phase Seg2 einstelen
  mcp2515_write_register( CNF3, (1<<PHSEG21) );

  // Aktivieren der Rx Buffer Interrupts
  mcp2515_write_register( CANINTE, (1<<RX1IE)|(1<<RX0IE) );

  // Buffer 0 : Empfangen aller Nachrichten
  mcp2515_write_register( RXB0CTRL, (1<<RXM1)|(1<<RXM0) );

  // Buffer 1 : Empfangen aller Nachrichten
  mcp2515_write_register( RXB1CTRL, (1<<RXM1)|(1<<RXM0) );

  // Alle Bits der Empfangsmaske löschen,
  // damit werden alle Nachrichten empfangen
  mcp2515_write_register( RXM0SIDH, 0 );
  mcp2515_write_register( RXM0SIDL, 0 );
  mcp2515_write_register( RXM0EID8, 0 );
  mcp2515_write_register( RXM0EID0, 0 );

  mcp2515_write_register( RXM1SIDH, 0 );
  mcp2515_write_register( RXM1SIDL, 0 );
  mcp2515_write_register( RXM1EID8, 0 );
  mcp2515_write_register( RXM1EID0, 0 );

  // Device zurück in den normalen Modus versetzten
  mcp2515_bit_modify( CANCTRL, 0xE0, 0);
}

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tip für Initialisierung von Ports, muss aber nicht für das Problem 
relevant sein: immer erst die Daten setzen, dann die Richtung. Obiger 
Code sorgt beispielsweise dafür, dass CS kurz aktiv ist, weil der Pin 
erst als Ausgang aktiviert, dann auf 1 gesetzt wird.

Apropos CS: externer Pullup empfohlen, damit inaktiv wenn der µC noch 
nicht initialisiert ist.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe ich jetzt keine Lust, das einzeln durchzuklamüsern.
Hier "meine" init, die funktioniert.
Nicht von CAN_sw verunsichern lassen, dass kommt nur davon, dass 2 
MCP2515 an der SPI hängen.

//|========================== MCP2515 Initialisation 
==========================|
void mcp2515_init(unsigned char CNF1_val, unsigned char CNF2_val, 
unsigned char CNF3_val)
{
  if (!CAN_sw)  PORTB &= ~(1<<SPI_CS1);    // CS low
      else PORTB &= ~(1<<SPI_CS2);     //|------------- MCP2515 per 
Software Reset zurücksetzten -----------|
  spi_putc( SPI_RESET );
  PORTB |= (1<<SPI_CS1 | 1<<SPI_CS2);      // CS high


//|---------- Device in den Konfigurations Modus versetzten ---------|
//|-------------------- CLKOUT Pin deaktivieren ---------------------|
   mcp2515_bit_modify( CANCTRL, 0xE0, (1<<REQOP2) );


//|------------------- Einstellen des Bit Timings -------------------|


// 10kbit @16MHz
   //prescaler
   mcp2515_write_register( CNF1, CNF1_val); //0x1f);

   // Prop Seg und Phase Seg1 einstellen
   mcp2515_write_register( CNF2, CNF2_val); //0xbf );

   // Phase Seg2 einstelen
   mcp2515_write_register( CNF3, CNF3_val); //0x07 );


//|-------------- Einstellen der Rx Buffer Interrupts ---------------|
   mcp2515_write_register( CANINTE, (1<<RX1IE)|(1<<RX0IE) );


//|--------------------- Buffer Operating Mode ----------------------|
   // Buffer 0 : Empfangen aller Nachrichten, Infos Datasheet S.27
   mcp2515_write_register( RXB0CTRL, (1<<RXM1)|(1<<RXM0) );

   // Buffer 1 : Empfangen aller Nachrichten, Infos Datasheet S.28
   mcp2515_write_register( RXB1CTRL, (1<<RXM1)|(1<<RXM0) );


// Alle Bits der Empfangsmaske löschen,
  // damit werden alle Nachrichten empfangen
  mcp2515_write_register( RXM0SIDH, 0 );
  mcp2515_write_register( RXM0SIDL, 0 );
  mcp2515_write_register( RXM0EID8, 0 );
  mcp2515_write_register( RXM0EID0, 0 );

  mcp2515_write_register( RXM1SIDH, 0 );
  mcp2515_write_register( RXM1SIDL, 0 );
  mcp2515_write_register( RXM1EID8, 0 );
  mcp2515_write_register( RXM1EID0, 0 );

// Deaktivieren der Pins RXnBF Pins ( High Impedance State )
  mcp2515_write_register( BFPCTRL, 0 );

  // TXnRTS Bits als Inputs schalten
  mcp2515_write_register( TXRTSCTRL, 0 );


//|--------- Device zurück in den normalen Modus versetzten ---------|
//mcp2515_bit_modify( CANCTRL, 0xE0, 0);
//|--------- Device zurück in den listen-Modus versetzten ---------|
//CLK_OUT on, prescaler 1
// mcp2515_bit_modify( CANCTRL, 0xE7, (1<<REQOP1 | 1<<REQOP0|1<<CLKEN));
//|--------- Device zurück in den normalen Modus versetzten ---------|
//CLK_OUT on, prescaler 1
mcp2515_bit_modify( CANCTRL, 0xE7, (1<<CLKEN));
}

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank, ich werde das mal vergleichen.
Auch das mit dem Pullup werde ich mal probieren. Das es im Master 
Betrieb Probleme mit dem /SS Pin geben kann hab ich im Datenblatt leider 
erst gelesen, als es schon verdrahtet war.

Vielen Dank für Eure Hilfe
und gute Nacht

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was hängt denn an SS dran?

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Am SS hängt CS vom MCP2515 ist aber als Ausgang konfiguriert und auf 
high, wenn der Mega8 nicht mit dem MCP redet.

Ich habe eben mal in meine Init nach dem SoftReset eine kleine Wartezeit 
eingebaut (hab einfach mit 4k8 was auf dem uart ausgeben) und nun 
scheint es zu gehen? Bei crazy horse ist ja allerdings keine Wartezeit 
nach dem Reset.

Edit: Es ist reproduzierbar:

PORTB &= ~(1<<SPI_CS);
spi_putc( SPI_RESET );
PORTB |= (1<<SPI_CS);

SendStr("bischen warten....");

mcp2515_write_register( CNF1, (1<<BRP0)|(1<<BRP1)|(1<<BRP2) );
...

Nehme ich das "bischen warten" wieder raus funktioniert es nicht mehr

Autor: Markus B. (wolframator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

seit ich den CKDIV8 von meinem 644 "ausgeschaltet" habe und statt mit 
1MHz mit 8MHz alles laufen lasse hab ich einige Probleme mit dem SPI... 
Das Interessante ist das es mal geht und mal geht es nicht. Was ja in 
der digitalen Welt schon seltsam ist :/

Ab der Zeile "spi_putc(SPI_WRITE);" bleibt alles stehen. :( Ich hab kein 
Plan warum...
//SPI Master Interface aktivieren (Register SPCR, SPSR and SPDR)
//Atmega 644 20PU.pdf Seite 161
//SPR1, SPR0 = SPI Clock Rate Select
//F_CPU =  8MHz -> SPR1=1 SPR0=0 -> F_CPU /  64
SPCR = (1<<SPE)|(1<<MSTR) | (1<<SPR1)|(0<<SPR0);
SPSR = 0;

//PIN MCP2515_CS als Ausgang definieren
SET_OUTPUT(MCP2515_CS);
//SPI-CS auf Hi setzen (Hi=SPI auf Zielkomponente inaktiv)
SET(MCP2515_CS);

//PIN P_SCK und P_MOSI als Ausgang definieren
SET_OUTPUT(P_SCK);
SET_OUTPUT(P_MOSI);
//Rücksetzen der Pins P_SCK und P_MOSI
RESET(P_SCK);
RESET(P_MOSI);

//PIN P_MISO als Eingang definieren
SET_INPUT(P_MISO);
RESET(P_MISO);

//PIN MCP2515_INT als Eingang definieren
SET_INPUT(MCP2515_INT);
SET(MCP2515_INT);

//SPI-CS auf Lo setzen (Lo=SPI auf Zielkomponente aktiv)
RESET(MCP2515_CS);
//MCP 2515 per SPI resetten um ihn in den Konfigurationsmodus zu bringen
spi_putc(SPI_RESET);
//SPI-CS auf Hi setzen (Hi=SPI auf Zielkomponente inaktiv)
SET(MCP2515_CS);

//10µs warten bis der Reset vom MCP 2515 durchgeführt wurde >>> 2µs sind minimum
//(MCP 2515-I-P.pdf Seite 55)
_delay_us(10);

//SPI-CS auf Lo setzen (Lo=SPI auf Zielkomponente aktiv)
RESET(MCP2515_CS);

//Die Konfigurationsregister laden (CNF1, CNF2 und CNF3)
//(MCP 2515-I-P.pds Seite 57)
spi_putc(SPI_WRITE);

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein PC scheint an dieser Zeile auch zu verzweifeln. Oder wie ist es zu 
verstehen, dass der Quelltext genau da endet und auch sonst reichlich 
unvollständig ist (lies: zur Analyse unbrauchbar).

Und weil das bis auf den Chip nichts mit diesem Thread zu tun hat: Mach 
einen neuen Thread auf.

Autor: Markus B. (wolframator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Egal was nach der letzten Zeile von mir kommt wird nicht mehr 
ausgeführt... Und wie man hier im Thread sehen kann hängt es an der 
gleichen Stelle auch bei anderen. Warum sollte mein Problem denn ein 
anderes sein?

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies dir mal im Datasheet das Kapitel über den SS-Pin im Master-Betrieb 
durch. Und dann überleg, was passieren kann, wenn zuerst MSTR=1 und 
danach erst SS=Output programmiert wird.

Autor: Markus B. (wolframator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arg, sch****... Man sollte sein Quellcode natürlich nicht kaputt 
optimieren. Hatte das in unterschiedlichen Funktionen stehen und hatte 
das heute zusammengeführt und die Reihenfolge wohl vertauscht... Thx! 
Geht jetzt wieder wie bisher :) Dachte schon das würde an der Umstellung 
der Geschwindigkeit liegen. selbst-paddel

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.