Hallo, ihr seid meine letzte Hoffnung. Und zwar benützte ich wie oben angegeben einen Atmel AT90CAN128. Es werden 3 CAN Nachrichten über einen interrupt eingelesen. So weit so gut. Mein Problem: Alles funktioniert so lange die Nachrichten nur sporadisch kommen. Sobald die Daten aber mit einer Zykluszeit von ca. 30ms gesendet bzw. empfangen werden bleibt der yC hängen. Heißt es werden keine Daten mehr empfangen. Beim debugen kommt der Fehler nicht vor, heißt, Programm läuft, Daten werden empfangen und verarbeitet. Erste Hilfe meinerseits war über den Watchdog den yC immer wieder zurück zu setzen wenn keine Daten mehr empfangen werden, dies funktioniert nur zum Teil! Wenn der yC sich resetet oder ich die Platine von Hand neustartet tritt zum teil der exakt selbe Fehler direkt wieder auf! Was ich allerdings beobachtet habe, häufig nur wenn auch zum selben Zeitpunkt (beim start) auch Daten auf dem CAN-Bus versendet werden. Komisch ist auch noch, dass eine Nachricht noch eingelesen wird und zwei nicht mehr. Nun meine Frage: Woran kann das liegen? :-( Besitzt der Atmel einen internen Buffer welcher direkt voll ist bevor die Daten verarbeitet werden können? Kann ich diesen löschen? Kann ich auch nur jeden zweiten Interrupt auslösen? Achso, während meinen Berechnungen deaktiviere ich den Interrupt. Hoffe Ihr könnt mir helfen. Bin echt am verzweifeln da mit dem yC am Donnerstag Tests geplannt sind und wenn ich das Problem bis dahin nicht gefunden bzw. gelöst hab alles ins Wasser fällt :-( Hoffe meine Erklärung war nicht ganz verwirrend :-) Vielen Dank schon mal. Gruß Timo
>Achso, während meinen Berechnungen deaktiviere ich den Interrupt.
Dann sind deine Berechnungen bzw. möglicherweise Ausgaben zu den
Berechnungen zu lang. Sendest du irgendwas über UART und wartest
bis das weg ist? Oder gibst du was auf LCD aus?
Ja Ausgabe auf LCD und das Ergebnis der Berechnung als Nachricht über den CAN Heißt wenn ich das richtig verstehe meinst du das meine Berechnung so lang braucht bis der Buffer voll ist!? Was wäre eine Abhilfe wenn ich die Ausgabe auf dem LCD behalten wollen würde, bzw. wenn meine Berechnung zu lang dauern würde!? Wenn ich mit CANoe mitlog habe ich eine durchschnittliche Berechnungszeit von ca. 2ms also weit weg von den 30ms ! :-( Danke für deine Antwort!
Hallo! Ich denke, Du machst da einen strukturellen Fehler. Für jede einkommende CAN Message bekommst Du einen CANIT Interrupt (Vektor 19 an Adresse 0x0024). Wenn der kommt, mußt Du alle Message Objekte abklappern, ob und wo eine neue Message eingetrudelt ist, eingegangene Messages aus dem Controller abholen, bearbeiten und das jeweilige Message Object wieder freigeben. Das sieht dann ungefähr so aus:
1 | // Imagecraft Interrupt-Deklaration
|
2 | #pragma interrupt_handler can_interrupt_rcv:iv_CAN
|
3 | |
4 | void can_interrupt_rcv(void) |
5 | {
|
6 | char can_irq=CANGIT; |
7 | int mob_irq; |
8 | char i,mob,st,cd; |
9 | |
10 | if (can_irq&BIT(7)) |
11 | {
|
12 | CANGIT=can_irq; // Interrupts zurücksetzen |
13 | if (can_irq&BIT(6)) |
14 | {
|
15 | //Bus OFF IRQ, CAN neu initialisieren
|
16 | can_init(); |
17 | }
|
18 | |
19 | mob_irq=CANSIT2|(CANSIT1<<8); |
20 | if (mob_irq) // Interrupt durch eine Message verursacht? |
21 | {
|
22 | for(mob=0;mob<NB_MOB;mob++) // alle Messages durchgehen |
23 | {
|
24 | if (mob_irq&&1) |
25 | {
|
26 | CANPAGE=mob<<4; // Message Object auswählen |
27 | cd=CANCDMOB; |
28 | st=CANSTMOB; |
29 | if (st&BIT(5)) |
30 | {
|
31 | //!!! hier Message aus dem Controller abholen,
|
32 | //!!! auswerten und bearbeiten
|
33 | }
|
34 | CANCDMOB=0; |
35 | CANSTMOB=0; // Status zurücksetzen |
36 | }
|
37 | mob_irq>>=1; |
38 | }
|
39 | }
|
40 | }
|
41 | }
|
Ich habe den Code ziemlich zusammengestrichen. Mag sein, daß ich da zu viel gestrichen habe, aber so im Prinzip geht das. Also: Du mußt JEDEN CANIT-Interrupt SOFORT behandeln. Ich denke, Du bekommst darüber irgendwelche Werte. Die mußt Du dann in der Interruptroutine in einen Zwischenspeicher schreiben und wenn ein neuer Auswertezyklus beginnt dort herausholen. fchk
Okay, würde bedeuten das ich nicht den Interrupt einfach deaktivieren kann. Und das heißt bei jeder CAN-Nachricht kommt ein Interrupt, egal ob meine gesuchte ID oder nicht. (Dies war mir klar) Aber so wie oben gezeigt mach ich es auch, ich speicher in meiner isr die Daten zwischen und dann kommt die Berechnung und danach die Ausgabe. Allerdings deaktiviere ich die Interrupts während der Berechnung. Dies ist falsch wenn ich dein SOFORT richtig deute!? Gehen denn die Daten sonst in einen Puffer? Danke für deine Antwort. Gruß Timo
Timo schrieb: > Okay, würde bedeuten das ich nicht den Interrupt einfach deaktivieren > kann. Genau. > Und das heißt bei jeder CAN-Nachricht kommt ein Interrupt, egal ob meine > gesuchte ID oder nicht. (Dies war mir klar) Eigentlich kommt nur ein Interrupt, wenn die Nachricht zu einer der definierten Akzeptanzmasken paßt, die Du natürlich vorher passend setzen mußt. Interrupts können aber auch aus anderen Gründen auftreten (z.B. Bus Errors, die speziell am Anfang auftreten können, oder wenn der Bus mal aufgetrennt wird oder ein Gerät dazugeschaltet wird). Siehe Beschreibung von CANSTMOB im Datenblatt. Und die mußt Du natürlich auch alle behandeln. Wenn nicht, dann hängt es irgendwann. Mein Beispiel ist in der Hinsicht ziemlich gekürzt. > Aber so wie oben gezeigt mach ich es auch, ich speicher in meiner isr > die Daten zwischen und dann kommt die Berechnung und danach die Ausgabe. > Allerdings deaktiviere ich die Interrupts während der Berechnung. > > Dies ist falsch wenn ich dein SOFORT richtig deute!? Richtig. In der Interruptroutine würde ich aber keine Berechnungen machen. > Gehen denn die Daten sonst in einen Puffer? Du hast 16 Message Objekte (MOB). Zu jedem MOB gibt es einen Speicher für eine Nachricht, es gibt eine Akzeptanzmaske und einen Satz Status/Control-Register. Wenn Du bei einem MOB eine Akzeptanzmaske setzt und dieses MOB scharf schaltest, kann es eine Nachricht empfangen. EINE. Danach ist es voll und will geleert und zurückgesetzt werden. Niemand hindert Dich aber daran, mehrere MOBs gleichzeitig zu initialisieren und zum Empfang zu benutzen. Dafür hast Du ja so viele. Zum Senden brauchst Du auch MOBs. Die MOBs liegen alle auf einem gemeinsamen Adressraum. Durch Schreiben in CANPAGE schaltest Du auf ein bestimmtes MOB (Stichwort Bankswitching). Mehr Pufferung gibts nicht. Also lautet die Strategie, Interrupts möglichst zeitnah zu behandeln und möglichst wenig in den Interrupts zu machen bzw die Interrupts möglichst kurz gesperrt zu lassen. fchk
Okay, danke für deine Ausführliche Antwort. Dann hab ich ja morgen was zu tun :-) Sollten noch Fragen auftauchen melde ich mich noch mal! Aber war schon mal super für die Hilfe!! Danke Gruß
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.