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
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;
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
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
naja, so soll es ja auch sein. Aber ohne Schaltung und Software wird dir keiner weiterhelfen können...
Wenn es bei allen funktioniert (9,x MHz), nur bei dir nicht, was sagt dir das?
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?
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.
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); }
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.
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)); }
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
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
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...
1 | //SPI Master Interface aktivieren (Register SPCR, SPSR and SPDR)
|
2 | //Atmega 644 20PU.pdf Seite 161
|
3 | //SPR1, SPR0 = SPI Clock Rate Select
|
4 | //F_CPU = 8MHz -> SPR1=1 SPR0=0 -> F_CPU / 64
|
5 | SPCR = (1<<SPE)|(1<<MSTR) | (1<<SPR1)|(0<<SPR0); |
6 | SPSR = 0; |
7 | |
8 | //PIN MCP2515_CS als Ausgang definieren
|
9 | SET_OUTPUT(MCP2515_CS); |
10 | //SPI-CS auf Hi setzen (Hi=SPI auf Zielkomponente inaktiv)
|
11 | SET(MCP2515_CS); |
12 | |
13 | //PIN P_SCK und P_MOSI als Ausgang definieren
|
14 | SET_OUTPUT(P_SCK); |
15 | SET_OUTPUT(P_MOSI); |
16 | //Rücksetzen der Pins P_SCK und P_MOSI
|
17 | RESET(P_SCK); |
18 | RESET(P_MOSI); |
19 | |
20 | //PIN P_MISO als Eingang definieren
|
21 | SET_INPUT(P_MISO); |
22 | RESET(P_MISO); |
23 | |
24 | //PIN MCP2515_INT als Eingang definieren
|
25 | SET_INPUT(MCP2515_INT); |
26 | SET(MCP2515_INT); |
27 | |
28 | //SPI-CS auf Lo setzen (Lo=SPI auf Zielkomponente aktiv)
|
29 | RESET(MCP2515_CS); |
30 | //MCP 2515 per SPI resetten um ihn in den Konfigurationsmodus zu bringen
|
31 | spi_putc(SPI_RESET); |
32 | //SPI-CS auf Hi setzen (Hi=SPI auf Zielkomponente inaktiv)
|
33 | SET(MCP2515_CS); |
34 | |
35 | //10µs warten bis der Reset vom MCP 2515 durchgeführt wurde >>> 2µs sind minimum
|
36 | //(MCP 2515-I-P.pdf Seite 55)
|
37 | _delay_us(10); |
38 | |
39 | //SPI-CS auf Lo setzen (Lo=SPI auf Zielkomponente aktiv)
|
40 | RESET(MCP2515_CS); |
41 | |
42 | //Die Konfigurationsregister laden (CNF1, CNF2 und CNF3)
|
43 | //(MCP 2515-I-P.pds Seite 57)
|
44 | spi_putc(SPI_WRITE); |
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.
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?
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.