Hallo! Ich moechte mithilfe eines ATMega128 und eines MPC2510 einen CAN-Bus abhoeren und abh. von den eintreffenden Nachrichten die Ausgaenge steuern. Das bedeutet, ich muss CAN-Nachrichten lesen koennen... Ich habe auch schon im Netz gestoebert und mit den gefundenen Beitraegen versucht mir ein Programm zusammmen zu basteln, aber so ganz klar ist mir das ganze noch nicht, vor allem das Einlesen der CAN-Nachrichten /**************************** importierte Header-Files **********************/ #include <mega128.h> #include <stdio.h> #include <delay.h> #include <mcp2510.h> #define MISO 3 //ist Eingang #define MOSI 2 //ist Ausgang #define SCK 1 //ist Ausgang #define SS 0 //ist Ausgang //SPI Control Register SPCR #define SPIE 7 #define SPE 6 #define DORD 5 #define MSTR 4 #define CPOL 3 #define CPHA 2 #define SPR1 1 #define SPR0 0 //SPI Status Register SPSR #define SPIF 7 #define WCOL 6 /**************************** Funktionsdeklarationen *************************/ void init_SPI (void); void configure_mcp (void); void reset_mcp (void); void write_mcp (unsigned char adress, unsigned char value); unsigned char read_mcp(unsigned char adress); //Initialisierung des Serial Peripheral Interfaces void init_SPI (void) { DDRB = (1<<MOSI) | (1<< SCK) | (1<<SS); //MOSI, SCK, SS als Ausgang (-> DDRB=0x07) PORTB |= (1<<SS); //Pull-up an SS (mcp disable) (PORTB.0=1); SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0); // SPI Controll Register (-> SPCR=0x51) //| (1<<SPIE); Interruptfreigabe } void reset_mcp (void) { PORTB &= ~(1<<SS); //CS auf LOW setzen, SPI Übertragung einleiten (-> PORTB.0=0) SPCR=RESET_MCP; //Reset Instruction senden (0xC0) while (!(SPSR && 0x80)); while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) PORTB |= (1<<SS); //CS auf HIGH setzen, Übertragung beendet (-> PORTB.0=1) } void configure_mcp (void) { reset_mcp(); //mcp in den Grundzustand setzen write_mcp(CANCTRL, 0x85); //Configuration Mode, CLKOUT enable, System Clock/2 write_mcp(CNF1, 0x05); //CNF1, CNF2, CNF3 legen 83,3 kbaud @ 8 MHz fest write_mcp(CNF2, 0x90); write_mcp(CNF3, 0x02); write_mcp(CANCTRL, 0x45); //Loopback Mode, CLKOUT enable, System Clock/2 } //Beschreiben der MPC-Register void write_mcp (unsigned char adress, unsigned char value) { PORTB &= ~(1<<SS); //CS auf LOW setzen, SPI Übertragung einleiten (-> PORTB.0=0) SPCR=WRITE_MCP; //Write Instruction senden (0x02) while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) SPDR=adress; //Addresse senden while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) SPDR=value; //Wert senden while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) PORTB |= (1<<SS); //CS auf HIGH setzen, Übertragung beendet (-> PORTB.0=1) } //Auslesen der MPC-Register unsigned char read_mcp(unsigned char adress) { unsigned char spidata; PORTB &= ~(1<<SS); //CS auf LOW setzen, SPI Übertragung einleiten (-> PORTB.0=0) SPCR=READ_MCP; //Read Instruciotn senden (0x03) while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) SPDR=adress; //Addresse senden while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) SPDR=0xAA; //Dummy-Byte senden while (!(SPSR && (1<<SPIF))); //warten bis BYTE (SPIF-Flag gesetzt) gesendet wurde (Ende Übertragung) spidata=SPDR; //Daten aus SPI abholen PORTB |= (1<<SS); //CS auf HIGH setzen, Übertragung beendet (-> PORTB.0=1) return (spidata); } /**************************** Hauptprogramm **********************************/ int main( void ) { DDRC=0x0F; //C.0, C.1, C.2, C.3 sind Eingang, C.4, C.5, C.6, C.7 sind Ausgang DDRB=0x0F; //B.0, B.1, B.2, B.3 sind Eingang, B.4, B.5, B.6, B.7 sind Ausgang init_SPI(); while(1) { } } Folgende Punkte sind fuer mich noch vollkommen unklar: * Wie kann ich die (richtigen) CAN-Nachrichte empfangen??? Wie frage ich den Identifier ab? * Was ist besser: Polling oder Interrupt?? und wie werden diese generiert?? * sind CNF1, 2 und 3 richtig festgelegt??? * Wofuer benoetigt der MCP einen eigenen Quarz, wo er doch die Taktleitung des Mega128s hat? Wie man leicht merken kann, ist die Verwirrung noch recht gross, daher bin ich sehr dankbar, wenn mir der ein oder andere einen Tipp geben kann um ein bisschen Licht in die Dunkelheit zu bringen! Herzlichen Dank und viele Gruesse LARA
http://www.mikrocontroller.net/forum/list-1-1.html?filter=mcp2510 Vielleicht hilft dir das. Deinen Code habe ich mir nicht angeguckt.
habe auch keine Lust, mich durchzuquälen. MCP2510 kenne ich nicht, ist der kompatibel zum 2515? Folgende Punkte sind fuer mich noch vollkommen unklar: * Wie kann ich die (richtigen) CAN-Nachrichte empfangen??? Wie frage ich den Identifier ab? Dabei gibts 2 Strategien. Einmal kannst du das Akzeptanz-Filter im MCP programmieren, du erhälst also überhaupt nur die Botschaften, die dieses Filter passieren können. Der Rest verschwindet im Nirwana. Vorteil: du brauchst nicht jede empfangene Botschaft auszulesen und zu interpretieren. Ansonsten: alles empfangen und die gewünschten Identifier selbst ausfiltern. in der Art: if (CAN0_message_received) {CAN0_message_received=0; #asm ("cli") switch (message1.id) { case 0x280: {Heizung[0]=message1; process_heizung1(); break; } case 0x289: {Heizung[1]=message1; process_heizung2(); break; } case 0x298: {Heizung[2]=message1; process_heizung3(); break; } default: break; } //end switch } #asm ("sei") Der Empfang erfolgt im Interrupt und wird in den struct CANMessage geschrieben (besteht aus int id, char rtr, char length und data[8]. Anhand von .id wird entschieden, was passieren soll. Botschaften, die zwar vom CAN-Controller kommen, aber nicht in obiger switch-Anweisung verarbeitet werden, werden mit der nächsten Nachricht überschrieben. * Was ist besser: Polling oder Interrupt?? und wie werden diese generiert?? Auf jeden Fall Interrupt. Das Interruptsignal erzeugt der CAN-Controller, in der ISR werden dann alle rel. Daten gelesen und das Interruptflag des CAN-Controllers gelöscht. * sind CNF1, 2 und 3 richtig festgelegt??? Bei Microchip gibts ein schönes Programm, welches dir alle Einstellungen berechnet. * Wofuer benoetigt der MCP einen eigenen Quarz, wo er doch die Taktleitung des Mega128s hat? Er benötigt keinen eigenen Quarz, aber einen eigenen Takt. Mit Taktleitung meinst du sicher die der SPI? Das funktioniert natürlich nicht. Ich setz meist den Quarz an den MCP, dessen (programmierbarer) clk_out versorgt dann den AVR. Manchmal ist es aber nötig, getrennte Quarze einzusetzen, wenn z.B. auf dem MC auch UART-Kommunikation höherer Baudrate läuft. Dann bekommt der MC einen Baudratenquartz, der CAN einen für CAN passenden.
Hallo nochmals! Ehrlich gesagt, verstehe ich es immernoch nicht. Ich habe folgende Funktionen (die ich auch soweit verstehe und die in dem Quellcode oben umgesetzt sind) generiert: *void init_SPI (void) *void reset_mcp (void) *void configure_mcp (void) *void write_mcp (unsigned char adress, unsigned char value) *unsigned char read_mcp (unsigned char adress) Wie kann ich nun diese verwenden, um die Nachrichten ueber die SPI die Nachrichten an den Controller zu schicken? @Crazy Horse: leider ist mir nicht so klar, wie ich das sw-befehlsmaessig umsetzen soll... warum machst Du "CAN0_message_received=0"?? Mir fehlt total der Ansatz fuers Hauptprogramm! Danke nochmals allen, die mich vorm Verzweifeln retten ;-) Gruss LARA
CAN0_message_received ist nur ein flag (bit), welches dem Hauptprogramm anzeigt, dass eine Botschaft auf dem CAN0 (stammt aus einem Gerät mit 3 CAN-Controllern) angekommen ist. Eh wir das jetzt alles Schritt für Schritt durchkauen, empfehle ich dir folgende Seite: http://www.kreatives-chaos.com/ Wenn du es dann prinzipiell verstanden hast, können wir gerne über Einzelheiten weiterreden.
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.