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.
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.
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.
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
return0;
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
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
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.