Hallo zusammen, ich möchte gerne an einen ATMega32 zwei MCP2515 per SPI anschließen. Ich brauche zur Lösung der Aufgabe 2 CAN-Controller ????!!!!! Auch ein AT90CAN128 und ein MCP2515 wären denkbar. Es soll ein bidirektionaler Datenstrom eingelesen und gefiltert ausgegeben werden. Der CAN arbeitet beidseitig mit 100Kbit. Ist das überhaupt möglich ???? welche Datenrate (Anzahl der Datenrames) ließe sich theoretisch erzielen ??? Gibt es da schon fertige Lösungen im bezahlbaren Rahmen (100-200Eur) oder Layouts Mit der Programmierung in C habe ich bis jetzt nicht viel zu tun gehabt. Würde mich aber bei entsprechenden Beispielen gerne daran versuchen. Gruß Peter
Man könnte natürlich auf den Gedanken verfallen, einen Controller mit 2 internen CAN-Einheiten zu verwenden. Hinsichtlich Durchsatz ist der MCP2515 nicht der ganz grosse Wurf, dafür ist er einfach nicht gebaut. Der ist für einfaches Messaging gebaut, nicht für Massendatentransfer.
Hallo, daran hatte ich auch gedacht !!! es gibt ja welche mit 2 bis z.B. 5 (und mehr) internen Can Controllern nur sind die nur in SMD zubekommen und das könnte ich mit der Dip Varinate vom MCP2515, Mega32 und dem Treiberbaustein 82C250 umgehen. Mir macht die Programmierung in C schon deutlich zuschaffen. Gruß Peter C.
Also ich habe eine Sache laufen mit 2x500kBit-CAN. 2xMCP2515 an ATMega32, Hardware-SPI, ist ziemlich viel traffic drauf, (Motor-CAN) läuft problemlos.
Hallo, ja super, genau sowas suche ich. Wäre es unverschämt nach der Lösung (Schaltplan und Code) zufragen. Ich würde sogar nur 100KBit benötigen. Eine Lösung für Maske/Filter findet sich bestimmt auch. Gruß Peter C.
Peter C schrieb: > Hallo zusammen, > ich möchte gerne an einen ATMega32 zwei MCP2515 per SPI anschließen. Ich > brauche zur Lösung der Aufgabe 2 CAN-Controller ????!!!!! Auch ein > AT90CAN128 und ein MCP2515 wären denkbar. > Es soll ein bidirektionaler Datenstrom eingelesen und gefiltert > ausgegeben werden. Der CAN arbeitet beidseitig mit 100Kbit. > > Ist das überhaupt möglich ???? > welche Datenrate (Anzahl der Datenrames) ließe sich theoretisch erzielen > ??? > Gibt es da schon fertige Lösungen im bezahlbaren Rahmen (100-200Eur) > oder Layouts Es gibt von Olimex das SAM7-LA2 Board: http://www.olimex.com/dev/sam7-ea2.html Der Prozessor dadrauf hat 4 CAN-Ports. Einer ist auf einem Stecker herausgeführt, die anderen sind über eine Stiftleiste verfügbar. Hier müßtest Du noch CAN-Transceiver anschließen, aber das ist einfach. Da hier alles intern ist, solltest Du keine Geschwindigkeitsprobleme haben. Das Board kostet bei Olimex selber 90€.
Hallo, mich würde die Schaltung von Autor: H.joachim Seifert (crazyhorse) schon mehr interessieren. Ich hoffe er meldet sich noch einmal. Gruß Peter C.
Hallo, klasse, sind ja garnicht soviele Bauteile. Programmierst du in C ??????, Ist der Schaltplan mit Eagle oder Target gezeichnet worden ??? Kann ich irgend wie an den Quellcode kommen, muß ja nicht umsonst sein !!?? Welche Funktion übernimmt die Schaltung zwischen Motor und Steuergerät ? mfg. Peter
Quellcode kann ich dir höchstens die Grundfunktionen geben, die Einzelheiten im CAN sind geheim. Das ganze fusst auf den ziemlich genialen Routinen von www.kreatives-chaos.com. Bisschen aufgebohrt auf die 2 CS-Steuersignale. Das ganze dient dazu, ein Motorsteuergerät mit einem Auto zu verheiraten, die eigentlich nicht zusammenpassen/zusammengehören. D.h. alle Botschaften vom Auto und alle vom Motorsteuergerät werden umgebastelt und dann im passenden Format an den jeweils anderen Bus gesendet. Deshalb habe ich auch mit keinerlei Filtern oder Masken gearbeitet, alle ankommenden Botschaften werden auch vom MC empfangen, einsortiert, neu zusammengestellt und im passenden Zeitraster auf der anderen Seite gesendet. Und die Frage nach Eagle bzw. Target überhöre ich jetzt mal, dass bisschen Kram wirst du doch wohl selber schaffen. Die Hauptarbeit liegt eh in der Software.
Hallo, ich dachte mir schon das mehr hinter der Schaltung steckt. Auf den Teil wo die Frames umgearbeitet oder geschlüsselt werden verzichte ich sehr gerne. Auf www.kreatives-chaos.com ist der Umgang mit dem MCP und der lip schon beschrieben nur als "noch " nicht C User ist es allemal schwer die 2. Steuerleitung irgendwie herein zubekommen und da die Sprache von Basic schon deutlich abweicht schwer zum Quadrat. Wenn es sich bei den Grundfunktionen um das bidirektionale senden und empfangen geht kann ich dir garnicht genug danken. Wenn ich das richtig verstehe müßte man den mittleren Teil der deine Anpassung Auto zu Steuergerät macht für meine Zwecke "nur" herausnehmen und schon sollte es laufen. Ja ich glaube ich fantasiere, so leicht ist es sicher nicht. Zur Aufklärung, ich entwerfe kleine Platinen mit Target (Version 400 Pins), vom Enwurf bis zur Fertigung meiner Schaltung habe ich bis heute immer geschafft. Deshalb bevorzuge ich liebend gerne die DIP/DIL Varianten. Also wenn ich die Grundfunktionen nutzen düfte, wäre das ein großer Schritt vorwärts für mich. Gruß Peter
du musst alle Grundroutinen bearbeiten, die direkt auf die SPI zugreifen, mal als Beispiel die mcp2515_read_rx_status: Original: unsigned char mcp2515_read_rx_status(void) {unsigned char data; PORTB &= ~(1<<SPI_CS); // CS low spi_putc(SPI_RX_STATUS); data = spi_putc(0xff); // Die Daten werden noch einmal wiederholt gesendet, // man braucht also nur eins der beiden Bytes auswerten. spi_putc(0xff); PORTB |= (1<<SPI_CS); // CS high return data; } geändert: (mit einer Variablen CAN_sw), die kannst du natürlich auch an die Funktion übergeben, ich benutze sie allerdings als globale Variable, die vor dem Aufruf geschrieben wird, das hat andere Gründe, die hier nichts zur Sache tun) unsigned char mcp2515_read_rx_status(void) {unsigned char data; if (!CAN_sw) PORTB &= ~(1<<SPI_CS1); // CS1 low else PORTB &= ~(1<<SPI_CS2); //CS2 low spi_putc(SPI_RX_STATUS); data = spi_putc(0xff); // Die Daten werden noch einmal wiederholt gesendet, // man braucht also nur eins der beiden Bytes auswerten. spi_putc(0xff); PORTB |= (1<<SPI_CS1 | 1<<SPI_CS2); // beide CS high return data; }
Hallo, das heißt alle Routinen von www.kreatives-chaos.com des MCP2515 Beispieles ????? Ich lese also von 1. MCP ein, speicher ID, DLC und die Datenbytes/RTR in Variablen und gebe sie dann von den Variablen wieder an den SPI des 2. MCP Wenn ich das so sehe ist der Syntax der Sprache C das große Problem. Ob ich das allerdings so hinbekomme !!!!!!! Gruß Peter
der zentrale Punkt für die ganzen Variablen ist folgender: typedef struct { unsigned int id; unsigned char rtr; unsigned char length; unsigned char data[8]; } CANMessage; erzeugt eine Variablenart CANMessage. Nun kann man beliebig viele Variablen (solange der RAM reicht:-) erzeugen. CANMessage rec_can0; //für ISR0 CANMessage rec_can1; //für ISR1 Empfangen wird grundsätzlich im Interrupt: // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { CAN_sw=0; can_get_message(&rec_can0); CAN0_message_received=1; } // External Interrupt 1 service routine interrupt [EXT_INT1] void ext_int1_isr(void) { CAN_sw=1; can_get_message(&rec_can1); CAN1_message_received=1; } Empfangene Botschaften stehen nun in den Variablen, zusätzlich werden die flags CAN0_message_received bzw. CAN1_message_received gesetzt. In der main wird nun anhand dieser flags geprüft, ob was zu tun ist. Wenn ja, anhand der der ID entsprechend reagiert. Da die Interrupts die Variable CAN_sw ohne Rücksicht auf Verluste einfach umschaltet, musst du sicherstellen, dass nicht gerade eine Sendeaktion läuft. Also vor jedem Senden Interrupts sperren, danach wieder freigeben
Hallo, das für mich schlimme ist, ich kann dir so in etwa folgen und weiß was die Controller tun sollen. Ich bekomme nur sprichwörtlich die Kraft, die Information nicht auf den Boden - soll heißen der C Dialekt in Verbindung mit altem Schulenglisch ist für mich das Problem. So suche ich Beispiel/e, die funktionieren und an dehnen ich mich weiter hangeln kann um so auch mehr von C zu verstehen. Deshalb ja meine Frage nach dem Code. Ich habe mehr als nur Verständis das wenn etwas funktioniert man die "Geheimsache" nicht veröffentlicht. Wir kennen uns nicht und so muß man immer mit Spionage, blödes Wort, rechnen. Ich denke ich werde deinen Schaltplan zugrunde legen (ich habe nur kein Jtag) und mal versuchen die Routinen mit einenm MCP und mega8 zum Laufen zubekommen. Wenn das geht, gehen sollte, mit dem zweiten paralell und wenn das auch geht CAN0 und CAN1 mit einander zuverknüpfen. Sollte ich das auch noch hinbekommen müßte der letzte Schritt mit Maske und Filter auch zuschaffen sein. Ich habe auch einen Seite gefunden die mehr zum Thema C zeigt. http://www.c-programme.de/ Gruß Peter
Tja, vielleicht nimmst du dir auch etwas viel vor für den Anfang... CAN neu, C neu, naja. Wenn du Basic kannst, kannst du ja auch versuchen, die Routinen auf Basic umzuschreiben. Oder es gibt was entsprechendes schon fertig, kann ja auch sein. Hier gibts jedenfalls kaum Basic-Leute, und das hat auch seinen Grund (ohne jetzt eine neue Diskussion darüber anleiern zu wollen) JTAG solltest du dir auf jeden Fall zulegen, damit kann man in den MC hineinschauen, ohne wirds deutlich zeitaufwändiger.
Hallo, Da geb ich dir recht, je mehr ich drüber nachdenke. Der Umgang mit dem CAN ist zwar nicht so neu, sitz aber nicht so tief. Mit einem At90CAN habe ich mit Basic schon "etwas" Erfahrung, nur erscheint mir das Schreiben etwas langsam - lesen geht super fix. Ich denke es sollte schneller gehen als nur alle 15-20ms einen Frames senden zu können und da fällt mir ein alter Spruch ein. Nimm C und alle Sorgen sind passe. Wahrscheinlich nur wenn man C drauf hat. Das Schulenglsich kommt auch nur bedingt mit dem technischen Englisch der Datenblätter mit. Ich muß mal schauen. Zunächst werde ich die fehlende Bauteile bei Reichelt bestellen und in der Zwischenzeit kann ich mir die Routinen und den AT90CAn nochmal zu Gemüte führen. Okay Gruß Peter
Hallo crazyhorse, ja ich weiß der Beitrag ist jetzt 14 Monate alt und ich habe mir deinen Rat zu Herzen genommen und wohlt mal kurz Rückmeldung geben. Ich habe mich voll in die CAN Nummer und Basic gehängt. Ich hatte mir eine Lochrasterplatine mit zwei MCP2515 nehmst MCP2551 und da gleicher Sockel wie ein ATMega8 einen ATMega328P aufgebaut. Der hat den Vorteil das er pinkompatibel ist und mehr Ram und Flash hat und zudem ein Freq Ausgang und im max Fall bis 20MHz betrieben werden kann. Der ATMega8 wäre schon für die kleine Bascom Lösung zu klein (flash und Ram) gewesen und so war der ATMega328 schon eine gute Wahl - fand ich. Das Bascom Proggi läuft auch auf beiden CAN mit 100KBit in beide Richtungen. Leider konnte ich für mich die Buffer/Speicheung der Frames nichts lösen und habe aus Geschwindiglkeitsgründen vor 4 Monaten tatsächlich auf C umgestellt. Aus den ehemals böhmischen Dörfern ist mitlerweile eine Nachbargemeinde geworden und so hangel ich mich anhand des Beispieles von kreatives Chaos durch. Nach Umstellung des Programmes auf den ATMega328P hatte ich dann wohl einen Fehler der es erforderte die iom328p zuerweitern. Nach der Anpassung der Bus Frequenz konnte ich dann auch schon was empfangen und am Bildschirm darstellen. Der 328P hat andere Registernamen und so war der Umstieg mit meinem 20 Jahre alten Schulenglsich schon eine Herausforderung. Da in dem Testprogramm ja nicht im Interrupt empfangen wird sondern nach nach Auswertung des Pins im der Main stelle....versuche ich gerade den Empfang in den Interrupt zuverlegen. Nach Einstellung und Angleich an den MCP versuche ichs gerade - da so wie ich vermutet anhand des C-Code du Codevision verwendest sieht das bei AVR Studio ja etwas anders aus. //Interrupt INT1 und INT0 einschalten EIMSK|=(1<<INT1)|(1<<INT0); // INT1 und INT0 einschalten im General Interrupt Control Register // Einstellen auf fallenden Flanke EICRA|=(1<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00); //fallende Flanke löst aus ISR (INT0_vect) { tCAN message; //erzeugt ein Variable nach dem tCan struct mcp2515_get_message(&message); //liest einen Frame vom MCP2515 print_can_message(&message); // ausgabe nur für kurzen Test PRINT("Interrupt ausgelöst\n"); // ausgabe nur für kurzen Test } Ob es funktioniert weiß ich noch nicht es läßt sich zumindest jetzt compelieren. Mein Frage ...warum ich eigentlich den Betrag aufwärme - sollte ich nochmal ein Frage haben ob ich dann nochmal um Rat fragen kann.?? Okay das wars schon......... Gruß Peter
Jaja, mach nur. Erste Anmerkungen - ich hab die Interrupts als low-level laufen. Das hatte auch irgendeinen Grund - weiss ich im Moment nicht, müsste ich nachschauen. Und den print-Kram solltest du schnellstmöglich aus der ISR entsorgen, der gehört da nicht hin. Solange du in der ISR bist, funktioniert ja kein UART-Interrupt.
Hallo, gute Info, das die Uart in der ISR nicht geht wuste ich jetzt nicht. Ich bleib am Ball Schöne Weihanchten
H.joachim Seifert schrieb: > Erste Anmerkungen - ich hab die Interrupts als low-level laufen. Das > hatte auch irgendeinen Grund Hat es. Peripherie-ICs haben meistens mehrere Interruptquellen. Es kann dann sein, daß zufällig eine 2.Quelle getriggert wird und der Interruptpin bleibt low. Du arbeitest die erste ab, verläßt den Interrupt und kriegst nie wieder ne Flanke, Dein IC ist tot. Beim Pegelinterrupt kann das nicht passieren. Peter
Peter C. schrieb: > Der ATMega8 wäre schon für die kleine Bascom Lösung zu klein (flash und > Ram) gewesen Das ist aber schon heftig, ist Bascom wirklich so verschwenderisch? Du solltest versuchen, keinen Spaghetticode zu schreiben. Sobald man ähnliche Aufgaben zweimal oder öfter macht, sollte man eine Unterfunktion dafür schreiben. Dann ist auch die Fehlersuche einfacher, man muß den Fehler nur an einer Stelle berichtigen. Aber auch um verschiedene Aufgaben zu trennen, kann man der besseren Lesbarkeit wegen Unterfunktionen benutzen. Z.B. Funktionen für SPI-IO, CAN-Init, CAN-Senden, CAN-Empfang. Peter
Der UART funktioniert in der ISR schon, nur mit an sicherheit grenzender Wahrscheinlichkeit nicht interruptgesteuert (was ja sonst aus Geschwindigkeits- und Effektivitätsgründen der Fall ist). Das liegt daran, daß in einer ISR aus der AVR-libc als erste Aktion die Interrupts gesperrt werden. Also kann der FIFO-Interrupt im UART zwar schön sein Interruptflag setzen, aber ohne global interrupt enabled passiert da nichts weiter (welches erst als letzte Aktion bei Verlassen der ISR wieder eingeschaltet wird). Erst dann wird der UART-interrupt abgearbeitet. Du kannst natürlich mit sogenannten nested interrupts arbeiten, das wird aber heftigst und sollte wegen der Interruptstruktur beim AVR vermieden werden. Beim Cortex M3 sieht das aber schon anders aus. Peter C. schrieb: > Da in dem Testprogramm ja nicht im Interrupt empfangen > wird sondern nach nach Auswertung des Pins im der Main > stelle....versuche ich gerade den Empfang in den Interrupt zuverlegen. Das vergiß mal am besten ganz schnell wieder. Die ISR soll/muß aus o.g. Grund so kurz wie nur irgend möglich sein, damit keine Überschneidungen passieren. Sowas würde sich dann z.B. in gelegentlich fehlenden Zeichen usw. äußern; auf jeden Fall meist nicht reproduzierbar, da von der aktuellen Belastung des µC abhängig. Selbst wenn es jetzt klappen sollte: Es gibt keine Garantie und spätestens bei Reduzierung der timingresourcen hast du dann irgendwann und irgendwie ein Problem. Und dann wieder die ganze Softwarestruktur ummodeln motiviert nicht gerade. Die Softwarearchitektur muß vor dem ersten Programmfetzen schon ziemlich konkret und logisch feststehen. Und "ISR so kurz wie möglich" ist beim AVR eine unumstößliche Regel. Wie gesagt, spätestens bei Erweiterungen (oder auch späterer simpler Taktreduzierung wegen Stromsparen oder so) holt einen das ein.
Hallo, ich denke das aufgrund der Funktionen und Interpretationen sowie Umsetzung in Bascom der Bascom Code schon größer ist. Es kann auch durchaus sein das bei mir nicht alles super kompakt programmiert ist (learning by dooing usw.....). Vielleicht vermittelt deshalb Bascom einen Hauch von Geschwindigkeitsverlust/nachteil - ohne jetzt den Bascom Nutzer zusehr auf die Füsse zutreten - denn bis vor 4 Monaten habe ich auch damit gearbeitet. Das die ISR möglichst kurz sein soll ist ja klar..Da ich möglichst viel durch den ATMega und die 2 MCPS2515 durchschleusen möchte dacht ich das aufgrund der Darstellung von H.joachim Seifert das ein begehbarer Weg sein kann. Seinen Ausführungen entnahm ich das in seiner Anwendung ein Haufen Frames durchgehen und es super läuft und sogar noch eine Sortierung und weitere Bearbeitung stattfindet. Ich habe rund 15 Frames die in einer Sekunden von CAN 0 zu CAN 1 sollen und zurück sind es ca. 5 Frames. Die kleinste Widerholungszeit sind 100ms - so dachte ich das es funktionieren kann selbst wenn ich mit, vorher Bascom und jetzt C selbst was proboiere. Ich bin kein Hardwarprofi und kein Programmierer und studiert habe ich das auch nicht. An hand meiner Forschungen ist sicher ein 32Bit MC mit min 2 internen Can Controllern und 40MHz die beste Wahl sogar noch mit deutlichen Reserven - nur sind da keine Informationen zu bekommen zumindest nicht für für mich. Ich möchte noch selbst Hand anlegen und was lernen. Selbst wenn ich auch bei der Lösung feststellen muß - es reicht nicht - gehts vielleicht weiter mit einem LPC2129 oder wie auch immer. Erst mal der AVR und die 2 x MCP2515, händelbar als DIL Varianten und dann sehen wir weiter. Gruß Peter PS: Ich bin für jede Hilfe dankbar.
Peter C. schrieb: > An hand meiner Forschungen ist sicher ein 32Bit MC mit min 2 > internen Can Controllern und 40MHz die beste Wahl sogar noch mit > deutlichen Reserven Auch Deine jetzige Konfiguration hat doch deutliche Reserven. Es ist daher effektiver, diese nutzen zu lernen. Das Wissen nutzt einem dann auch auf den großen Boliden. Der Trick beim Programmieren ist eigentlich nur, einen ordentlichen Programmablaufplan zu erstellen. Daran kann man dann viel besser den Flaschenhals erkennen und durch Umstellen beseitigen. Was man mit Worten aufgeschrieben hat, läßt sich dann auch viel leichter in Code umsetzen. Leider programmieren aber viele Anfänger einfach so drauflos, ohne Plan und ohne zu wissen, was sie tun. Und das ergibt dann umständlichen, fehlerträchtigen und langsamen Code. Und dieser Code bleibt dann auch auf einen 64Bit 1GHz Boliden langsam. Peter
Hallo, ja ich weiß was die Schaltung tun soll und kann das auch beschreiben. Nur ist halt die Umsetzung meist nicht so einfach. Ich befasse mich jetzt seit 4 Monaten mit C und kann nicht unbedingt sagen das ich ein Profi bin ich würde eher so den Status kurz nach Anfänger nehmen. Aber ich kann in einem gewissen Umfang den C Code deuten was da passiert oder passieren soll. So habe ich in meiner Schaltung auch schon Fehler in der Software beseitigt die vom org Atmel Studio (io328p) verursacht wurde. Hat zwar gedauert aber mit meinem Schulenlisch habe ichs dann doch gefunden. Also rein beim Empfang und der Darstellung der Frames die ich aus dem Notebook über einen MHS USB CAN Adapter an den MCP2515 schicke ist schon enorm. Selbst wenn ich mit dem MCP2515 empfange und das Eingelesene mit einer um 10 erhöhten ID wieder versende ist der Zeitverzug erst ab ca 8 Frames deutlich zusehen. Bei der Bascom Variante schon ab dem 4. Frame. So bin ich zur Zeit guter Dinge das da noch was geht und ich zur Verbesserung noch einen Puffer irgendiwe dazwischen bekomme. Aber Schritt für Schritt lernen und begreifen, mir hilft es wenn ich erst mal selber schaue und mir das Hirn zermatere. Klappt nicht immer !!!!! Gruß Peter
Du hast dabei auf jeden Fall die richtige Grundeinstellung => verstehen und lernen wollen, nicht blind und doof copy&paste. Auch bei den DIL-Geschichten zu bleiben finde ich hier absolut richtig, da du schnell und problemlos von der Theorie zur Praxis wechseln kannst. Auf Grund der jetzigen "Probleme" wie Treffsicherheit oder Handhabung das Luftgewehr AVR gegen eine Panzerfaust Cortex M3 zu tauschen, wäre der größte Fehler, um die Scheibe in 3 m Entfernung treffen zu wollen ... Die Einarbeitung und Änderung nur wegen des Chips und der Toolchain würde dich vollends demotivieren und du hast dort erstmal ganz andere Probleme, die mit deinen Jetzigen nichts zu tun haben. Wie schon von mehreren Seiten kam: Strukturiertes Arbeiten ist die Basis einer jeden effektiven Tätigkeit. Das schließt das (vorherige) Planen natürlich mit ein. Um eventuell noch ein Mißverständnis auszuräumen: Interrupts sind dazu erfunden worden, um die vorhandenen Resourcen effektiver zu nutzen; dienen quasi der Verteilung von Resourcen, wo sie gerade benötigt werden. So sollte man (spätestens) bei der kleinsten Leistungsanhebung, wie z.B. Nutzung einer zweiten Peripherieeinheit, von z.B. Polling auf Interrupts umsteigen. Innerhalb der ISR sollten aber wirklich nur die absolut zeitkritischen Sachen gemacht werden; die evtl. weitere (weniger zeitkritische) Verarbeitung muß dann an anderer geeigneter Stelle erfolgen. Nur so ist sicherzustellen, daß ein anderer, ebenfalls zeitkritischer Prozeß, seine absolut notwendigste Aufgabe ebenfalls in der erforderlichen Zeit abarbeiten kann. Im übertragenen Sinne bedeutet das, daß beim Receive-Interrupt der Inhalt innerhalb der ISR in z.B. irgendeinen Buffer ausgelesen und der Receive-Buffer danach sofort wieder für den nächsten Frame freigegeben wird (inkl. Rücksetzen von Interrupts/Flags sowie Flags zur Weiterverarbeitung etc.). Ende der ISR. Die Verarbeitung der gerade ausgelesenen Message findet dann also außerhalb der ISR statt; z.B. durch Auswerten des in der ISR gesetzten Weiterverarbeitungs-Flags in der main-loop.
Hallo Lutz, ich danke dir für deine Meinung und ermutigenden Worte. Einen Plan habe ich selbstverständlich: - 2 x MCP2515 an einem ATMega328P - bidiretionaler Datenstrom - Richtung 0 zu 1 = alles durch - Richtung 1 zu 0 = 2 IDs herausfiltern (ID 0x261 und ID 0x263) - Empfangs- Sendebuffer mit einbeziehen - bei freien MC-Resourcen soll bei einer bestimmten ID die Schaltung abgeschaltet werden. Mein Plan und Vorgehensweise - zuvor habe ich mit einem CAN USB Adapter den kompletten Datenstrom mit geschnitten. Ich weiß also das der CAN 100KBit hat, Frames in verschiedenen Längen sowie RTRs dazwischen sind. Es sind insgesamt ca 15-20 Frames die mit unterchiedlichen Zeiten wiederholt werden. Ein paar werden mit 100msec, 200msec, 500msec und ein kleiner Teil mit 800msec / 1000msec versendet. Die Ids konnte ich zu 95 Prozent identifizieren und weiß was für Daten die Frames enthalten. Bauteilanmeldung am CAN Ring usw usw....... In der Testschaltung arbeitet auf einer Seite ein CAN USB mit dem ich per Notebook senden/empfangen kann und die andere Seite bildet ebenfalls ein AT90CAN128 der auch senden/empfangen kann. Meine Schaltung sitzt dann dazwischen und hat eine Verbindung zu einem Standrechner der per RS232 angebunden ist - nur um zusehen was passiert. das Notbook zeigt alle CAN Daten mit Zeitstempel. Ich habe auf einer Lochrasterplatine sowohl 2 x MCP2515 mit ATMega328 sowie auch einen AT90CAN128 mit MCP2515 gebaut. Beides habe ich auf Bascom zum Laufen gebracht mit mäßigem Gechwindigkeitsgewinn. Um C zuerlernen habe ich im Internet nach was brauchbaren erklärten gesucht und die Seite von Kreatives Chaos war der Treffer schlecht hin. So habe ich zunächst das Beispiel auf dem AVR Studio 4 geladen und auf den ATMega328P umgestellt. (das hat schon einige Zeit gedauert da ich auch das Datenblatt einmal umkrempeln mußte und nach der Nadel im Heuhaufen gesucht habe und den Fehler in der Studio eigenen Datei gefunden habe) Nach dem das Beispiel dann fehlerfrei im AVR Studio compelierbar war, war es auch einfacher Teile des Codes zuverstehen. So war der 1. MCP und der ATMega328P schon mal online und als Knoten am CAN instaliert. Da in dem Code der Int0 nicht als Interrupt sondern als PIN in der Main abgefragt wurde - die Main also nur darauf wartet das der PIN gesetzt wird arbeite ich an der Umstellung auf den Interrupt - zur Zeit. Weiter möchte ich dann die Initialsierung des 2. MCP2515 einbauen und den Empfang gleichzeit über beide Seiten darstellen. Dann die empfangen Frames von CAN 0 und CAN 1 in einem Buffer zwischenspeichern und bis dahin wirds sicher noch Monate dauern, überkreuz aus dem Buffer versenden. Wenn das klappt ...........wird sicher noch das Filtern vor dem Buffer erfolgen müssen. Macht ja keinen Sinn was zu speichern was man nicht braucht. so ....das wäre mein Plan. Anregungen oder Tipps nehme ich gerne entgegen..... Gruß Peter
Peter C. schrieb: > Da in dem Code der Int0 nicht als Interrupt sondern als PIN in der Main > abgefragt wurde - die Main also nur darauf wartet das der PIN gesetzt > wird arbeite ich an der Umstellung auf den Interrupt - zur Zeit. Die main läuft also immer durch und schaut gerade in dem Moment, ob der Pin gesetzt ist. Wenn ja, wird die message weiterverarbeitet. => Das wäre schlecht, denn alles was nach der Pinabfrage kommt, geht erst weiter, wenn die vorherige messageverarbeitung zu Ende ist. In der Zeit kann evtl. schon eine weitere message (auch in einem anderen Empfangsregister) überschrieben werden/verloren gehen. Als Lösung "einfach" wie beschrieben den INT aktivieren und in der ISR den buffer auslesen, ein Flag in der main setzen, den INT zurücksetzen und weiter geht das Programm. Insgesamt ist der Code für alles ja schon da; du mußt ihn nur entsprechend auf die ISR und die main aufteilen.
Geht es dabei zufällig um das anzeigen von eigenen Daten im FIS? ID 0x261 und 0x263 würde da passen.
Hallo Lutz, wenn ich den Demo-Code richtig deute läuft die Main sogar nicht mal durch sondern wartet in dieser Endlosschleife auf den Empfang. while (1) { // warten bis wir eine Nachricht empfangen if (mcp2515_check_message()) { PRINT("Nachricht empfangen!\n"); // Lese die Nachricht aus dem Puffern des MCP2515 if (mcp2515_get_message(&message)) { print_can_message(&message); PRINT("\n\n"); //schickt direkt Message + 1 zurück // message.id = message.id +1; // mcp2515_send_message(&message); } else { PRINT("Kann die Nachricht nicht auslesen\n\n"); } } } return 0; } Okay..........also den ISR int0 auf "low Level" damit auch der zweite schnell nachfolgende Interrupt mitbekommen wird und doch besser in der ISR den MCP-Buffer auslesen in Framebuffer speichern und mit flag in der Main weiterverarbeiten. Im Moment stecke ich am Interrupt, nachdem die ISR ausgelöst wurde vermutet ich gehts nicht weiter denn der Interrupt im MCP wird nicht gelöscht. Nach EInschalten liegen am Int0 5V nach Empfang 0V un dkeine Änderung mehr........ //aktivieren des int0 im ATMega328P EIMSK|=(1<<INT0); //fallende Flanke EICRA|=(1<<ISC01); der muß dann wohl auf low Level gem. Datenblatt ATMega328P Seite 73 !!?? schreibt man das so EICRA|=(0<<ISC01); oder so EICRA &= ~(1<<ISC01); In der ISR komme ich mit ISR (INT0_vect) { tCAN message; // def struct variable mcp2515_get_message(&message); // hol den Frame aus dem MCP Buffer noch ohne weiter speichern und flag print_can_message(&message); //nur zum zeigen } da ist auch noch was falsch. Gruß Peter
Ist leider ziemlich schwierig bzw. unmöglich, aus den Codefetzen auf das gewünschte Verhalten bzw. Gesamtverhalten des Programms zu schließen. Zumindest die o.g. while-Schleife macht anscheinend schon etwas sinnvolles (wobei wieder uneingeschränkt Satz 1 zum Tragen kommt). Das
1 | return 0; |
2 | }
|
gehört aber schon nicht mehr zur while-Schleife und wird vermutlich das Ende von main sein. Die Schleife prüft (anscheinend) ständig, ob eine Nachricht empfangen wurde. Wenn nicht wieder zum Schleifenanfang. Wenn ja, wird das (anscheinend) mit PRINT ausgegeben. Dann wird (anscheinend) versucht, die message in eine (vermutliche) struct zu schreiben. Wenn das erfolgreich war, wird die message (anscheinend) ausgegeben und anschließend noch 2 Zeilenumbrüche angefügt. Wenn das nicht erfolgreich war, wird das (anscheinend) mit PRINT ausgegeben. Du mußt beide Chips getrennt sehen: MCP2515: Erstmal mußst du dem MCP2515 "beibringen", welche messages er überhaupt annehmen soll. Das macht er ausschließlich über die Identifier. Dazu gehört auch, in welchem Empfangsbuffer die message landen soll. Und du mußt ihm sagen, wie er eine empfangenen Nachricht nach außen signalisieren soll. Ich glaube, man konnte beim MCP2515 einmal zwischen der Methode "Sammelinterrupt" wählen. Egal was er hat hat, er signalisiert das nur an einem Pin nach außen. Dann müßtest du den MCP2515 durch auslesen von Registern (über die SPI-Schnittstelle) gezielt befragen, was er denn hat. Oder man konfiguriert ihn so, daß er pro Empfangsbuffer einen bestimmten Pin signalisiert. Damit wäre dann nach außen schon klar, welcher Empfangsbuffer ausgelesen werden muß. Das reduziert die erforderliche Kommunikation mit dem MCP2515. ATMegaxx: Hier schließt du die oder den o.g. Pin "Signalpin" des MCP2515 an (je nach dem, ob Sammelinterrupt oder nicht). Den Pin des ATMega mußt du als externen Interrupt einrichten. In der ISR muß dann, je nach gewählter Methode ("Sammelinterrupt oder nicht"), die Befragung des MCP2515 angeschoben werden. *** Hier kommt dann das vorher diskutierte Thema zum Tragen, was in die ISR kommt und was in die while-Schleife gepackt wird. *** Zum Ende der ISR muß auf jeden Fall der Interrupt des ATMega wieder zurückgesetzt werden. Wann der Interrupt des MCP2515 zurückgesetzt wird, hängt wiederum von der gewählten Methode "Sammelinterrupt" ab. Eventuell werden die Interrupts auch durch Auslesen des Empfangsbuffers oder Ausführen der ISR automatisch zurückgesetzt; weiß ich aber nicht mehr, Steht aber natürlich im Datenblatt des MCP2515 und des ATMega. Peter C. schrieb: > schreibt man das so EICRA|=(0<<ISC01); oder so EICRA &= ~(1<<ISC01); Letzteres. Mal dir am besten binär mal beide Schreibweisen auf, dann verstehst du, was da eigentlich gemacht wird. Im ersten Fall verODERst du die Zahl Null, welche vorher um ISC01 Stellen nach links geschoben wurde (ISC01 wird irgendwo, wahrscheinlich in der atmega328io.h so stehen: #define ISC01 1). Wenn an der Stelle vorher eine Eins stand, bleibt sie da auch stehen. Wohl nicht das, was gewünscht ist. Im zweiten Fall verUNDest eine Bitmaske, bei der das gewünschte Bit in der Maske Null ist. Das ergibt auf jeden Fall als Ergebnis Null, egal was vorher da stand. Wohl das, was gewünscht ist. Wie gesagt, am besten mal binar aufschreiben. Jetzt ist aber der Entenbraten fällig!
Hallo Lutz, so anbei der komplette C Code mit allem aus diesem Verzeichnis auch mit der geänderten io328p Der MCP ist so eingestellt das jede empfangener Frames einen Interrupt an dem Sammel-PIN des MCP auslöst und damit am int0/PD.2 des Atmega anliegt. Im Demo Programm wir der PD.2 als PIN genutzt und in der mcp2515_check_message() abgefragt und dann mit mcp2515_get_message(&message) erst der Frame vom MCP geholt. In der While schleife wird bei jeden Durchlauf geprüft ob ein Frame da ist - und so können schon welche verloren gehen oder gegangen sein - speziell gesehen auf das was später mal raus werden soll - hatte ich schon beschrieben. Ich habe die ISR zum int0 angelegt und in der main eingestellt. Um zu sehen ob die ISR tatsächlich auch auslöst mit einem Todesstrafen Print versehen. Dann versucht dort ein Flag zusetzen um diese dann in der Main auzuwerten und das auslesen des MCP anzustoßen. geht aber so nicht,da sind die C Lücken wohl doch noch zugroß. bin für jeden Tipp dankbar Gruß Peter
Nur ganz kurz durch die main geflogen: Laut 7.0 Datasheet MCP2515: When an interrupt occurs, the INT pin is driven low by the MCP2515 and will remain low until the interrupt is cleared by the MCU. => Der MCP setzt den entsprechenden Interruptpin auf low. Du mußt also den ATMega-Interrupt auf einen Flankenwechsel von high nach low einstellen. Gemäß Table 13-2 Datasheet ATMega328P: (1<<ISC01). Der ISC00 muß Null bleiben. Da du erstmal nur mit INT0 testen solltest/kannst/willst, kannst du also einfach erstmal EICRA = (1<<ISC01); schreiben.
Hallo Lutz, ja diese Einstellung funktioniert auch, der Interrupt wird ausgelöst. In der ISR schreibe ich dann einfach eine 1 in meine Flag Variable die ich dann in der Main per Print anzeigen lasse bzw wieder mit 0 überschreibe um zu sehen ob in der nächsten ISR Auslösung wieder eine 1 hereingeschrieben wurde. Da der Int vom MCP ja zwingend per SPI bzw. Bitmodify vom ATMega zurückgesetzt werden muß ist die high -> low Flanke erstmal kein Problem da zu den Tests die Frames nur langsam mit 800mSec wiederholt werden und so Zeit zur Reaktion bleibt. Wenn später deutlich mehr Frames folgen, kann es da nicht passieren, das wenn der Int vom MCP durch den ATMega abgearbeitet / der Frame ausgelesen wird, das dann bereits ein zweiter Frame im MCP angekommen ist und den Int-MCP auf low hält der ATMega dies aber nicht erkennt weil der Int0 "nur" auf den Flankenwechsel High->low reagiert und so ein Frame, vom Atmega unbemerkt, im MCP bleibt. Der ATMega setzt ja auch nur das Register im MCP zurück welches zuvor als meldendes und ausgelesendes identifizerit wurde - oder ???????????? Wurde deshalb weiteroben die "Low Level" Einstellung bevorzugt ???? und so der ATMega immer nach einem angekommenden Frame in den 2 Buffern sucht (Statusabfrage) solange der Int-MCP auf Low bleibt ?????? Ich habe versucht in der main mein ISR Flag abzufragen und so das auslesen des MCP anzustossen - da geht aber noch was in die Hose. Aus Basic kenne ich die Do - Loop Schleife die sich immer wiederholt, stellt die While () ähnliches da ???? Diese Frage traue ich mich als Anfänger garnicht zustellen. Gruß Peter
Hallo Lutz, also so funktioniert es jetzt mit dem setzen des Flag in der ISR und Auswertung in der Main. Direkt nach dem Einlesen schicke ich dén Frames wieder mit ID+10 zurück auf den CAN (sicher nicht schön aber der test heiligt die Mittel - damit es keine Kollisionen und Fehler gibt). So schafft der MCP 50 Frames einzulesen und 50 Frames zuversenden und das in einer Sekunde. Da die Frames mit wie schon geschrieben mit 100 msec, 200 msec usw bis 1000 msec eingehen und auch wieder direkt versendet werden haben die Einzelframes nur eine Verzögerung von 1-2 mSec. Das übersteigt meine künsten Erwartungen - ich bin begeistert. Dann werde ich mich mal an den Buffer wagen........... Achja damit auch der zweite Empfangsbuffer im MCP den Rollover mitspielt habe ich noch das BUKT Bit gesetzt (MCP Seite 27) // turn off filters => receive any message mcp2515_write_register(RXB0CTRL, (1<<RXM1)|(1<<RXM0)|(1<<BUKT)); mcp2515_write_register(RXB1CTRL, (1<<RXM1)|(1<<RXM0)); volatile uint8_t flag; ISR (INT0_vect) { flag = 1; } while (1) { if (flag == 1) { // Lese die Nachricht aus dem Puffern des MCP2515 mcp2515_get_message(&message); // PRINT(" ID : 0x%3x\n", message.id); //nur Test //schickt direkt Message + 1 zurück message.id = message.id +10; // ID + 10 senden auf gleichen CAN mcp2515_send_message(&message); flag = 0; // zurücksetzen des ISR flag } } return 0; }
Peter C. schrieb: > Wenn später deutlich mehr Frames folgen, kann es da nicht passieren, das > wenn der Int vom MCP durch den ATMega abgearbeitet / der Frame > ausgelesen wird, das dann bereits ein zweiter Frame im MCP angekommen > ist und den Int-MCP auf low hält der ATMega dies aber nicht erkennt weil > der Int0 "nur" auf den Flankenwechsel High->low reagiert und so ein > Frame, vom Atmega unbemerkt, im MCP bleibt. Der ATMega setzt ja auch nur > das Register im MCP zurück welches zuvor als meldendes und ausgelesendes > identifizerit wurde - oder ???????????? > Wurde deshalb weiteroben die "Low Level" Einstellung bevorzugt ???? und > so der ATMega immer nach einem angekommenden Frame in den 2 Buffern > sucht (Statusabfrage) solange der Int-MCP auf Low bleibt ?????? Na ja, der MCP2515 läßt sich ja schon den Geschwindigkeitsanforderungen entsprechend nutzen. Grundsätzlich erfüllt er die Spezifikation mit 1 MBit/s, ist aber noch verhältnismäßigig simpel (jede Funktion für sich alleine; das Gesamtzusammenspiel des Chips ist schon deutlich doller. Aber bei wenig Bitrate kommt halt jeder einfach und schnell zu seinem Ziel). Man kann an den Schrauben drehen: - SPI-Takt. Geht bis 10 MHz. Da kann man schon abschätzen, wieviel Bit/s theoretisch gehen. Kommt dann aber auch auf den Overhead an. Wie komme ich schnellstmöglich an meine Informationen? Lese ich dieses oder jenes Register erstmal pauschal aus? Hangel ich mich Schritt für Schritt mit Abfragen an meine Information? Auch unterstützt da das automatische address-increment; man braucht nur weiter die Schnittstelle takten. - Interrupt-Pins. Man kann einen Sammelinterrupt nehmen und o.g. Abfrageorgie praktizieren. Man kann aber auch jeden Empfangsbuffer einzeln per Pin signaliseren lassen. Dann ist schon mal klar, welchen Buffer man auslesen muß und man muß weniger per SPI kommunizieren. - Man kann Rollover als letztes Mittel nutzen. - Generell haben die meisten CAN-Chips mehr Sende- als Empfangsbuffer. Warum nur? - Man kann übelst Takte zählen und schauen, ob es nicht kürzer geht, wenn man den Empfangsbuffer schon in der ISR ausliest. Während der Inhalt per SPI rüber geht, puffert im Zweifelsfalle das MAB, bis der nächste Frame evtl. gültig wird und dann erst in den Empfangsbuffer kopiert wird. Da geht bestimmt noch mehr.
Hallo, Peter So, jetzt schreib ich auch meinen Senf dazu.. :) Ich habe was ähnliches wie Du auch schon mit einem Mega8 gemacht, sogar mit bis zu 4 x 2515. Bei meinen recht nidrigen Bitraten gab's nie Probleme. Wenn ich etwas daraus gelernt habe dann: Lass wenns irgendwie möglich ist die Finger weg von Interrupts (im AVR, die Interrupt-Leitungen von den Controllern machen ggf. schon Sinn. Dein letztes Beispiel klappt genauso gut wenn Du auf den ISR (INT0_vect) komplett verzichtest und in main() statt if (flag == 1) einfach den Portpin abfragst an dem der Interrupt anliegt. Damit vermeidest Du insbesondere die Fehlerquelle (die in Deinem Code noch da ist), dass ein zweiter IRQ kommt noch bevor Du flag = 0 setzt. Wenn Du das unbedingt so machen willst, mach' es jedenfalls in der Zeile unmittelbar nach der Abfrage des flag. Auf KEINEN Fall solltest Du in irgend einem Interrupt eine SPI Kommunikation machen. Die Probleme die Du bekommst wenn ein Interrupt in eine laufende Kommunikation, vielleicht sogar mit einem anderen 2515 hineinkracht, kannst Du damit wirksam vermeiden. Ich verzichte übrigens komplett auf die Interrupt-Leitungen und frage den Buffer-Status nur über SPI ab. Mit einer schnellen SPI und wenn Du beide Empfangsbuffer der 2515 (Rollover Buffer 0 -> Buffer 1) nutzen kannst funktioniert das nach meiner Erfahrung ausgezeichnet ohne das was verloren geht. Ich hoffe ich konnte was konstruktives zu Deinem Projekt beitragen... lg Luigi
Nun ja, das ist in der Tat ein freies Land und da darf natürlich ein Jeder sagen und denken, wie es ihm behagt. Bei sachlichen Themen helfen Fakten da allerdings extrem weiter. Luigi schrieb: > Auf KEINEN Fall solltest Du in irgend einem Interrupt eine SPI > Kommunikation machen. Die Probleme die Du bekommst wenn ein Interrupt in > eine laufende Kommunikation, vielleicht sogar mit einem anderen 2515 > hineinkracht, kannst Du damit wirksam vermeiden. Du kennst die zu Grunde liegende avr-libc schon, ja? #define ISR (vector, attributes ) Introduces an interrupt handler function (interrupt service routine) that runs with global interrupts initially disabled by default with no attributes specified. Jede ISR aus der avr-libc sichert als erstes mal das SREG, dann cli(); und restored als letztes das SREG beim Verlassen wieder. Zumindest war es mal so. Wie kann da jetzt in einer ISR ein Interrupt dazwischenhauen und das von dir beschriebene Verhalten verursachen??? u.A.w.g. P.S.: Bitte zerstöre wegen deiner (wegen Zensur habe ich den Inhalt der Klammer schon selber gelöscht) Erfahrungen einem ernsthaft Lernenden nicht den Lehrweg. Echt nicht persönlich gemeint, aber nur weil du die Interrupts nicht verstanden hast, müssen andere nichts falsches lernen. Und das zuerst gelernte bleibt nun mal am besten hängen ... Aber sollen bitte noch andere ihre Meinung dazu sagen; es kann ja schließlich auch sein, daß ich mich irre.
Hallo zusammen, ich wollte eigentlich nur mitteilen das ich die nächste Stufe in meinem Plan geschafft habe.(mit euren Tipps).... Im Vorfeld habe ich einwenig geforscht um Informationen zum Datendurchsatz und dem Händling zubekommen, auf viel bin ich nicht gestossen mit dem ich zum damaligen Zeitpunkt was hätte anfangen können und ohne Ahnung .....wonach hätte ich fragen sollen. Wie der Anfang des Beitrages ja zeigt bin ich dann vor 14 Monaten dem Tipp von H.joachim Seifert nachgekommen und hatte es zuerst mit Bascom propiert. Mit Bascom habe ich einwenig Erfahrung aber das war gestern.... Sicher bin ich auch auf Ergebnisse gestossen die auf 16/32Bitter MCs basierten oder auch Kauflösungen. Aber ich wollte selbst ran und verstehen was da so abgeht. Vor 4 Monaten habe ich die Bascomlösung geschmiessen und habe mit C begonnen - kein leichter Schritt. Ich habe viel gelesen und habe aufgrund der Dil Varinaten genau diese Chips gewählt. Ich kann die Platine selbst herstellen, ich kann eine Testschaltung selbst aufbauen und so ist auch der Weg ein Teil des Zieles. Meine Elektronikerausbildung ist 25 Jahre her und da spieleten diese Dinge(MCs) noch garkeine Rolle ganz zu schweigen vom Schulenglisch und den Schwierigkeiten mit den Datenblättern und dem technischem Englisch. So bleiben mir sicher Dinge verborgen die andere mit einem Handstreich begreifen und umsetzen können. Ich ich finde es toll, das diese Eure Meinungen hier zusammen kommen und viele Wege aufzeigen wie es gehen kann oder welche Erfahrung jeder Einzelne gemacht hat. Alles geäußerte ist es wert uberdacht und beachtet zu werden. Wie schon gesagt.....geschrieben ich bin für jeden Tipp dankbar. Gruß Peter
Ja, sorry, bin noch nicht dazu gekommen, deine mir geschickten Sourcen durchzusehen. Jahresende ist bei mir immer etwas stressig und zu allem Überfluss habe ich mir einen netten PC-Virus eingefangen. Ist noch nicht geklärt, woher der kam. Aber 4 Rechner komplett neu aufgesetzt....:-( Interrupt ist auf jeden Fall der richtige Weg, lass dich da nicht irre machen. Habe ich ja auch ganz am Anfang geschrieben: wenn du was senden willst, vorher die Ints sperren und anschliessend wieder freigeben, ist ja kein Problem, da du (bzw. dein Programm) weiss, wann es etwas senden willst. Zum Zeitverhalten: Bei mir laufen 2 x 500kbit, mit 11bit ID und i.a. 8 Datenbytes/frame. Das macht 130 bit pro message. 2µs/bit * 130 = 260µs/frame. Um diesen auszulesen oder einen frame zu senden, braucht man ca. 20 SPI-Transfers. Bei 8MHz SPI-Takt/16MHz MC-Takt dauert das gerade mal 20µs. Also, angenommen, beide Busse laufen mit Volldampf (kommt in der Praxis nicht mal annähernd vor), dann hast du alle 130µs einen frame zu lesen/zu senden. Rechnen wir grosszügig mit Interruptaufruf/return 30µs. Macht eine Auslastung von 25% der Prozessorzeit, also eigentlich Langeweile... Kürzere messages verschlechtern diesen Wert etwas, aber niemals bedohlich (SPI-Transfers werden ja auch weniger bei kürzeren messages) Du hast in jedem Fall Zeit genug, alles zu erledigen, was anfällt. Und wenn die CAN-Bus-Rate niedrieger ist, hast du sogar noch deutlich mehr Zeit.
Hallo crazyhorse, okay arbeitet dann deine Schaltung von der Hand in den Mund ???? soll heißen der empfangene Frame wird per Int vom MCP-0 dem Mega auf dem int0 (für Can0) mitgeteilt und der sperrt nur den Int0 (für Can0) holt den Frame aus dem MCP-0 noch in der ISR und überträgt den Frame in den 2. MCP (CAN1) und gibt dann den int0 wieder frei. In der Zeit kommen schon wieder weitere Frames an die dank des low Level ISR auch nicht vergessen werden können ??????? Arbeitest du mit einem Zwischenpuffer der die Framerichtung im Auge behält oder hat deine Variable CAN_sw=1; CAN_sw=0; eine direkte Abarbeitungsrichtung zur Folge ?????? hast du die Umschaltvariable direkt mit in den CAN struct mit eingebaut ???? oder separiert. Wenn ein Zwischenspeicher voller wird und die Versendung nicht so schnell hinterher kommt könnte natürlich auch ein Speicherüberlauf vorkommen !!!!!!????? Wie gesagt vor 14 Monaten habe ich noch nicht gecheckt was da so geht....heute nach 4 Monaten ("C") bin ich deutlich weiter wenn auch noch lange lange nicht auf dem Level. Auf meinem CAN sind es 2 x 100KBit mit Datenframes mit unterschiedlicher Länge und das reicht von 8byte und einer Wiederholungsrate von 1000msec bis hin zu einem Datenbyte mit 100msec. Eine Wiederholungsrate die kürzer als 100msec ist, ist nicht dabei. Würde ein Mitschnitt des Datentransfer für die fachliche Beurteilung helfen können ??? Gruß Peter
Hallo nochmal Peter! Hallo, Lutz! Scheinbar habe ich mich da etwas unglücklich ausgedrückt, jedenfalls schlecht genug um von Lutz gleich in die Spinner-Ecke gestellt zu werden... (: Ich hoffe dass ich die Interrupts ganz gut verstehe, danke dennoch für die Belehrung. Der Punkt auf den ich hinauswollte ist der, dass es Probleme geben kann, wenn Du sowohl aus einer ISR als auch aus dem main() Kontext die SPI Schnittstelle ansteuerst. Nimm an Du startest eine SPI Kommunikation aus main() und diese wird von einer ISR unterbrochen. Wenn Du in der ISR ebenfalls SPI machst, wird die ursprüngliche Kommunikation gestört, das passiert natürlich auch dann wenn 2 unterschiedliche Geräte angesteuert werden, da ja CS von der Original-Kommunikation noch gesetzt ist. Das Ergebnis ist dann leider ziemlich unvorhersehbar. Natürlich kann man das über Flags synchronisieren, aber was macht man in der ISR wenn man draufkommt dass man grad kein SPI machen kann..? Noch ein kurzes Wort zu H.joachims "Interrupt ist auf jeden Fall der richtige Weg": Jetzt fange ich auch ein bisschen rechnen an... Du hast also 260µs pro Frame. Mit einem hohen Anteil an Remote-Frames kommt man etwas tiefer, vielleicht 200µs. Das Abfragen des Empfangs-Register-Status über SPI dauert ungefähr 2 µs also 1/100tel davon. Bei 2 x 2515 also ca. 4 µs. Wenn Du laufend, während nichts anderes zu tun ist, die Statusregister der 2515 abfragst, kannst Du also innerhalb von 4 µs auf einen eingegangenen Frame reagieren. Wenn man dasselbe mit Interrupts macht, kann man das vielleicht auf 1 µs drücken. Keinesfalls kann es passieren, dass deswegen ein Frame verloren geht. Außerdem hat man eine laufende Prüfung (die ich gerne verwende) ob der 2515 noch korrekt ansprechbar ist. Bitte beachte dass ich nicht sagen möchte dass die Verwendung der Interrupts jedenfalls sinnlos ist, es geht nur i.A. auch ohne, so dass man sich in vielen Fällen die zusätzlichen Leitungen sowie die Port-Pins sparen kann. So, jetzt will ich Euch Experten nicht länger davon abhalten, andere Poster zu zerreissen und wechsle wieder in die englischsprachlichen Foren. Irgendwie scheint es dort eine positivere Grundstimmung gegenüber Laien die Interrupts nicht verstehen zu geben... lg Luigi
Moin Peter. ich habe noch etliche weitere Buffer drin CANMessage motor0_rec[6]; CANMessage motor0_trans[10]; CANMessage motor1_rec[10]; CANMessage motor1_trans[9]; In die Receivebuffer wird erstmal alles nur anhand der ID einsortiert dann, die Daten umgerechnet/umsortiert und entsprechenden Felder der Transmitbuffer geschrieben, welche dann im passenden Zeitraster wieder gesendet werden. Das brauchst du aber alles gar nicht, da du gar nicht kreuz und quer alles verwursten musst. Ich weiss im Moment gar nicht mehr genau, wo dein eigentliches Problem liegt, der trööt ist mir zu lang geworden, nochmal alles durchzulesen... Wie ist im Moment deine Hardware? 1 oder 2 MCP2515? Hast du eine garantiert funktionierende Gegenstelle (z.B. CAN/USB Adapter oder irgendein DevBoard, mit dem du die CAN-Daten anzeigen kannst?) Fang an mit einem, empfange im Interrupt und sende es zurück mit geänderter ID. Vorausgesetzt, dein Empfang funktioniert, ist das Programm trivial: CANMessage rec_can0, transmit_can0; while (1) {if (CAN0_message_received) {#asm ("cli") CAN0_message_received=0; transmit_can0=rec_can0; transmit_can0.id=transmit_can0.id+1; CAN_sw=0; can_send_message (&transmit_can0); #asm ("sei") } } Kann man kürzer schreiben, und man sollte auch nicht blind irgendwelche IDs (transmit_can0.id+1) auf einen realen Bus werfen. Für nen Testbetrieb an deinem eigenen System geht das natürlich. Und mit 2 MCP2515 sieht das auch nicht viel anders aus: CANMessage rec_can0, transmit_can0, rec_can1, transmit_can1; while (1) {if (CAN0_message_received) //CAN0 empfangen? {#asm ("cli") CAN0_message_received=0; transmit_can1=rec_can0; CAN_sw=1; //SPI für MCP2515_1 can_send_message (&transmit_can1); #asm ("sei") } if (CAN1_message_received) //CAN1 empfangen? {#asm ("cli") CAN1_message_received=0; transmit_can0=rec_can1; CAN_sw=0; //SPI für MCP2515_0 can_send_message (&transmit_can0); #asm ("sei") } } Sendet also alles empfangene auf dem anderen Bus und behandelt erst mal nur die reinen Datenframes.
Hallo, also mein ursprüngliches Problem vor 14 Monaten war das ich einen CAN zu CAN Router bauen wollte und das ohne Plan mit wenig CAN Kenntnissen und mehr Bascom Erfahrung...................Nach 10 Monaten also vor 4 Monaten habe ich zwar einen CAN zu CAN Router mit Bascom und 2 x MCP2515 und Atmega328P sowie mit AT90CAN128 und einem MCP2515 realisiert aber das war nicht mit dem Datendurchsatz zu vergleichen was jetzt mit C und dem MCP und dem ATMega328P schon geht. 4 Monate intensives lernen und probieren haben mich einen deutlichen Schritt an den CAN und große Schritte näher an C gebracht. Hardware: Notebook mit CAN USB von MHS, Lochrasterplatine (SPI Leitungen noch nicht optimal) mit 2 x MCP2515 und ATMega328P und noch einen AT90CAN128 (langsames lesen/schreiben= Bascom) sowie RS232 Anzeigemöglichkeit auf dem Stand PC auf dem auch AVR Studio ist. Von der Seite her kann ich 2 CAN Strecken ausbauen wo sich in der Mitte die Platine mit den 2 x MCP und der ATMega befindet - so kann ich den Durchsatz ansatzweise testen. Um beide MCP mit dem Atmega zu nutzen muß ich dann aber noch die Initialisierung auf beide bringen, ich muß mir noch mal dein Beispiel ansehen wie ich die CS Pins in die Grundfunktionen einbringen muß - ohne dem gehen ja nicht beide. Ich schau aber erstmal ob ichs selbst hinbekommen - dann bleibt es besser kleben Danke..... Gruß Peter
Also Initialierung: CAN_sw=0; mcp2515_init(0x00,0xb8,0x05); //CAN0 500kbit,100kBit natürlich anders :-) CAN_sw=1; mcp2515_init(0x00,0xb8,0x05); //CAN1 500kbit // Global enable interrupts #asm("sei") while (1) { . . } und das hier: if (!CAN_sw) PORTB &= ~(1<<SPI_CS1); // CS1 low else PORTB &= ~(1<<SPI_CS2); //CS2 low . . . PORTB |= (1<<SPI_CS1 | 1<<SPI_CS2); // beide CS high steckt in: - mcp2515_read_register - mcp2515_write_register - mcp2515_write_register_f - mcp2515_bit_modify - mcp2515_read_rx_status - mcp2515_init - can_get_message - can_send_message also überall da, wo im Origninal vorkommt PORTB &= ~(1<<SPI_CS); // CS low ersetzen durch if (!CAN_sw) PORTB &= ~(1<<SPI_CS1); // CS1 low else PORTB &= ~(1<<SPI_CS2); //CS2 low und PORTB |= (1<<SPI_CS); // CS high ersetzen durch PORTB |= (1<<SPI_CS1 | 1<<SPI_CS2); // beide CS high das ist alles. Blöde Frage am Rande: liegen deine /CS überhaupt beide an PortB?
Luigi schrieb: > Scheinbar habe ich mich da etwas unglücklich ausgedrückt, hat ja jetzt aber gut geklappt. > jedenfalls schlecht genug um von Lutz gleich in die > Spinner-Ecke gestellt zu werden... (: Ach was! Nich gleich Pippi in die Augen kriegen. Luigi schrieb: > Der Punkt auf den ich hinauswollte ist der, dass es Probleme geben kann, > wenn Du sowohl aus einer ISR als auch aus dem main() Kontext die SPI > Schnittstelle ansteuerst. > Nimm an Du startest eine SPI Kommunikation aus main() und diese wird von > einer ISR unterbrochen. Das Grundproblem bzw. die Grundlösung ist aber die Gleiche wie beim vorherigen Mißverständnis: Wenn ich etwas im Programm habe, was nicht unterbrochen werden darf, muß ich diese Unterbrechung eben verhindern! In der ISR macht die avr-libc das schon von alleine (weil eine ISR hier niemals unterbrochen werden sollte), an anderen Stellen muß es der Programmierer halt selber machen (da er ja als einziger diese Stellen kennt). In diesem Falle z.B. in jeder SPI-Funktion als erstes SREG sichern, cli(), machen, was zu machen ist und als letztes wieder das SREG restoren. Wobei hier beim MCP2515 wohl außer der Initialisierung am Anfang eigentlich nur noch Interrupts als "SPI-Trigger" in Frage kommen dürften. Kann aber allgemein in anderen Fällen ganz anders sein; hast du recht. Rumgerechnet habe ich nun nicht ... Luigi schrieb: > Bitte beachte dass ich nicht sagen möchte dass die Verwendung der > Interrupts jedenfalls sinnlos ist, es geht nur i.A. auch ohne, so dass > man sich in vielen Fällen die zusätzlichen Leitungen sowie die Port-Pins > sparen kann. Steht außer Frage. Zumal der Interrupt sicher nicht das Erste auf der Welt war. Nur hatte ich weiter oben schon argumentiert, daß 1.) ein Anfänger als erstes lernen sollte, wie es "richtig" ist. Wenn er später Erfahrung hat, kann er selber Abschätzen und daraufhin entscheiden, wie er es im konkreten Einzelfall macht. 2.) bei Programmerweiterungen aus Performancegründen sehr schnell ein komplettes Redesign der Softwarestruktur erforderlich werden kann, was man sich dann hätte sparen können. Klar kann man auch erst Bascom lernen ... War jetzt fies, ich weiß. Aber bestimmt verständlich (was ich inhaltlich meine).
Hallo H.joachim Seifert, die ISR mit der MCP-Abfrage drin läuft, den Teil der CAN Routinen aus der Demo habe ich schon zum Teil angepasst hier muß ich aber mehr tun da hier auch der/die CSs sowie die SPI Initialisierung drin ist. Aber auch in der Funktion sieht es etwas anders aus Da muß ich mal sehen ob ich da *rec_can0 über eine Variable einschleusen/übergeben kann so das auch *rec_can1 übergeben werden kann(siehe unten...), man könnte natürlich die Funktion doppelt schreiben und dann anpassen aber das finde ich jetzt schon Mist..........und ich möchte auch keinen ünötigen Flashspeicher verschwenden. Achja die CS liegen beide auf PortB einmal PB1 und PB2 Die CAN_Sw macht mit noch zuschaffen da ich nochmal nach der "globalen Variable" schauen muß wie die angelegt wird, so meckert das AVR Studio noch - da will ich aber erst selbst ran. So ist auch die schreibweise Codevision zum AVR Studio für mich schon unterschiedlich. Aber ich sehe Licht am Ende des Tunnels und es ist nicht die Eisenbahn......Spaß beiseite - ich will damit sagen das ich begeistert bei der Sache bin.. @Lutz, >Klar kann man auch erst Bascom lernen ... >War jetzt fies, ich weiß. Aber bestimmt verständlich (was ich inhaltlich > meine). Nee..... ist nicht fies wenn man weiß wie man da hingekommen ist. Vor Jahr und Tag habe ich mit den C-Control Dingern von Conrad angefangen, die waren recht schnell am Ende den die Ansprüche stiegen. Dann kam die open C-Control, da ging schon etwas mehr und die waren günstiger. Aber auch von den Preisen wurde man ruckzuck von den Beinen geholt und so war der dritte Schritt Atmel AVR und als Basic geschädigter war Bascom das nahliegenste. Nur mit CAN anlein wäre mit Bascom nicht Schluß gewesen doch wo es jetzt um hardwarenahe Programmierung geht und daraus resultierend um Geschwindigkeit ist C für mich "die" Wahl. Wenn mir das einer vor Jahren gesagt hätte, hätte ich den noch ausgelacht. Allerdings muß ich heute sagen - gut das ich umgestiegen bin. uint8_t mcp2515_get_message(CANMessage *rec_can0) { // read status uint8_t status = mcp2515_read_status(SPI_RX_STATUS); uint8_t addr; if (bit_is_set(status,6)) { // message in buffer 0 addr = SPI_READ_RX; } else if (bit_is_set(status,7)) { // message in buffer 1 addr = SPI_READ_RX | 0x04; } else { // Error: no message available return 0; } RESET(MCP2515_CS_0); spi_putc(addr); // read id rec_can0->id = (uint16_t) spi_putc(0xff) << 3; rec_can0->id |= spi_putc(0xff) >> 5; spi_putc(0xff); spi_putc(0xff); // read DLC uint8_t length = spi_putc(0xff) & 0x0f; rec_can0->header.length = length; rec_can0->header.rtr = (bit_is_set(status, 3)) ? 1 : 0; // read data for (uint8_t i=0;i<length;i++) { rec_can0->data[i] = spi_putc(0xff); } SET(MCP2515_CS_0); // clear interrupt flag if (bit_is_set(status, 6)) { mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0); } else { mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0); } return (status & 0x07) + 1; } // ------------------------------------------------------------------------ ----
Hallo zusammen, zunächst wünsche ich allen ein glückliches und gesundes neues Jahr 2012. Direkt an dieser Stelle möchte ich mich für die kompetente Hilfsbereitschaft speziell bei - H.joachim Seifert - Lutz - Peter Dannegger bedanken. Ohne die richtigen Initialzündungen eurerseits hätte ich das als "C Anfänger" nicht hinbekommen. Die Schaltung empfängt nun bidirektional die CAN-Frames zwischen der o.g. Demohardware und versendet auch entsprechend der eingestellten CAN_SW Variable. Damit habe ich mit eurer Hilfe schon einen großen Teil meines Planes erreichen können. Die Bearbeitungsgeschwindigkeit ist schon klasse. >Einen Plan habe ich selbstverständlich: >- 2 x MCP2515 an einem ATMega328P >- bidiretionaler Datenstrom >- Richtung 0 zu 1 = alles durch >- Richtung 1 zu 0 = 2 IDs herausfiltern (ID 0x261 und ID 0x263) >- Empfangs- Sendebuffer mit einbeziehen >- bei freien MC-Resourcen soll bei einer bestimmten ID die Schaltung >abgeschaltet werden. Die Einstellung der Empfangs Masken und Filter im MCP sollte ich auch noch hinbekommen obwohl mich die Datenfilterung im AVR direkt brennender interessiert da ich nur einzelne IDs herausfiltern will und nicht den Rest um die 0x261 und 0x263 herum definieren will. DANKE !!!!! Gruß Peter
CANMessage rec_can0, transmit_can0, rec_can1, transmit_can1; while (1) {if (CAN0_message_received) //CAN0 empfangen? {#asm ("cli") CAN0_message_received=0; CAN_sw=1; //SPI für MCP2515_1 can_send_message (&rec_can0); //alle unverändert senden #asm ("sei") } if (CAN1_message_received) //CAN1 empfangen? {#asm ("cli") CAN1_message_received=0; switch (rec_can1.id) {case 0x261: { //tu hier was du mit 0x261 machen willst break; } case 0x263: { //dto mit 0x263 break; } default: {transmit_can0=rec_can1; //alle anderen senden CAN_sw=0; //SPI für MCP2515_0 can_send_message (&transmit_can0); break; } } #asm ("sei") } } ist natürlich nur ein Grundgerüst. Funktioniert auch, wenn du keine remote- oder errorframes hast. Ansonsten fand ich deine Beharrlichkeit schon beeindruckend, findet man nicht mehr allzuhäufig heute. Was sich nicht mit KlickiBunti zusammenschieben lässt, ist eh alles Mist....
Hallo H.joachim vielen dank für die Blumen. Sicher gibt es Lösungen die man per copy und paste übernehmen kann, allerdings stellt sich dies meinst als Griff ins Klo dar sobald man einen Fehler hat der entweder beim portieren oder sogar an der Hardware selbst liegt - also in der Regel eigene Schuld ist. Mir lag und liegt immer noch viel daran zu verstehen was da passiert und auch passieren soll. Nur so bin ich in der Lage auch als Anfänger Fehler zu finden und zu beseitigen oder wenn das nicht klappt die Fehler zubeschreiben und mit Tipps dem Fehler auf die Pelle rücken zukönnen. Was ich auf jeden Fall gelernt habe das es für die Umsetzung immer verschieden Ansätze gibt und man auch seinen Weg finden muß. Die Case select Lösung werde ich mal für mich beleuchten und mal sehen ob so für mich lösbar ist. Bei der Schaltung bzw dem Durchschleusen habe ich einige wenige RTRs drin...... ich muß mal sehen. Sobald ich die Demo- in die Probehardwareplatine umgesetzt habe werde ich einen Probelauf in der Zielhardware starten. Tausend Dank Gruß Peter
Hallo erstmal, ich würde gerne ein ähnliches System aufbauen und dabei aber mehr MCP2515 an einen AVR anbinden, als es INT-Pins gibt. Das heißt am Beispiel ATmega16, gleich 3 MCP2515 oder mehr. Gibt es da eine Möglichkeit, das zu realisieren oder bin ich nur am träumen. Ich hab im Tutorial etwas über ein SPI Kommando gelesen als Alternative zur Interruptleitung, stimmt das? Allgemein zum MCP2515 steht im Datenblatt ein Puffer von 2 oder 3 Nachrichten. Kann ich diesen als abrufbaren Zwischenspeicher von Nachrichten nutzen, die noch nich zum AVR weitergeleitet wurden? Der Experte liest sich gleich raus, das ich meine ersten wackligen Schritte auf der CAN-Bus Leitung mache, und deshalb kann ich jede Hilfe brauchen. Gruß Tobi
Hi, nochmal ich, ist ein Interrupt Controller eine Möglichkeit? Könnte man mit dem Interrupt Controller die verschiedenen MCP2515 Interrupts koordinieren?
Tobi Jay schrieb: > ich würde gerne ein ähnliches System aufbauen und dabei aber mehr > MCP2515 an einen AVR anbinden, als es INT-Pins gibt. Auf den moderneren AVRs hast du massenhaft "int-Pins". Schau dir mal die 8er-Familie (48/88/168/328) genauer an: Nebst den klassischen INT0 und INT1 Interrupts gibt es auch die PCINTx, welche zwar über einen gemeinsamen Interrupt feuern, aber leicht auseinander gehalten werden können. Siehe Kapitel 11.3 im atmega..8 Datenblatt (alternate port functions). Tobi Jay schrieb: > ist ein Interrupt Controller eine Möglichkeit? Nicht nötig, s.o.
> Auf den moderneren AVRs hast du massenhaft "int-Pins". Schau dir mal die > 8er-Familie (48/88/168/328) genauer an: Nebst den klassischen INT0 und > INT1 Interrupts gibt es auch die PCINTx, welche zwar über einen > gemeinsamen Interrupt feuern, aber leicht auseinander gehalten werden > können. Was verstehst Du unter "PCINTs leicht auseinander halten"? Ein Flag pro Pin, welches man in der ISR abfragen könnte, habe ich nicht gefunden. Was mir auch nicht klar ist, ob die ISR tatsächlich für jeden PCINT extra 1x aufgerufen wird (und nicht dass z. B. bei mehreren gleichzeitigen PCINTs diese nur 1x angesprungen wird).
Roland H. schrieb: > Was verstehst Du unter "PCINTs leicht auseinander halten"? Nun, der MCP läßt ja ohne eine Aktion den Interruptpin für ewig auf low. Also einfach den Pin abfragen, ob der MCP daran einen Interrupt hat. Peter
> Nun, der MCP läßt ja ohne eine Aktion den Interruptpin für ewig auf low. > Also einfach den Pin abfragen, ob der MCP daran einen Interrupt hat. Die Frage war allgemein zum PCINT gemeint. D. h. einfach bezieht sich auf "einfach Pin abfragen". Bleiben die Frage, ob zeitgleiche "pin changes" in einem ISR-Aufruf landen, oder ob er einen puffert (solange die ISR noch verarbeitet wird), und ob ggf. weitere verloren gehen.
Der Pin-Change Interrupt hat nur ein Flag. Man muß also im Handler alle aktivierten Eingänge prüfen und bearbeiten. Und man kann die Flanke nicht auswählen. Man kriegt also direkt danach noch einen Dummy-Interrupt, wo alle Eingänge high sind. Man kann aber auch am Ende des Handlers das Flag löschen. Man muß dann aber nochmal prüfen ob gerade in diesem Moment ein Eingang wieder low geworden ist, denn diesen hätte man dann mit gelöscht und er ginge verloren. Peter
Schau Dir das mal an: http://www.kreatives-chaos.com/artikel/sja1000-testboard Hier wird ein Mega162 und ein SJA1000 CAN-Controller verwendet. Du kannst mehrere SJA1000 anschließen und musst nur das !CS-Signal für jeden einzelnen SJA aus den oberen Adressleitungen ausdekodieren, z.B. mit einem 74HC138
1 | HC138 |
2 | --------------+ |
3 | A8---------+1 16+---VCC |
4 | A9---------+2 15+---!CS1 |
5 | A10--------+3 14+---!CS2 |
6 | A15--------+4 13+---!CS3 |
7 | A14--------+5 12+---!CS4 |
8 | VCC--------+6 11+---!CS5 |
9 | !CS8-------+7 10+---!CS6 |
10 | GND--------+8 9+---!CS7 |
11 | +-------------+ |
Die anderen Leitungen zum AVR kannst Du alle parallel schalten, auch die IRQ-Leitung. Die Interrupt-Routine muss dann eben nur alle SJAs abfragen, ob irgendwo ein Interrupt ausgelöst wurde, und den dann bearbeiten. Da die SJA1000-Register hier aber direkt im Adressraum des Prozessors liegen und wie RAM-Adressen direkt auslesbar und beschreibbar sind, ist das kein so großer Overhead. Das machen andere auch so, und in früheren Zeiten (z.B. C64) war diese Methode gängige Praxis. In dem Link wird ein Mega162 benutzt. Wenn Dir die Pins knapp werden (und die Chancen stehen nicht schlecht), dann kannst Du auf einen Mega641 oder 1281 ausweichen. fchk PS: Die beiden Quarze ersetzt Du am Besten durch einen 16 MHz Quarzoszillator, der dann Prozessor und die SJA1000 taktet. fchk
Ich probiere mich mich auch gerade daran, eine Kombination aus ATmega328P und MCP2515 mit der canlib von kreatives-chaos.com zum Laufen zu bekommen. Das ist mein erstes wirkliches Projekt mit einem µC und dementsprechen groß sind die Anlaufschwierigkeiten. Ich wäre dankbar für einen Tipp, an welchen Stellen ich die canlib vor dem Kompilieren überall verändern muss, damit ich mit dem ATmega328P statt des ATmega8 arbeiten kann. Dazu verwende ich einen 8MHz Quarz, dafür muss ich wohl auch die Bittimings ändern. Dafür fehlt mir leider auch der Ansatz. Vielen Dank im Voraus!
Eben WEIL du eine Anfänger bist, solltest du solche Modifikationen vorerst lassen. Baue es 1:1 auf. Atmege8 und 16 MHz Quarz. Wenn das läuft sehen wir weiter.
Die Entscheidung über die zu verwendende Hardware liegt leider nicht in meiner Macht. Das Projekt ist so angesetzt und muss zuende geführt werden. Daher meine Bitte um Denkanstöße!
Tja, dann muss es halt sein. >Ich wäre dankbar für einen Tipp, an welchen Stellen ich die canlib vor >dem Kompilieren überall verändern muss, damit ich mit dem ATmega328P >statt des ATmega8 arbeiten kann. Einfach Controller im Projekt umstellen und schauen was beim Compilieren passiert. Wenn man Glück hat, gibt es keine Fehler, wenn nicht, muss man Registernamen und Bitdefinitionen anpassen. >Dazu verwende ich einen 8MHz Quarz, dafür muss ich wohl auch die >Bittimings ändern. Das ist der leichtere Teil, einfach neu ausrechnen. Hab ich auch mal mit dem gleichen Projekt vom kreativen Kaos gemacht. defaults.h
1 | // 125kbit/s @ 10 MHz XCLK
|
2 | //#define CAN_BAUD_DIV ((1<<BRP2))
|
3 | |
4 | // 125kbit/s @ 16 MHz XCLK
|
5 | #define CAN_BAUD_DIV ((1<<BRP2)|(1<<BRP1)|(1<<BRP0))
|
Ins Datenblatt schauen und die Rechung nachvollziehen. MFG Falk
Hmm, jetz wo ich es sehe, hab ich damals auch den ATmega328 genutzt ;-) Die Umstellung war nicht sonderlich schwer, obwohl ich ein paar Pins verschoben habe.
Hallo, sorry dass ich das hier nochmal nach oben ziehe, aber aus welchen Grund sind denn die Ausgänge von IC6 und IC2 auf der Zeichnung von H.Joachim Seifert negiert? Ist es außerdem denkbar, statt zwei MCP2551 nur einen MCP2551 und zusätzlich noch einen TJA1055 (Lowspeed CAN) zu verwenden? Kann dieser Analog zum MCP2551 angeschlossen werden, oder wird zusätzliches benötigt? Der TJA1055 hat ja noch einige Pins mehr... VG!
Florian schrieb: > aber aus welchen Grund > sind denn die Ausgänge von IC6 und IC2 auf der Zeichnung von H.Joachim > Seifert negiert? /INT und /CS? Das sind einfach nur low-aktive Eingänge und meiner Meinung nach so etwas seltsam gezeichnet. Florian schrieb: > Ist es außerdem denkbar, statt zwei MCP2551 nur einen MCP2551 und > zusätzlich noch einen TJA1055 (Lowspeed CAN) zu verwenden? Klar geht das, nur wird der TJA1055 eben anders verschaltet was Du ja auch schon erkannt hast. Die zusätzlichen Pins kann man auch nicht einfach weglassen. Etwas hässlich habe ich das gerade aus einem EAGLE Design gezogen mit dem TJA1054, die drei Pins 4,5 und 6 gehen dabei an I/O Pins vom Controller. Der wichtigste Unterschied ist die Wakeup-Funktionalität die ich in dem Design aber nicht benutzt habe.
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.