Hallo zusammen, ich habe eine Schaltung zusammen gebaut mit einem ATMEGA32 und einem CAN Controller MCP2515. Schaltung und Code basieren auf den Daten von Kreatives-Chaos.com. Da das dortige Tutorial sehr verbreitet ist, hoffe ich das mir hier jemand helfen kann... Ich hab versucht eine Nachricht zu senden. Dies schlägt allerdings fehl, da die Abfrage, ob die Sendepuffer frei sind, immer ein false zurück liefert. In dem o.g. Tutorial ist auch ein Democode von dem Can Controller zu finden. Auch bei diesem Code tritt der gleiche Fehler auf. Zusätzlich wird in der Initialisierung des Controllers versucht, ein Register auszulesen, welches zuvor beschrieben wurde. Dies schlägt bei mir auch fehl (also das auslesen). Ich habe die Schaltung bereits mehrfach gecheckt und konnte keinen Fehler finden. Auch die SPI Kommunikation scheint zu funktionieren. Aktuell weis ich absolut nicht mehr, wo ich noch suchen soll. Falls jemand eine Idee hat wäre ich wirklich sehr dankbar... Viele Grüße Stefan
Ist der Controller allein im Netz? Wenn ja: Das geht bei CAN nicht, führt zu Dauerfehler mangels Quittierung. In dem Fall solltest du deine ersten Tests im Loopback-Testmodus machen. Wär ohnehin kein Fehler, wenn du dir die Status/Error-Register anschaust. PS: Das setzt natürlich voraus, dass du den MCP überhaupt ansprechen kannst. Dein Text erweckt aber etwas undeutlich den Eindruck, dass der Treiber mit einem Stück Holz redet. Um das also zu klären: Funktioniert der Zugriff auf die Register des MCP? Wenn nicht: Falsch angeschlossen, falsche Pindefinitionen, kein Takt und hundert andere Möglichkeiten.
Hi A.K. danke für deine Nachricht. Ehrlich gesagt bin ich auch etwas verwirrt, weshalb ich in der mcp init ein Register nicht auslesen konnte (als Test). Ich habe mittels Oszilloskop allerdings schonmal geschaut, ob die Pins vom µC während der Datenübertragung mittels SPI richtig geschaltet werden. Das sieht eigentlich ganz gut aus. Werd wohl nochmal versuchen ein anderes Register auszulesen, um zu schauen ob das funktioniert. Ja der Controller ist alleime am Netz. Müsste er nicht im ersten Moment die Nachricht absenden und erst in den Fehlerzustand gehen, wenn er kein Ack bekommen hat ? In dem Democode zum MCP2515 ist am Anfang der Loopback gesetzt und ich hab das gleiche Problem, dass die Sendepuffer nicht freigegeben sind. Viele Grüße Stefan
Stefan schrieb: > Ja der Controller ist alleime am Netz. Müsste er nicht im ersten Moment > die Nachricht absenden und erst in den Fehlerzustand gehen, wenn er kein > Ack bekommen hat ? ja raussenden wird der controller den frame, also mit dem oszilloskop zwischen CANH und CANL wirst du was sehen. der controller wird nur irgendwann in den error modus gehen ohne ack
Welches Register konntest Du nicht verändern? CNF1, CNT2, CNF3, TXRTSCTRL, Filter und Mask-Register lassen sich nur im Konfigurationmodus verändern. Dazu CANTCTRL.REQOP auf 0b100 setzen. Bzw. Bit7 im CANCTRL-Register setzen. Mit Bit 3 (von 0 angefangen zu zählen) kann man den MCP2515 in den One-Shot-Modus bringen. Dann sendet er nur einmal die Botschaft und wartet nicht auf Acknowledge. Dadurch kann man verhindern, dass er zu schnell in den Fehlermodus springt. Wenn das alles nichts hilft. Dann einen Software-reset mit dem SPI-Kommando 0xC0 senden.
Guten Abend zusammen, vielen Dank für die rege Beteiligung. Auf der Seite von kreatives-chaos gibt es ein Demo Package zum MCP2515. Hier wird in der Init nach setzen des Configurationsmodus die Baudrate eingestellt und anschließend versucht, diese zu lesen. Hier bekomme ich aber lediglich ein false zurück
1 | // reset MCP2515 by software reset.
|
2 | // After this he is in configuration mode.
|
3 | RESET(MCP2515_CS); |
4 | spi_putc(SPI_RESET); |
5 | SET(MCP2515_CS); |
6 | |
7 | // wait a little bit until the MCP2515 has restarted
|
8 | _delay_us(10); |
9 | |
10 | // load CNF1..3 Register
|
11 | RESET(MCP2515_CS); |
12 | spi_putc(SPI_WRITE); |
13 | spi_putc(CNF3); |
14 | |
15 | spi_putc((1<<PHSEG21)); // Bitrate 125 kbps at 16 MHz |
16 | spi_putc((1<<BTLMODE)|(1<<PHSEG11)); |
17 | spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0)); //CNF1 |
18 | |
19 | // activate interrupts
|
20 | spi_putc((1<<RX1IE)|(1<<RX0IE)); |
21 | SET(MCP2515_CS); |
22 | |
23 | // test if we could read back the value => is the chip accessible?
|
24 | if (mcp2515_read_register(CNF1) != ((1<<BRP2)|(1<<BRP1)|(1<<BRP0))) { |
25 | return false; |
26 | }
|
Warum das nicht funktioniert, ist mir ein Rätsel. Habe auch gerade versucht manuell ein Bit zu setzen und anschließend auszulesen. Ich kann leider nicht debuggen, sondern habe nur eine LED zum An-/Ausschalten
1 | //... Konfigurationsmodus aktiv...
|
2 | mcp2515_write_register( CNF3, (1<<PHSEG21) ); //Bit 1 |
3 | uint8_t test; |
4 | test = mcp2515_read_register(CNF3); |
5 | |
6 | if (test = 2) |
7 | {
|
8 | PORTA |= (1<<PA0); |
9 | }
|
Das komische ist, vergleiche ich "test" auf 2, leuchtet die LED. 2 ist auch der erwarte Wert. Vergleiche ich auf 0, bleibt die LED aus. Passt also auch. Vergleiche ich aber z.B. auf test=1, ist die LED wieder an, was aber garnicht sein darf, da Bit0 = 0 ist. Versteh ich nicht... ?! Der Vollständigkeit halber noch die Sende- und Empfangsroutinen:
1 | void mcp2515_write_register( uint8_t adress, uint8_t data ) |
2 | {
|
3 | // /CS des MCP2515 auf Low ziehen
|
4 | PORT_CS &= ~(1<<P_CS); |
5 | |
6 | spi_putc(SPI_WRITE); |
7 | spi_putc(adress); |
8 | spi_putc(data); |
9 | |
10 | // /CS Leitung wieder freigeben
|
11 | PORT_CS |= (1<<P_CS); |
12 | }
|
13 | uint8_t mcp2515_read_register(uint8_t adress) |
14 | {
|
15 | uint8_t data; |
16 | |
17 | // /CS des MCP2515 auf Low ziehen
|
18 | PORT_CS &= ~(1<<P_CS); |
19 | |
20 | spi_putc(SPI_READ); |
21 | spi_putc(adress); |
22 | |
23 | data = spi_putc(0xff); |
24 | |
25 | // /CS Leitung wieder freigeben
|
26 | PORT_CS |= (1<<P_CS); |
27 | |
28 | return data; |
29 | }
|
Den CAN-Controller kann man auch im Loopback-Modus (oder so ähnlich) betreiben. Da kann man ihn dann für sich alleine testen, ohne einen weiteren Knoten zu haben.
Wenn Du das selbst Programmiert hast, dann funktioniert das nicht, weil Du das Tripel Komando, Register, Daten nicht einhälst. Stefan schrieb: > // load CNF1..3 Register > > RESET(MCP2515_CS); > > spi_putc(SPI_WRITE); > > spi_putc(CNF3); > > > > spi_putc((1<<PHSEG21)); // Bitrate 125 kbps at 16 MHz > > spi_putc((1<<BTLMODE)|(1<<PHSEG11)); > > spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0)); //CNF1 > > > > // activate interrupts > > spi_putc((1<<RX1IE)|(1<<RX0IE)); > > SET(MCP2515_CS); Vielleicht funktioniert das hier: RESET(MCP2515_CS); /* Kommando 0x02*/ spi_putc(SPI_WRITE); /* Registeradresse */ spi_putc(CNF3); /* Daten für CNF3 */ spi_putc((1<<PHSEG21)); // Bitrate 125 kbps at 16 MHz /* Chip-Select wieder auf 1 -> siehe dazu Fig 11-04*/ /* auf Seite 63 des Datenblattes MCP2515 */ SET(MCP2515_CS); /*Warten ist hier nicht verkehrt*/ _delay_us(10); RESET(MCP2515_CS); /* Kommando 0x02*/ spi_putc(SPI_WRITE); /* Registeradresse */ spi_putc(CNF2); /* Daten für CNF2 */ spi_putc((1<<BTLMODE)|(1<<PHSEG11)); SET(MCP2515_CS); /*Warten ist hier nicht verkehrt*/ _delay_us(10); RESET(MCP2515_CS); /* Kommando 0x02*/ spi_putc(SPI_WRITE); /* Registeradresse */ spi_putc(CNF1); /* Daten für CNF1 */ spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0)); //CNF1 SET(MCP2515_CS); /*Warten ist hier nicht verkehrt*/ _delay_us(10); RESET(MCP2515_CS); /* Kommando 0x02*/ spi_putc(SPI_WRITE); /* Registeradresse */ spi_putc(CANINTE); /* Daten für CANINTE */ spi_putc((1<<RX1IE)|(1<<RX0IE)); //CANINTE1 SET(MCP2515_CS); /*Warten ist hier nicht verkehrt*/ _delay_us(10); HIER MUSST DU GENAUSO DEINE FILTER SETZEN FUER DIE MBX 0 und 1 /*ZUM SCHLUSS KONFIGURATIONMODUS AUF NORMALMODUS UMSCHALTEN !!!*/ RESET(MCP2515_CS); /* Kommando 0x02*/ spi_putc(SPI_WRITE); /* Registeradresse */ spi_putc(CANCTRL); /* Daten für CANCTRL BIt 8 löschen -> Normalmodus /* Bit4 -> OneShotModus */ spi_putc(0x04); //CANCTRL SET(MCP2515_CS); Ab hier dann fröhliches Senden und empfangenn Stefan schrieb: > 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); > > } Hier ist die Reihenfolge richtig. Aber in der Initialisierung wird der Konfigurationmodus nie verlassen. Abgesehen davon, weiss der MCP beim besten Willen nicht, was er mit den Informationen anfangen sollen, wenn man die Reihenfolge Kommando, Register, Daten nicht einhält. Viel Erfolg
Guten Abend, Der erste Teil des Quellcodes stammt aus dem DemoCode. Ich hab ein File angefügt, indem die Funktionen enthalten sind, wie ich sie nutze (Redundants bereits entfernt). Ich habe in der can_send_message Funktion auch einen Vermerkt gemacht, wo bei mir das Problem liegt. Bis auf die Main Funktion stammt der Code ebenfalls von kreatives Chaos. Bisher hab ich aber nur Beiträge im Netz gefunden, dass das so funktioniert. Ich weis nicht mehr weiter -.- Viele Grüße Stefan
Also, das sieht soweit o.k. aus. In meiner Initialisierung habe ich das zuvor beschriebene Register gelesen und mit der Vorgabe verglichen. Erst dann setzt die Initialisierung fort. Ich weiß nicht, ob Du weißt, wo Dein Programm stehen bleibt? Hast Du das mal gescheckt? Wie wird der MCP getaktet? externer Quarz oder von Mikrocontroler? Eine Sache noch: Nach dem Reset (Software) 0xC0 mußt Du mal das CANSTAT lesen und prüfen, ob 0x100x xxxx vorliegt. Erst dann ist der Controler im Konfigurationsmodus. Wenn nicht, dann ist klar, warum er nicht sendet. Er ist dann nicht konfiguriert. Wenn Du keinen Debugger hast, würde ich zunächst auf einen freien Port 8LEDs anschließen und mit jedem Byte ein Zähler inkrementieren, dann weißt Du, wo er hängen bleibt.
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.