Datum:
Angehängte Dateien:Hallo, ich habe im Rahmen einer wissenschaftlichen Arbeit eine Bibliothek geschrieben, mit der es möglich ist den CAN-Controller des AT90CAN128 relativ schnell und komfortabel ansprechen zu können. Eine ausführliche Anleitung und Beispielcodes sind auch vorhanden. Bei Fragen einfach melden MfG Marco
Datum:
Sorry, aber sollte man nicht im Rahmen einer wissenschaftlichen Arbeit das h-File nur für Deklarationen und die Funktionen in ein c-File auslagern? Ansonsten sieht das echt gut aus. Vor allem, dass du die Docu dazu gelegt hast. Danke Werner
Datum:
Angehängte Dateien:Ok, hier nochmal die Version mit ausgelagerten Funktionen. Ich würde mich über Anregungen, Verbesserungen oder einfach nur eine Rückmeldung freuen... Gruß Marco
Datum:
Hallo Marco, der klare Stil des Programms gefällt mir. In dem pdf File gehen aber set und get durcheinander. Welchen Compiler verwendest Du? Wie sieht main() aus? Wo sind die Interrupt Service Routinen? Z.B. wartest Du bei CAN_sendData(...) bis TXOK in CANSTMOB. Dieses Bit kann nur durch "read modify write" geklärt werden und nicht durch clearbit.... Ich würde gern auf Deinem Ansatz aufbauen! Gruß Gerhard
Datum:
Hallo Gerhard, zuerst einmal vielen Dank für die Rückmeldung. Es freut mich zu lesen, dass der Stil des Programms dir gefällt. Bei welcher Funktion genau sind get und set durcheinander? Ich habe für diese Bibliothek den WinAVR Compiler zusammen mit dem AVRStudio verwendet. Die Hauptfunktion main() kann sehr einfach aussehen. Um zum Beispiel Daten zu senden:
main(){
CAN_init (1000 , TX );
// Zu sendende Daten
CAN_message msg ;
msg.id = 0 x12345678 ;
msg.idm = 0 xffffffff ;
msg.data [0] = 0 x11 ;
msg.data [1] = 0 x22 ;
msg.data [2] = 0 x33 ;
msg.data [3] = 0 x44 ;
msg.data [4] = 0 x55 ;
msg.data [5] = 0 x66 ;
msg.data [6] = 0 x77 ;
msg.data [7] = 0 x88 ;
// Objekt 0 auf Empfang setzen
CAN_enableMOB (0, RECEIVE_DATA , msg );
// Daten ¨uber Objekt 0 senden
CAN_sendData (0, msg . data );
while(1){}
}
|
Eine ISR zum Empfang von Daten ist am Ende der CAN.c angehängt. Diese kann ggf. individuell angepasst werden. Beim Senden von Daten über CAN_sendData() wird gewartet, bis das TXOK Flag gesetzt wird und erst dann die Funktion beendet. Das mit dem read-modify-write beim TXOK stimmt so wie du es geschrieben hast. Komischerweise funktioniert es aber auch mit dem clearbit() Makro (zumindest bei meinem Board und Debugger). Wenn du willst kann ich dir ein paar fertige Programme zukommen lassen, die die CAN-Funktionalität ausnutzen... Wenn du noch Fragen hast werde ich sie dir gerne beantworten. Viele Grüße Marco
Datum:
hallo zusammen, mal vorweck:die bibliotek ist klasse und die dokumentation ist auch der hit. habe versucht das bei mir einzubinden. hat leider nicht geklappt, würde mich interressieren, wie ein hauptprogramm aussieht, bzw wie genau ich das einzubinden habe, damit ich auf die bibliotek zugreifen kann. danke und gruß von timo
Datum:
Hi Timo, ich habe zwar gerade kein Board da um es zu testen aber prinzipiell sieht ein Programm dazu folgendermaßen aus: Für den Sender:
Für den Sender: #include "can.h" // Sonstige benötigte Bibliotheken // Hauptprogramm Int main(){ CAN Nachrichtenobjekt erstellen CAN_message msg1; //////////////////////////////////////////////////////// // Hier schreibst du deinen eigenen Programmcode rein // //////////////////////////////////////////////////////// // CAN initialisieren CAN_init(1000, RX); // Interrupts aktivieren sei(); // ID-Maske festlegen msg1.idm = 0xffffffff; // Es kommt nur genau dieselbe ID durch // Endlosschleife. Fragt zyklisch deinen Port ab und sendet die Schalterstellungen while(1){ // Schalterstellungen im ersten Datenbit abspeichern msg1.data[0] = PORTA; // ID festlegen (1) msg1.id = 0x00000001; // Objekt 0 aktivieren und Daten übergeben CAN_enableMOB(0, RECEIVE_DATA, msg1); // Daten senden CAN_sendData(0, msg1.data); } return 1; } |
Für den Empfänger:
#include "can.h"
// Sonstige benötigte Bibliotheken
// Hauptprogramm
Int main(){
CAN Nachrichtenobjekt erstellen
CAN_message msg1;
////////////////////////////////////////////////////////
// Hier schreibst du deinen eigenen Programmcode rein //
////////////////////////////////////////////////////////
// CAN initialisieren
CAN_init(1000, RX);
// Interrupts aktivieren
sei();
// ID-Maske festlegen
msg1.idm = 0xffffffff; // Es kommt nur genau dieselbe ID durch
// ID festlegen
msg1.id = 0x00000001; // Selbe ID wie im Sender
// Endlosschleife.
while(1){
}
return 1;
}
//////////////////////////////////////////////////////////////////////////////
// //
// Funktion: SIGNAL() //
// //
// Beschreibung: Interrupt für den Empfang einer Nachricht. //
// //
//////////////////////////////////////////////////////////////////////////////
SIGNAL(SIG_CAN_INTERRUPT1){
uint8_t save_canpage;
static CAN_message message;
// Aktuelle CANPAGE sichern
save_canpage = CANPAGE;
// Index des MOB ermitteln, der den Interrupt ausgelöst hat
uint8_t mob = CAN_getMOBInterrupt();
// Falls es kein gültiges MOB war abbrechen
if(mob == NOMOB){
return;
}
// Objekt das den Interrupt ausgelöst hat holen
CAN_getMOB(mob);
// Daten des MOBs aus CANMSG auslesen
message = CAN_getData();
// Id der Nachricht holen
message.id = CAN_getID();
//////////////////////////////////
// Daten verarbeiten / ausgeben //
//////////////////////////////////
// Hier verarbeitest du deine empfangenen Daten
// Wären deine LEDs auf Port A dann steuerst du sie so an
PORTA = message.data[0]; // Nutzdaten aus 1. Byte verarbeiten
//////////////////////////////////
// Daten verarbeiten / ausgeben //
//////////////////////////////////
// RXOK-Flag löschen
clearbit(CANSTMOB, RXOK);
// MOB auf Empfang und CAN 2.0B Standard setzen
CAN_setMode(RECEIVE_DATA);
// CANPAGE wiederherstellen
CANPAGE = save_canpage;
}
|
Das ist jetzt eine Anregung wie man es machen kann. Du kannst natürlich deinen Controller so programmieren, dass er sowohl senden als auch empfangen kann. Wie gesagt, ich habe im Moment keine Boards mehr um den Code zu testen. Aber prinzipiell müsste es so gehen. Falls etwas unklar ist oder du sonst noch Fragen hsat stehe ich dir gerne weiter zur Verfügung Viele Grüße Marco
Datum:
hi marco, ja mensch, der perfekte formteilnehmer kann nur sagen. ich habs gestern mal mit meinem eigenen hauptprogramm ausprobiert (sah so ähnlich aus wie deins) und hat hingehauen. trozdem danke für die bespielhafte hilfe!! ich werde immer mehr zum atmel fan.
Datum:
Angehängte Dateien:Hallo Marco, so, ich hab jetzt auch endlich mein CAN Board und konnte deine LIB testen. Das Senden hat auf Anhieb funktioniert. Ich habe auf der anderen Seite des Busses eine CAN Box/XL mit CAN-OE hängen und der zeigt mir die Nachricht auch richtig an. Wenn ich allerdings Nachrichten empfangen möchte, klappt das irgendwie nicht. Ich habe in der Interruptroutine erstmal eine LED blinken lassen.
SIGNAL(SIG_CAN_INTERRUPT1){
uint8_t save_canpage;
static CAN_message message;
// Aktuelle CANPAGE sichern
save_canpage = CANPAGE;
// Index des MOB ermitteln, der den Interrupt ausgelöst hat
uint8_t mob = CAN_getMOBInterrupt();
if (LED2)
LED2 = 0;
else
LED2 = 1;
...
|
Im main.c habe ich mit
CAN_message msg0, msg1; CAN_init(83, RX); msg1.idm = 0xffffffff; // Es kommt nur genau dieselbe ID durch msg1.id = 0x0B; // Selbe ID wie im Sender CAN_enableMOB(1, RECEIVE_DATA, msg1); // Muss der auch aktiviert werden? |
Leider wird meiner Meinung nach der Interrupt gar nicht aktiviert. Ich hab mal das ganze Projekt angehängt. Mir ist nicht ganz klar, wie das mit dem Aktivieren von MOBs ist. So wie ich das verstanden habe, definiere ich die Message, aktiviere den MOB und kann dann diese Nachricht senden. Was ist denn, wenn ich mehrere Nachrichte schicken will? Bzw. wie kann ich mehrere verschiedene Nachrichten empfangen? Vielleicht kannst du ja mal drüber schauen, wo da mein Denkfehler ist? Danke schonmal Werner
Datum:
OK, den ersten "Fehler" hab ich gefunden. Du hattest die extended ID aktiviert. Ich sende aber ein 2.0A Identifier. Das empfangen einer Nachricht klappt jetzt (den Inhalt hab ich noch nicht betrachtet) Allerdings habe ich festgestellt, dass bei msg0 jetzt die ID verloren geht. Habt ihr mal probiert gleichzeitig zu senden und zu empfangen? Danke schonmal Werner
Datum:
So, jetzt gehts. Das Problem war noch, dass auch das Einstellen der ID und der Maske an den Standart Identifier angepasst werden musste. Hier der "universell" anwendbare Code:
////////////////////////////////////////////////////////////////////////////////// // // // Funktion: CAN_setIDMask() // // // // Parameter: uint32_t idm - ID-Maske in Dezimalschreibweise // // // // Rückgabe: 1 - Maske erfolgreich eingestellt // // // // Beschreibung: Diese Funktion setzt die ID-Maske eines Objekts auf einen // // neuen Wert. In CANIDM4 bleiben dabei die Werte der unteren // // 3 Bit (RTRTAG, Reserved und IDEMSK) erhalten. // // // ////////////////////////////////////////////////////////////////////////////////// int CAN_setIDMask(uint32_t idm){ if (!getbit(CANCDMOB, IDE)){ //Standart identifier (11 bit) CANIDM2 = (uint8_t)(idm << 5); CANIDM1 = (uint8_t)(idm >> 3); } else{ //extended identifier idm <<= 3; idm |= 7; CANIDM4 = (unsigned char) (idm); CANIDM3 = (unsigned char) (idm>>8); CANIDM2 = (unsigned char) (idm>>16); CANIDM1 = (unsigned char) (idm>>24); } return 1; } ////////////////////////////////////////////////////////////////////////////////// // // // Funktion: CAN_setID() // // // // Parameter: uint32_t id - ID in Dezimalschreibweise // // // // Rückgabe: 1 - ID erfolgreich eingestellt // // // // Beschreibung: Diese Funktion setzt die ID eines Objekts auf einen // // neuen Wert. In CANIDM4 bleiben dabei die Werte der unteren // // 3 Bit (RTRTAG, RB1TAG und RB0TAG) erhalten. // // // ////////////////////////////////////////////////////////////////////////////////// int CAN_setID(uint32_t id){ if (!getbit(CANCDMOB, IDE)){ //Standart identifier (11 bit) CANIDT2 = (uint8_t)(id << 5); CANIDT1 = (uint8_t)(id >> 3); } else{ //extended identifier id <<= 3; id &= 0xfffffff8; id |= (CANIDT4 & 0x07); CANIDT4 = (unsigned char) (id); CANIDT3 = (unsigned char) (id>>8); CANIDT2 = (unsigned char) (id>>16); CANIDT1 = (unsigned char) (id>>24); } return 1; } ////////////////////////////////////////////////////////////////////////////////// // // // Funktion: CAN_getID() // // // // Parameter: // // // // Rückgabe: uint32_t - ID der empfangenen Nachricht // // // // Beschreibung: Diese Funktion holt die ID der empfangenen Nachricht. // // // ////////////////////////////////////////////////////////////////////////////////// uint32_t CAN_getID(){ uint32_t id; id = 0; if (!getbit(CANCDMOB, IDE)){ //Standart identifier (11 bit) id = (uint8_t) CANIDT2 >> 5; id |= (uint16_t) CANIDT1 << 3; } else{ //extended identifier id |= ((uint32_t) CANIDT1<<24); id |= ((uint32_t) CANIDT2<<16); id |= ((uint32_t) CANIDT3<<8); id |= (CANIDT4&0xF8); id >>= 3; } return id; } |
Datum:
Hi Leute, bin ganz neu auf diesem Gebiet und habe mir natürlich auch die lib runtergeladen... die ist echt toll, die doku ist auch sehr ausführlich und leicht zu durchblicken... Trotzdem habe ich es nicht geschafft nachrichten zu empfangen... ich habe irgendwie das gefühl, dass die Interrupts nicht gehen... hat jemand mal einen funktional Code, womit ich es testen kann...? Gruß
Datum:
Unter welcher Lizenz steht der Quellcode? Darf ich deinen Code in einem GPL-Projekt verwenden?
Datum:
Hallo Michael, klar darfst du den Code für dein Projekt verwenden...
Datum:
Hallo Marco,
sehr übersichtlich und gut programmiert, Habe nur noch eine Frage:
Du aktivierst den MOb mit RECEIVE_DATA obwohl du ihn versenden willst.
Funktioniert bei mir auch. Als ich es umstellen wollte auf TRANSMIT_DATA
wurde irgend etwas versendet nur nicht das was ich unter msg1.data
definiert hatte.
// Objekt 0 aktivieren und Daten übergeben
CAN_enableMOB(0, RECEIVE_DATA, msg1);
// Daten senden
CAN_sendData(0, msg1.data);
Datum:
Angehängte Dateien:Hallo Leute, ich hab die Bibliothek fuer meine Zwecke angepasst und will meine Arbeit gerne wieder dem Autor und der Allgemeinheit zurueckgeben. Veränderungen: * Die Version ist deutlich entschlackt, was aber auch auf Kosten der Kommentare geht. Aber auch an anderer Stelle liess sich gut Code einsparen. * Die Baudrate-Einstellung funktioniert nur noch bei 16 MHz. Wer eine andere Taktrate fährt, muss sich die entsprechenden Zeilen Code aus der ursprünglichen Version vom Marco kopieren. * Es werden nicht nur extended IDs (mit 29-Bit-Identifier; CAN 2.0B) unterstuetzt, sondern auch die mit nur 11-Bit (CAN 2.0A). Dazu habe ich im Prinzip nur die Patches von Werner eingebaut. * Es können Nachrichten mit variabler Länge verschickt werden. * Die API hat sich etwas geaendert. Siehe auch Beispiel. Das war für mein Projekt notwendig. Hier ein Beispiel, um Daten mit variabler Laenge und extended ID zu verschicken:
#include <avr/io.h> #include <avr/interrupt.h> #include <inttypes.h> #include <stdbool.h> #define F_CPU 16000000ULL #include <util/delay.h> #include "can.h" void sleep(uint32_t i) { while(i--) _delay_ms(1); } int main(void) { int8_t data[8]; uint8_t i; data[0] = 'H'; data[1] = 'i'; data[2] = ' '; data[3] = 't'; data[4] = 'h'; data[5] = 'e'; data[6] = 'r'; data[7] = 'e'; // baudrate: 250K, keine Interrupts, extended Id can_init(3, 0, 1); // mob: 0, modus: senden, id 3, idm 0xffffffff can_enable_mob(0, 1, 3, 0xffffffff); for(i = 1; i <= 8; i++) { sleep(1000); can_send_data(0, i, data); } while(1); return 0; } |
Code, das Beispiel und Makefile sind angehaengt, so dass man eigentlich (bei richtiger Taktfrequenz von 16MHz) gleich durchstarten kann. Ich wuerde mich ueber Kommentare/Kritik freuen. An dieser Stelle nochmal herzlichen Dank an Marco Glietsch fuer die urspruengliche Version und seine sehr, sehr, sehr gute Dokumentation. :)
Datum:
Hallo Michael, dein Beispielprogramm hat sofort funktioniert, super.... gibts auch noch Beispiele für den Empfang bzw. gleichzeitiges Senden und Empfangen? Ich hab damit Probleme, manchmal werden Messages nicht korrekt übertragen und der PCAN-Adapter zeigt Busfehler an.
Datum:
Angehängte Dateien:Hallo Wolfgang, ich hab die Bibliothek wieder etwas modifiziert. Nur die ganzen enum-Konstanen in die Header-Datei verlagert, so dass man sie jetzt auch in main.c nutzen kann. Es macht den Code wesentlich uebersichtlicher, wenn man aussagekraeftige Konstanten wie z.B. CAN_BAUDRATE_250K verwenden kann und nicht eine einfache Zahl wie 3. Nun zu deinem Problem. Ich hab mom. nichts hier zum testen, hab aber die main.c mit Beispielen erweitert, wie es eigentlich funktionieren sollte. Wenn es nicht geht, dann ist es wahrscheinlich ein Bug. ;-) Das Problem ist, dass ich mich auch erst seit ein paar Tagen mit dem CAN-Bus befasse und daher durchaus noch Fehler schlummern koennte. Probier es einfach mit den Beispielen aus und sag, was geht und was nicht. Ich habe mit der Bibliothek heute erfolgreich Senden, Empfangen und automatische Antworten getestet. Allerdings immer nacheinander und nie gleichzeitig. Muss ich am Montag mal genauer untersuchen. Wenn ihr Fehler seht, dann sagt mir Bescheid. Danke! 2*n Augen für n>1 sehen eben einfach mehr als nur 2. ;-) --Michael
Datum:
Hallo Michael, es freut mich, dass du die Bibliothek funktionell erweiterst. Aber die Baudrate hättest du drin lassen können. Der Präprozessor sorgt dafür, dass nur der zur Taktrate passende code compiliert wird. F_CPU wird übrigens im AVR-Studio in den Projekteinstellungen eingestellt und muss nicht extra im Quellcode angegeben werden. Gruß Marco
Datum:
Angehängte Dateien:Hallo Marco, die Makros fuer die Baudrates habe ich rausgenommen, weil ich sie nicht brauche und ich sie unuebersichtlich finde, weil sie so lang sind. Wenn man etwas im Code sucht, dann stoert mich sowas und bei meinem Projekt weiss ich, dass es nur mit 16MHz laeuft. Dass das nicht mit weniger Belegung von Flash oder schnelleren Code zu tun hat, ist mir klar. In der angehaengten Version hab ich es jedenfalls wieder angehangen, weil es fuer andere vielleicht nuetzlich sein koennte. Zu F_CPU im AVR-Studio kann ich nichts sagen. Ich nutze avr-gcc unter Linux mit vim und wenn ich F_CPU nicht angebe, beschwert sich avr-gcc. Ich lass mich aber gerne eines besseren belehren. Kann es sein, dass man Autoreply und Empfangen nicht gleichzeitig fuer zwei unterschiedliche MOBs nutzen kann oder ist im Code noch irgendwo ein Fehler? --Michael
Datum:
Hallo Michael, hab leider Probleme mit deiner neuen Version.... Senden funktioniert, aber beim Empfang tut sich überhaupt nichts... Er springt nicht in die Interruptroutine, übrigens egal welche ID ich benutze und die idm komplett öffne. PCAN zeigt auch weiterhin Busfehler an.... Ich werde heute auch mal suchen, vielleicht entdecke ich etwas... muß das bei Autoreplay nicht id 5 heißen? Gruß Wolfgang
Datum:
Hallo Michael, ich hab entdeckt daß der Empfang funktioniert wenn man die Interrupts global mit "sei" freigibt. Aber ich denke das ist doch nicht richtig, denn die IR's des CAN-Controllers sind doch unabhängig davon, oder nicht?
Datum:
Hallo Wolfgang, das globale Interrupt Flag (GIE) im Status Register muss mit sei() gesetzt werden, da sonst überhaupt kein Interrupt bearbeitet wird. Im CAN General Interrupt Register (CANGIT) werden dann die Interrupts für den CAN-Controller freigegeben. Gruß Marco
Datum:
Hallo Marco, danke für die Info, aber wann muß daß passieren? Vor der CAN Initialisierung oder egal wann? Ich hab einfach noch Probleme daß der Empfang mal geht, mal nicht. Momentan kann ich nichts feststellen, es ist einfach wahllos wann.... Senden klappt komischerweise konstant immer... Gruß Wolfgang
Datum:
Hallo Wolfgang, die Interrupts sollten aktiviert werden bevor du ein MOB in den Empfangsmodus setzt. Somit wird sichergestellt, dass jede Nachricht ankommt bzw. einen Interrupt auslöst. Würdest du zuerst dein MOB auf Empfang setzen und dann die Interrupts aktivieren kann es passieren, dass eine Nachricht zwischen diesen beiden Aktionen ankommt, die dann aber keinen Interrupt auslöst und du nichts davon mitbekommst... Gruß Marco
Datum:
Hi Marco, ich habe die Interrupts jetzt vorher aktiviert, und es läuft jetzt zufriedenstellend. Eine kleine Unschönheit habe ich durch Zufall gefunden, ich werde mal versuchen sie zu beseitigen. Wenn man "can_enable_mob(0, CAN_MODE_TRANSMIT_DATA, 3, 0xfffffff);" ( stammt zwar von Michael, ist aber bei deiner Routine sehr ähnlich) aufruft wird sofort ein 'Signal' auf den CAN-Bus gesendet, allerdings mit null Datenlänge und demzufolge keinem Dateninhalt. Es wurde ja noch nichts definiert.. Es hat keine Auswirkungen, sieht nur nicht gut aus. Übrigens, bist du noch in KA? Gruß Wolfgang
Datum:
Hallo, dass Datenpakete mit der Laenge 0 geschicht werden, ist mir auch aufgefallen. Ich dachte allerdings, dass das von einem anderen Problem kommt. Naemlich hatte ich das Problem, die Datenlaenge fuer die Pakete richtig einzustellen (siehe auch Kommentar um Zeile 620 in can.c). Aber gut zu wissen, ich werde mir das mal genauer anschauen. Ich habe noch eine Frage zum Auto-Reply: Ist es normal, dass nur auf das erste Remote-Frame ein Auto-Reply geschickt wird und danach nicht mehr? Ich weiss noch nicht, ob dass ein Bug ist oder nicht. ;-) Ich schau dann auch mal, dass ich funktionierende Beispiele anhaenge. Die Beispiele mom. sind ja alle ungetestet und nur schnell zusammengeschustert, damit man sich vorstellen kann, wie es funktionieren sollte. Gruss. --Michael
Datum:
Hallo an alle, ich bin etwas weiter gekommen..... Die Nachrichten mit Datenlänge 0 werden durch setbit(CANCDMOB, CONMOD0) in der Funktion can_set_mode ausgelöst. Ich vermute mal der der Ablauf irgendwie noch nicht korrekt ist, da beim Enable des Mob normalerweise kein Senden ausgelöst werden darf..... Ich habe bei einem anderen Projekt die Atmel-Beispiele verwendet, da war das nicht der Fall, also muß es auch funktionieren. Leider hab ich erst morgen Abend wieder Zeit mich darum zu kümmern, vielleicht ist jemand schneller.... :-) Die Frage mit dem Auto-Replay kann ich nicht beantworten, ich hab diese Funktion bisher nicht verwendet und so lange beschäftige ich mich noch nicht mit dem CAN-Bus. Ich stecke da auch noch in den Anfängen... Gruß Wolfgang
Datum:
Hallo Wolfgang, Ich bin zur Zeit nicht mehr in KA. Ich schreibe gerade meine Diplomarbeit. Wieso? Bist/studierst du auch in KA? Gruß Marco
Datum:
Hi Marco, ich wohne direkt nebenan...., deswegen die Frage. Ich habe leider nur etwas weiter machen können an dem Problem des Sendens bei Can_send_mode mit Null Datenlänge. Die erste Initialisierung mit CAN_enablemob ist beim Senden nicht notwendig, es werden trotzdem die Daten gesendet. Man könnte demzufolge Can_set_mode aus Can_enablemob weglassen, bräuchte dann aber eine zweite Funktion alleine für das setzen des Filters und der ID, den die beiden müßen ja initialisiert werden. Wenn ich die nächsten Tage dazu komme werde ich es mal entsprechend probieren..... Grüße Wolfgang
Datum:
Angehängte Dateien:Hallo an alle, hab mir von Marco die CAN-Bibliothek angeschaut und stoße auf ein Problem das ich nach langem nicht allen lösen kann. Habe zwei Knoten an dem Can-bus sowie einen USB-Can-Sniffer von PEAK. Wenn ich vom PEAK aus eine Nachricht auf den BUS schicke sollte es wie folgt ablaufen. Beide Knoten sollen mir mit verschiedenen ID Antworten. Erste der mit der höheren Priorität dann der mit der niedrigen. Wenn ich bei einem ein delay einbau funktioniert das tadellos. Problem: 1. Wenn ich einen RESET von den Knoten mache und über den PEAK eine Nachricht versende, bekomme ich gleich von jedem Knoten 2 zurück.....? wie kommt’s....? 2. Wenn ich eine weitere Nachricht vom PEAK sende, bekomme ich von der höheren Priorität ID eine Nachricht zurück......soweit schön....das klappt auch immer. Jedoch bekomme ich von dem 2ten Knoten beim 2ten Senden keine Nachricht und beim 3ten Senden gleich 2 zurück....das geschieht alternierend. Habe im Projekt bei den Mops für beide Knoten lediglich die ID geändert. Das die nicht auf der gleichen ID Antworten.... Würde mich um eine Lösung SUPER freuen. Gruß Arno
Datum:
Hallo, kleiner Bugfix in der can.c von
Autor: Michael (Gast) Datum: 15.09.2008 09:13 Dateianhang: can.tgz |
Bug: MOb-Interrupts für MOb8..MOb14 werden nicht gesetzt Bugfix:
// Parameter: uint8_t mob: Nummer des Objekts (0-14) // Funktion setzt den Interrupt für das jeweilige Objekt void can_set_mob_interrupt(uint8_t mob) { if (mob < 8) { setbit(CANIE2, iemob[mob]); } else { setbit(CANIE1, iemob[mob]); } } |
Gruß Christian
Datum:
Hat jemand mal ein fertiges und übersichtliches beispiel wo daten zwischen zwei Controllern per CAN hin und her gesendet werden? Ich versuche mich nun schon seit ein paar tagen mit dieser Bibliothek aber bekomme ganz und gar keine funktion hin. Ob die Daten gesendet sind überprüfe ich mit der UART schnittstelle ich hoffe mir kann jemand helfen. Im fall ihr habt eine bessere Bibliothek so würde ich auch die nehmen. hauptsache es funktioniert und die Lib ist gut zu verstehen. Danke Martin
Datum:
hat einer ein Beispiel????
Datum:
Schonmal in der Doku gelesen?
Datum:
ja hab ich aber die ist nicht wirklich so gut. ich suche eigentich auch eher mehr ein beispiel füe einen empfänger und einen sender... aber danke für die hilfe ;-)
Datum:
zu: Autor: Arno Schulz (schneeball) Datum: 11.03.2009 14:33 Dateianhang: CANTest.zip (43,5 KB, 53 Downloads) Ich habe das gleiche Problem fest gestellet. Wenn ich mehere Daten per PC schnell hintereinader schicke, kommt als antwort manchmal 2 mal das gleiche zurück. sende: 01 00 00 00 00 00 00 02 00 00 00 00 00 00 03 00 00 00 00 00 00 04 00 00 00 00 00 00 05 00 00 00 00 00 00 antwort 02 00 00 00 00 00 00 02 00 00 00 00 00 00 03 00 00 00 00 00 00 05 00 00 00 00 00 00 05 00 00 00 00 00 00 ich suche jetzt schon seit 2 tagen den fehler. hat jemand eine idee womit das zusammen hängen kann? bin echt für jede Hilfe dankbar.
Datum:
Hallo wir veruschen hier gerade die Message "Blinken" von einer S-Klasse auszulesen. Haben einen Modelaufbau mit 2 Steuergeräten und CANOE. Der CAN läuft die Initaliesrung des MC funktioniert auch. Allerdings springt er nicht in den Interrupt, was er tun sollte sobald eine Message empfangen wurde. könnt ihr uns vielleicht irgendwie weiterhelfen z.b was hierbei typische Fehlerquellen sind? dankeschön
Datum:
Angehängte Dateien:typische fehlerquellen sind die globalen interuppts einfach mal sei(); ausführen um die interrupptabfrage zu starten. ich habe allerdings ein anderes problem mit dieser bibliothek... das senden und empfangen funktioniert. leider sendet er aber nur einmal. obwohl ich das senden innerhalb der endlosschleife habe. falls einer da ne idee hat worann es liegen könnte wäre ich sehr verbunden. ich habe auch noch mal mein komplettes C-Programm mit source datein angehängt. in diesem fall das für knoten 1.
Datum:
ich glaube das mein problem ist das can_send_data auf das TXOK wartet es aber nie bekommt. ich schließe das auch bei mir das clearbit nicht funktioniert wie bereits von Gerhard (Gast) am 04.05.2008 19:30 gepostet wurde. gibt es eine möglichkeit das bit anders zu setzen beziehungsweise zu übergeben? ansonsten klappt eigentlich alles perfekt. aslo schon mal danke für die routine.
Datum:
sobalt ich die txok abfrage in der can_send_data und das clearbit rxok im empfangsinterrupt entferne sendet mein system reibungslos. bei geschalteter abfrage des txok hängt sich der sende controller an der stelle auf. ich habe auch überbrüft ob es ein bitfehler ist der zu einem bus-off führt, dem ist nicht so, da der sender fleißig weiter sendet ohne irgendwann abgeschaltet zu werden. hatte jemand bereits dasselbe problem und kann mir helfen?
Datum:
Schaut euch ma die CANPAGE genauer an! Dann kommt ihr wahrscheinlich auf die LÖsung eurer Probleme!
Datum:
Angehängte Dateien:Mit dem Stand bis zum 11.03.2009 haben wir die CAN-Lib überarbeitet und Fehler und Unschönheiten korrigiert. Haben die Lib in einem System mit drei gleichen AT90CAN128 eingesetzt und die Kommunikation mit einem CANAlyzer verifiziert. Durch senden eines Zeichens über den UART wird abhängig vom Zeichen eine unterschiedliches CAN-Message versendet. Auto-Reply und Remote-Frames sind ebenfalls eingerichtet und getestet. Wird wohl noch nicht ganz perfekt sein, stellt aber einen ganz guten Stand dar. g Wir wünschen viel Erfolg mit weiterer Verwendung... Grüße MatMar
Datum:
Angehängte Dateien:Hallo Im Anhang: meine Send-Remote-Funktion. Und in meiner main-Funktion eine while-Schleife mit folgendem Inhalt:
while(1) { can_send_remote(0,8); led_blinken(); // Die LEDs blinken, damit ich weiß, wann die Schleife zu Ende ist... } |
Komsicherweise sendet er mir beim einen Durchgang den Remote-Request wie gewünscht. Beim nächsten Durchgang sendet er mir ein Daten-Frame. Und dann wieder Remote, dann Data, .... Ich komm einfach nicht dahinter warum das so ist. Ich will eigentlich nur den Remote-Request. Könnt ihr mir weiterhelfen???? VIelen dank !! Gruß
Datum:
Nob Ge. schrieb: > Hallo > > Im Anhang: meine Send-Remote-Funktion. > Und in meiner main-Funktion eine while-Schleife mit folgendem Inhalt: >
> while(1) > { > can_send_remote(0,8); > led_blinken(); > // Die LEDs blinken, damit ich weiß, wann die Schleife zu Ende ist... > } |
> > Komsicherweise sendet er mir beim einen Durchgang den Remote-Request wie > gewünscht. > Beim nächsten Durchgang sendet er mir ein Daten-Frame. > Und dann wieder Remote, dann Data, .... > > Ich komm einfach nicht dahinter warum das so ist. > Ich will eigentlich nur den Remote-Request. > > Könnt ihr mir weiterhelfen???? > VIelen dank !! > Gruß Habe jetzt doch noch die Antwort gefunden: Die Reihenfolge der Flags beim Setzen des Modus ist entscheidend.. Verdammt und jetzt erst schau ich in die "CAN-Lib.rar".. da stehts ja auch drin... Naja Gute nacht ;-)
Datum:
Jetzt habe ich doch noch eine Frage: Im Datenblatt steht doch: Das RTRTAG und das RPVL-Tag werden im Auto-Reply Modus automatisch zurückgestellt. --> Somit wird 1x die Auto-Reply Funktion ausgeführt. Wie macht man es jetzt am besten, dass beim nächsten mal (wenn ein Remote-Request "angefragt" wird), dieser RTR-TAG und RPVL-Tag wieder gesetzt ist? Gibts da ne besonders clevere Lösung? Geht das denn nicht automatisch?? Weil bis jetzt mache ich es immer so, dass ich am Anfang der while-Schleife wieder den MOb explizit "initialisiere" und dabei den Auto-Reply-Modus setze.. Ich finde diese Methode aber nicht besonders gelungen !!!! Vielen Dank für Anregungen und Antworten :-) Gruß
Datum:
Nob Ge. schrieb: > Im Datenblatt steht doch: > Das RTRTAG und das RPVL-Tag werden im Auto-Reply Modus automatisch > zurückgestellt. Das ist auch korrekt so. Diese müssen explizit wieder gesetzt werden, wenn ich das richtig in Erinnerung habe. Du stellt damit quasi explizit nur ein Frame bereit, wenn beispielsweise neue Daten zum Versenden bereit sind. Wieso auch gleiche Infos immer wieder versenden... Wir hatten das so gemacht, dass wir nen Sensor abgefragt hatten und wenn sich dessen Zustand geändert hat, haben wir das Auto-Reply CAN_message Objekt mit neuen Daten befüllt und danach die Funktion CAN_enableMOB() aufgerufen. Die anderen Mikrocontroller haben zyklisch Auto-Reply messages versendet und ne entsprechende Antwort erhalten, wenn sich was getan hat. Weitere Anregungen habe ich leider grade nicht. Hoffe, ich konnte helfen. Grüße, ein Teil von MatMar ;)
Datum:
Äh sorry, nicht "zyklisch Auto-Reply messages versendet", sondern natürlich remote frames ! Grüße
Datum:
Hallo MatMar !! Vielen Dank für die Antwort. Das hilft mir sehr weiter. Hatte bis jetzt leider keinen Kontakt mit Autp-Reply und Remote-Requests, deswegen wusste ich nicht, wie das "normalerweise" so gehandelt wird. Vielen Dank nochmal! Schöne Weihnachten !!
Datum:
Hallo euch allen, ich bin schon seit einiger Zeit auf der Suche nach einem CAN-Bootlader für den AT90CAN. Leider konnte ich dazu aber kein fertiges Projekt finden. Genauere Informationen gibt es unter fogendem Link: Titel - Beitrag "CAN BUS Bootloader AT90CAN" Ich hoffe es finden sich einige um dieses Projekt zu realisieren oder die dabei helfen können. Grüße martin
Datum:
Hallo zusammen... Ich verzweifel gerade! Nachdem mein Treiber für den AT90CAn nicht funktioniert habe ich jetzt schon 5 andere die funktionieren sollen getestet. Es klappt mit keinem. Mit dem Oszi bin ich dem ganzen mal etwas näher gekommen. Sobald ich ein MOb aktiviere hab ich auf dem Can ein unidentifizierbares Störsignal was meine bisher eingesetzten MCP2515 komplett taub macht. Also sprich das ganze Can Netzwerk bricht zusammen sobald ich beim AT90CAn ein MOb aktiviere. Hat jemand eine Idee was falsch sein könnte? extrem verzweifelt ist
Datum:
Versuch mal die Lib von Fabian Greif. Habe ich sowohl für den AT90CAN128 als auch SJA1000 genommen. Funktioniert superklasse. Das schöne daran ist, dass man sein Hauptprogramm unverändert lassen kann und nur die entsprechenden Routinen entweder für den MCP2515, SJA1000 oder AT90CAN128 dazu compiliert. Auf der Homepage ist auch eine ausführliche Anleitung bzgl. Filter. Dies wär nämlich ein Problem von mir. Grüße Andreas
Datum:
Die Hab ich auch schon probiert... Ich werd wohl einfach nochmal 10 Euro investieren und ein neuen AT90CAN128 kaufen. Ich ermute einfach das der innen drin kaputt ist. Leiterbahnen hab ich alle geprüft. Das isses ned. Hat jemand evtl. mal ein hex-file womit ich das bei mir testen kann? Es langt wenn das Programm 1:1 den ankommenden Datenstrom per UART ausgibt. (Verwende den UART Port 1, NICHT den 0er) Meine MCP2515 haben die Baudrate auf 125kbit (Glaub ich zumindest - Zur Kontrolle hier meine Einstellungen) write_Reg_MCP2515(CNF3, (1<<PHSEG21)); write_Reg_MCP2515(CNF2, (1<<BTLMODE)|(1<<PHSEG11)); write_Reg_MCP2515(CNF1, (1<<BRP2)|(1<<BRP1)|(1<<BRP0)); Hat da jemand mal was parat? :)
Datum:
Ich habe mal ne anmerkung zur Dokumentation. Hast du schon mal was von Doxygen gehört? Das ist ein Werkzeug zur Automatisierten Code Dokumentation. Dabei wird dein Code und zusätliche die Dokuzeilen (welche sich im Code befinden) analysiert und daraus eine sehr gute Code Doku erstellt. Dabei können verschiedene Ausgabe Vormate erstellt werden. unter anderem HTML und LaTeX. Der Grund warumn ich das erwähne ist der das die Doku Köpfe zu den Funktionen schon genauso aufgebaut sind wie es in Doxygen gern gemacht wird, eben nur die entsprechenden Befehlswörter fehlen. Man spart sich mit Doxygen einen Haufen Arbeit weil der Code nicht zwei mal dokummentiert werden musss.
Datum:
Hallo Tobias, Doxygen ist mir sehr wohl ein Begriff. Für andere Projekte habe ich es auch schon eingesetzt. Daher auch die Strukturierung der Kommentare in diesem Programmcode. Für dieses Projekt habe ich aber auf Doxygen verzichtet.
Datum:
Ah so. Naja das erklärt zumindetens die verblüfende Ähnlicheit der Doku
Datum:
Hallo, ich versuche z.Z. meine PC über eine Vector Karte (CANcaseXL) mit der AT90CANx zu kommunizieren. Meine Frage: Kann man direkt das CAN Kabel an den AT90CANx anschließen? oder braucht man noch ein Inteface zwischen Vector und der AT90CANx?. Das ist nämlich, was nirgendwo erwähnt wird, und für einen Anfänger wie ich ist das noch unklar. Falls diese Interface gebraucht wird, hat vielleicht jemand eine Schaltung? Ich danke für alle Antworten. Abel (Grüsse aus Bolivien)
Datum:
Es wird immer ein CAN Transceiver benötigt. Z.B. ein SN65HVD1050 von TI. Gruß Fabian
Datum:
Hallo zusammen! Ich habe ein Problem mit dem Auto-Reply-Mode. Auf eine RTR Msg mit der ID 0x099 soll folgende Antwort kommen: ID=0x099, DLC=2, DATA[0]=0x12 und DATA[1]=0x34. Das passiert auch, allerdings erhalte ich noch eine zweite Msg: ID=0x099, DLC=0. Sprich auf jede RTR-Msg erhalte ich zwei CAN-Nachrichten zurück. Einmal die Richtige und eine Leere. Ich habe meine CAN.C mit dem letzten Stand hier aus dem Forum abgeglichen und auch schon komplett getauscht, aber beides liefert das gleiche Resultat. Hat jemand eine Idee woran das liegen könnte? Ich setze das Auto-Reply Mob in der Endlosschleife immer wieder neu:
... CAN_message msg; int main(void) { ... msg.id = 0x099; msg.idm = 0xffff; msg.dlc = 2; msg.data[0] = 0x12; msg.data[1] = 0x34; ... while(1) { CAN_enableMOB(2, AUTO_REPLY, msg); ... } return(0); } |
Schöne Grüße, der Sven
Datum:
Hallo, ich habe ein Problem beim senden einer CAN Nachricht. und zwar läuft sich mein Prgramm immer in dieser while -Schleife fest! while (!getbit(CANSTMOB, TXOK)); währe sehr dankbar für eine Hilfestellung. Danke
Datum:
Gleiches Problem hier.
Datum:
Hi, für mich hat sich das Problem mehr oder weniger erledigt. Du brauchst neben dem Sender, mindestens einen Empfänger, sonst kommt es du dem beschriebenen Problem. Mein nächstes Problem ist allerdings das der Interrupt "SIG_CAN_INTERRUPT1" nicht beim Empfänger aufgerufen wird, sondern in einer Endlosschleife beim Sender. Aus "/usr/avr/include/avr/iocanxx.h": /* CAN Transfer Complete or Error */ #define CANIT_vect _VECTOR(18) #define SIG_CAN_INTERRUPT1 _VECTOR(18) Da der Interrupt immer wieder beim Sender aufgerufen wird, geh ich mal davon aus das beim senden etwas schief läuft ... bin noch an der Fehlersuche.
Datum:
@Tobias
Ich konnte meine Probleme (siehe oben) lösen. Dein Problem dürfte sein
das in der Funktion "CAN_setInterrupt" der TXOK Interrupt aktiviert
wird. Dadurch ergibt sich folgende Situation:
"CAN_sendData" sendet die Daten und wartet danach darauf das das "TXOK"
Bit gesetzt wird. Da der TXOK Interrupt aktiv ist, wird beim setzen
dieses Bits der Interrupt "SIG_CAN_INTERRUPT1" aufgerufen. Jetzt gibt es
zwei Möglichkeiten:
1) Das Bit TXOK wird innerhalb der Interrupt-Behandlungsroutine nicht
zurückgesetzt (so wie in der aktuellen Implementierung). In dem Fall
wird der Interrupt immer und immer wieder aufgerufen, die Funktion
"CAN_sendData" wird nicht weiter ausgeführt (hat also auch keine
Möglichkeit zu prüfen ob das TXOK Bit gesetzt ist).
2) Das Bit TXOK wird innerhalb der Interrupt Behandlungsroutine
zurückgesetzt. In diesem Fall wird die Funktion "CAN_sendData" zwar
weiterausgeführt, da das TXOK-Bit aber innerhalb der ISR zurückgesetzt
wurde bleibt diese in der Schleife "while(!getbit(CANSTMOB, TXOK))"
stecken.
Lösung:
In der Funktion "CAN_setInterrupt" den TXOK Interrupt NICHT aktivieren:
int CAN_setInterrupt(uint8_t mode)
{
switch(mode)
{
[...]
case TX:
setbit(CANGIE, ENIT);
clearbit(CANGIE, ENRX);
ALT: setbit(CANGIE, ENTX);
NEU: // setbit(CANGIE, ENTX);
return 1;
[...]
Datum:
Hallo Leute, ich habe die Bib von Marco gelesen und habe mich für meine Arbeit orientiert.Ich muss die Kommunikation zwischen PC und AT90CAN128 mitteln den Protokoll CANopen(MicroCANopen)Realisieren.die Node_ID muss mitteln 7-DIP-Schalter ( ist am PORT C den) und Baudrate mit 4-DIP-Schalter(PORT A) eingestellt werden.kann biztte Jemand tip geben wie ich das mache kann. Am ende muss in der lage sein mitteln den Schalter Node_ID und Baudrate ändern können. MFG Danke
Datum:
Hallo patnze, du driftest etwas vom ursprünglichen Thema ab! Ich gebe dir aber gern ein kleinen Denkanstoß, wie du dein DIP-Schalter Problem lösen kannst:
int get_baudrate(void) { int baudrate; switch(PINA & ((1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3))) { case 0x01: baudrate = 125; break; case 0x02: baudrate = 200; break; case 0x03: baudrate = 250; break; case 0x04: baudrate = 500; break; case 0x05: baudrate = 1000; break; default: baudrate = 100; } return(baudrate); } int get_node(void) { // kann man wie get_baudrate() aufbauen und an entsprechender Stelle im Code verwenden. // Kenne das OpenCAN Protokoll nicht, daher weiss ich nicht genau wo das hin muss! // Aber das wirst du dann ja wissen, wie du es ins Protokoll verpacken musst... } int main(void) { // Ports als Eingänge setzen DDRA &= ~((1<<DDA0)|(1<<DDA1)|(1<<DDA2)|(1<<DDA3)); // DIP-Schalter für Baudrate DDRC &= ~((1<<DDC0)|(1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4)|(1<<DDC5)|(1<<DDC6)); // DIP-Schalter für Node_ID // Ich kenne deine Eingangsbeschaltung der DIP's nicht, aber vermutlich brauchst du noch die PullUps, // falls du keinen externen hast?! // PullUps für Eingänge aktivieren PORTA |= (1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3); PORTC |= (1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3)|(1<<PC4)|(1<<PC5)|(1<<PC6); // CAN initialisieren CAN_init(get_baudrate(), TX); // ...wie das Senden und Empfangen funktioniert, hat Marco ja bereits gut beschrieben! // Dann kannst du ja einfach dein CANopen Protokoll umsetzen :) } |
Ich hab das gerade mal kurz im Editor runtergetippt, kann daher nicht sagen, obs komplett fehlerfrei ist, aber es geht ja vielmehr um einen möglichen Lösungsansatz! Bei weiteren Fragen oder Problemen mit OpenCAN, die nicht Marcos CAN-Bib betreffen, würde ich dir den Rat geben einen Thread aufzumachen! Gruß, Sven
Datum:
Danke Sven, habe auch ein Kumpelt gefragt und seineErklärung war genau wie deine.nochmals danke.
Datum:
Hallo, ich wollte man ein test Programm schreiben um mein Board die DIP-Schalter testen zu können.wollte vom Schalter in PORT A ein LED in PORTB anschalten.das Programm sieht aus: #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <inttypes.h> #include <stdbool.h> int main (void) { DDRA = 0x00; PORTA = 0xFF; DDRB = 0xFF; PORTB = 0xFF; while(1) { if(PINA &(1 <<PINA0)){ _delay_ms(100); PORTB=PORTB|(1<<PB5); } else { _delay_ms(100); PORTB &= ~(1<<PB5); } } return 0; } Beim kompieleren bringt keine Fehler aus aber es passiert einfach nichts. kann Jemand mir sagen wo das Problem ist oder einfach ein andere beispiel oder tips geben.danke. mfg
Datum:
Hi, ich hatte dir bereits geraten, ein eigenen Thread aufzumachen, da das hier thematisch nicht rein passt!
Datum:
Hallo Zusammen, kann mir jemand den Code von CAN_Test erklären, was da passiert?? Wäre super nett.............................. Ausserdem würde ich gerne verstehen, warum das Programm nicht in die ISR springt? Versteh ich net...................... Kann man die Daten auch über TXCAN die Daten schicken bzw. wohin gehen die versendten Daten?? Grüße und vielen Dank........
Datum:
Hallo zusammen, hat schon mal Jemand die Bibliothek mit dem Display3000 Modul ans laufen bekommen? At90CAN128 mit PCA82C250 Kompilieren klappt aber bekomme keine Nachricht mit egal welchen Testdemos die ich hier schon gefunden habe, über den Bus raus. Logge mit dem Canalyzer, aber es tut sich nichts?! Grüße
Datum:
Hello alle, Dieses Bericht ist für mich als CAN neuling sehr nutzvoll. Aber eine Frage habe ich: Wo wird der CRC geschrieben. Ich siehe kein CRC Berechnung in der Code....oder habe ich was üversehen? BD
Datum:
Die CRC-Summe wird direkt vom CAN-Controller (in der Hardware des AT90CAN128) erzeugt und angehängt bzw. verglichen. Chris D.
Datum:
Hi,
ich sitze gerade daran die vorhandene Bibliothek auf meine Bedürfnisse
anzupassen.
In der Funktion "CAN_getMOBINTERRUPT()" stoße auf ein Problem.
Die Abbruchbedingung in der for-schleife verstehe ich nicht. Ich gehe
davon aus, dass in der Variable "maske" nur ein Bit = 1 ist. Somit
müsste doch die Abbruchbedingung "(maske & 0x01)==1" heißen, damit man
den richtigen "mob" rauszieht, oder? Meinem verständnis nach, bricht die
schleife ab, sobald eine "0" an der ersten stelle der "maske" ist ->
quasi sofort.
uint8_t CAN_getMOBInterrupt()
{
uint8_t mob;
uint16_t maske;
maske = (((uint16_t)CANSIT1) << 8) | CANSIT2;
// Wenn alle 32 Bit der Bitmaske 0 sind dann ist ein Fehler
aufgetreten
if(maske == 0)
{
return NOMOB;
}
// Die Bitmaske wird so lange nach rechts geschoben, bis Bit0 eine 1
hat.
// Die Anzahl der Schiebeoperatoren gibt somit die Nummer
// Des MOBs zurück
for( mob=0; (maske & 0x01)==0; maske >>= 1, ++mob);
// Kontrolle: Wenn mob größer als die Anzahl der verfügbaren
// Message Objects ist das Ergebnis falsch
if ( mob > 14 )
{
return NOMOB;
}
else
{
return mob;
}
}
Für nen kleinen Tip wäre ich dankbar!
Grüße,
Sven
Datum:
hallo, ich habe die lib eingebunden, sehr übersichtlich und gut dokumentiert hut ab :-) habe ein programm(main) entwickelt, wobei ein sender realisiert werden soll. dazu hab ich das oben stehende beispiel genommen. nun wird aber beim can send gewartet das die nachricht vollständig versendet wurde (TXOK)... leider tut sich da sonst garnichts. mit dem tipp von sinotech, den txok interrupt deaktivieren hatte ich leider auch keinen erfolg :( verwenden tue ich das avr-can entwicklerboard von olimex mit fertigen at90can128 und mcp2551 drauf. am sub-d liegen saubere 2,5V an, jedoch ist keine kommunikation festzustellen. ich hoffe mir kann jemand vllt helfen danke im voraus liebe grüße ps: verbesserungsvorschlag: can.c benötigt einen include von can.h und im header file sollten headerguards also ifndef zb benutzt werden um compilierungsfehler zu vermeiden(das war auch eins meiner anfangsprobleme)
Datum:
Hallo, mit der CAN-Lib.rar kann ich ja anhand des RS232 Schnittstelle mein Datentransfer beobachten und auch was senden können? Wenn ich das richtig verstanden habe, sollte ich mit "b" oder "B" eine Nachricht an Modul B mit der Message ID 0x316 senden? Wenn ich das Programm starte erscheint auf dem Hyperterminal "Controller A online, yes we CAN........und der Compilier-Datum usw. " was ja auch alles richtig ist, aber Senden mit dem Hyperterminal funktioniert nicht. Ich logge mit dem Peak Dongle mit und bekomme keine CAN Nachricht? CAN-Baustein ist aber "wieder" 100% in Ordnung und funktioniert. Kann mir da Jemand weiter helfen? Grüße
Datum:
Hat sich erledigt. Mit HTerm klappt es.
Datum:
Ich habe noch immer das Problem zwischen dem AT90CAN128 und dem MCP2515 das sobald der AT90CAN128 aktiv geht das Netzwerk der funktionierenden MCP2515-er zusammenbricht... Hat jemand eine Idee woran es liegen könnte?
Datum:
Ich wage mich auch an ein CAN Projekt. Durch diesen Thread spare ich mir sehr viel Zeit. Nochmal ein Dankeschön an Marco Glietsch und alle Leute die diese Bibliothek optimiert und verbessert haben. Ich finde das Klasse von euch! Gute Arbeit! Beste Grüsse Dominik
Datum:
@Tim R.
ich hatte das selbe Problem und habe es mit einem Timeout und einem Flag
für den Timeout gelöst.
.
.
.
// Warten bis die Datenübertragung beendet ist (TXOK-Flag von
CAN-Controller
// gesetzt)
Timeout(0, 1, 50);
//while (!getbit(CANSTMOB, TXOK));
while(Timeout(0, 0, 50) == 0)
{
if (!getbit(CANSTMOB, TXOK))
{
CAN_ERR = 1;
}
else
{
CAN_ERR = 0;
break;
}
}//end while
// TXOK-Flag von Hand löschen
clearbit(CANSTMOB, TXOK);
.
.
.
/*********** TIMEOUT
************************************************************************
*********************************/
uint8_t Timeout (uint8_t timeout_array, uint8_t set_Timeout, uint16_t
Timeout)
{
if (set_Timeout == 1)
{
tmp_systemtime[timeout_array] = systemtime;
}//end if
if (systemtime >= (tmp_systemtime[timeout_array] + Timeout)) //An
Funktion "1" zurückgeben, wenn Timeout erreicht wurde
{
return 1;
}//end if
else //(millisekunden < Timeout_erreicht) //An Funktion "0"
zurückgeben, wenn Timeout nicht erreicht wurde
{
return 0;
}//end else
}//end Timeout
Datum:
Anbei noch ein paar Bugfixes um mehrere, gleichzeitig ausgelöste RX IRQ
MOBS zu handeln (bisher wurde immer nur das höchst priorisierte MOB
behandelt):
//Anzahl der ausgelösten MOB IRQ's ermitteln
uint8_t get_mob_irqs(void)
{
uint8_t n, mobirqs;
uint16_t bitpos, mobirqreg;
bitpos = 1;
mobirqs = 0;
mobirqreg = CANSIT2 | (uint16_t)(CANSIT1<<8);
//Anzahl der ausgelösten MOB IRQ's ermitteln
for (n=0; n<15; n++)
{
bitpos<<=1;
if ((mobirqreg & bitpos) == bitpos) mobirqs++;
}//end Anzahl der ausgelösten MOB IRQ's ermitteln
return mobirqs;
}
// Rückgabe: uint8_t mob: Nummer des Objekts
// Funktion ermittelt, welches Objekt Interrupt ausgeloest hat
uint8_t can_get_mob_interrupt(uint8_t lastmob)
{
uint8_t mob, n;
uint16_t maske, filter_maske;
maske = CANSIT2 | (uint16_t)(CANSIT1 << 8);
filter_maske = 1;
//Filtermaske erstellen, um das vorhergegangene MOB nicht erneut
abzurufen
for(n=0; n<lastmob; ++n)
{
filter_maske <<= 1;
}
//Vorheriges ausgelöstes MOB löschen
maske &=~filter_maske;
// Wenn alle 32 Bit der Bitmaske 0 sind dann ist ein Fehler
aufgetreten
if(maske == 0)
{
return NOMOB;
}
// Die Bitmaske wird so lange nach rechts geschoben, bis Bit0 eine 1
hat.
// Die Anzahl der Schiebeoperatoren gibt somit die Nummer des MOBs
zurück
for(mob=0; (maske & 0x01)==0; maske >>= 1, ++mob);
//Prüfen, ob das
// Kontrolle: Wenn mob größer als die Anzahl der verfügbaren
// Message Objects ist das Ergebnis falsch
if(mob > 14)
{
return NOMOB;
}
return mob;
}
// Interrupt für Empfang einer Nachricht
ISR (CANIT_vect)
{
uint8_t save_canpage, n, i, cnt_mobirq, mob, lastmob;
// Aktuelle CANPAGE sichern
save_canpage = CANPAGE;
lastmob = 0;
// Index aller MOB ermitteln, welche den Interrupt ausgelöst haben
cnt_mobirq = get_mob_irqs();
// MOB Daten holen und abspeichern
for(n=0; n<=cnt_mobirq; n++)
{
mob = can_get_mob_interrupt(lastmob);
// Falls es kein gültiges MOB war, Daten holen abbrechen
if(mob != NOMOB)
{
// Objekt das den Interrupt ausgelöst hat holen
can_get_mob(mob);
// XXX hier eintragen, was bei einem interrupt passieren soll XXX
// Id der Nachricht holen und Daten des MOBs aus CANMSG auslesen
//id = can_get_id();
can_get_data(receive_can);
//Daten aus aktuellem MOB
for (i = 0; i < 8; i++)
{ /* 15 Zeilen, 8 Spalten */
can_byte_by_mob[mob][i] = receive_can[i];
//Daten aus RX MOB in can byte schreiben
}//end send_can füllen
}//end Falls es kein gültiges MOB war, Daten holen abbrechen
lastmob = mob;
//Ausgelesenes MOB updaten
}//MOB Daten holen und abspeichern
// RXOK-Flag löschen
clearbit(CANSTMOB, RXOK);
// MOB auf Empfang und CAN 2.0B Standard setzen
can_set_mode(CAN_MODE_RECEIVE_DATA);
// CANPAGE wiederherstellen
CANPAGE = save_canpage;
//IRQ_CAN_RX = 1;
}//end CAN_Interrupt handle
Zudem war im Modul disable MOB noch ein kleiner Fehler, hier die
Korrektur:
// Parameter: uint8_t mob: Nummer des Objekts (0-14)
// Funktion löscht den Interrupt für das jeweilige Objekt
void can_clear_mob_interrupt(uint8_t mob)
{
if (mob < 8) { clearbit(CANIE2, iemob[mob]); }
else { clearbit(CANIE1, iemob[mob]); }
}
Datum:
Hallo Miteinander! Ich bin soeben zu folgendem Ergebnis gekommen. Ich habe Marco Glietsch's Bibliothek auf verschiedenen IDE's getestet. AVR-Studio 5.0 -> mit Erfolg CAN Nachrichten senden/empfangen AVR-Studio 5.1 -> ohne Erfolg keine CAN Nachrichten senden/empfangen AVR-Studion 6 -> ohne Erfolg keine CAN Nachrichten senden/empfangen Ich habe dieses Bibliothek 1 zu 1 in den jeweiligen Studio's kompilieren lassen und die Hex-File übertragen (JTAGICE mkII). Die Übersetzung erfolgt bei allen IDE's ohne Probleme nur nach dem übertragen auf den AT90CAN64 kommt es zu dem o.g. Ergebnis. Kann von Euch dieses Problem noch jemand bestätigen. Wenn ja, dann sollte man dies als BUG weitermelden. Besten Dank im Voraus für die Antworten! Gruß
Datum:
Angehängte Dateien:Hallo Schorsch, ich konnte bisher mit allen AT-Studios meine gemoddete CAN-lib compilieren. Ich hatte nur das Prob, dass mein JTAG ICE 3 nicht so richtig wollte (is immer ab einer gewissen Stelle im Run-Mode geblieben). Anbei mal meine libs. Viele Grüße
Datum:
Hallo, wir benutzen die Bibliothek von Marco Glietsch und wollten diese mit der standart ID (11 bit 2.0a) verwenden. Mit den Patches von Werner A sind wir leider nicht weiter gekommen. Der At90can128 (in Kombination mit PCA 82C250) sendet immer noch mit der extended ID (29 bit). Hat jemand eine fertige lib für die standart ID? Über Hilfe würden wir uns sehr freuen, viele Grüße
Datum:
Guten Tag @garphi Ich würde gerne deine gemoddete Lib testen... jedoch sagt der compiler das folgende h. fehlen #include "Globals.h" #include "Timer.h" sind diese wichtig für das programm?!
Datum:
ich habe folgende Problem: das versenden von Datensätze zwischen µC (A) und µC (B) funktioniern ganz gut, sobald ich eine 3. µC (C) dazu schalte, bricht die kominiklation zwischen A und B ab. sobald ich das C ausschalte steht die kominikation wieder da.
Datum:
hey lilhill welchen version von Atmel studio verwendest du ???
Datum:
ich verwende den Atmel Studio 6 (Version 6.0.1843)
Datum:
Welche Lib verwendest du???
Datum:
Hallo garphi, vielen Dank für Deine Antwort (03.08.12) und Deiner Library. Ich hätte noch eine Bitte an Dich. Könntest Du bitte noch die "Global.h" und Deine "Timer.h" mit zur ZIP-Datei anfügen. Besten Dank im Voraus! Gruß
Datum:
Hi Schorsch,
die Global.h brauchst du nicht da sollte nichts drin sein was für die
lib wichtig ist. So wie ich das sehe wird nur das array
uint8_t can_byte_by_mob[15][8];
benutzt.
in der Timer.h ist die Funktion timeout und rx_timeout
kan man sich sehr einfach nachbauen.
z.B.
/***********************************************************************
*/
/* tiemerNum ist die Position im array für die Softtimer
*/
/* timeout ist der einzuhaltende Timeout (abhängig von mscounter)
*/
/* wenn die Variable Timeout einen Wert größer 0 hat wird dieser zum
*/
/* laden des timers genutzt bei Wert = 0 wird abgetragt
*/
/* millis ist ein Variable die in der Timer0 ISR hochgezählt wird
*/
/***********************************************************************
*/
bool timeout (uint8_t timerNum, uint16_t Timeout)
{
static uint64_t timeout_array[NO_MOBS];
if (Timeout != 0)
{
timeout_array[timerNum] = Timeout + millis;
return false;
}
else if (timeout_array[timerNum] > millis)
{
return false;
}
else
{
return true;
}
}//end Timeout
in der ISR für Can Nachrichten wird die Schleife:
---
// MOB Daten holen und abspeichern
for(n=0; n <= cnt_mobirq; n++)
---
zu oft durchlaufen da muss ein < hin, denke ich.
In den can_send_data sollte noch ein Parameter für die id mit drin sein,
würde es schlanker machen. Diese ID muss alldrings genauso wie der mode
wieder hergestellt werden.
Meine Version:
Autor: garphi (Gast)
Datum: 03.08.2012 14:07
VG Thomas
Datum:
Angehängte Dateien:Hallo zusammen
kann mir jemand helfen?
Habe aktuell 2 Probleme einmal sendet mein Board immer eine leere und
eine richte Botschaft. Hatte ich weiter oben schon gelesen hat aber
nicht funktioniert.
So sende ich die Daten:
can_init(4, 0, 0);
can_enable_mob(0, 1, 0x70E, 0xffffffff);
sleep(1000);
can_send_data(0, 8, data);
Wenn ich die beiden letzten Zeilen umdrehe kommen zwei leere Botschaften
can_init(4, 0, 0);
can_enable_mob(0, 1, 0x70E, 0xffffffff);
can_send_data(0, 8, data);
sleep(1000);
Wie ich oben gelesen habe kommt es vom can_enable_mob.
Die Can Botschaften prüfe ich mit CanOe.
Über Hilfe würd ich mich tierisch freuen.
Gruß
Daniel
Datum:
Ich versuche es mal mit Hilfe. ;)
can_init initialisiert alles mit (0) also msg und length.
can_enable_mob setzt den mode dabei wird leider, warum auch immer, eine
Nachricht verschickt. Ist bei mir auch so, wenn ich da mehr weiß werde
ich es posten.
can_send_data verschickt die eigentliche Nachricht.
das heißt jedes init baut eine leere Nachricht und das en_mob schickt
los.
Generell init und can_enable_mob nur einmal und nicht in der while !!!
Für dich als Lösung 1:
####################
can_init(4, 0, 0);
// mob: 0, modus: senden, id 3, idm 0xffffffff
can_enable_mob(0, 1, 0x70E, 0xffffffff);
while(1){
while ( !(PINE & (1 << PE5)) ) {
can_send_data(0, 8, data);
sleep(1000);
}
}
####################
Jetzt wird die "leere" Nachricht nur einmal geschickt (in Zeile 3) und
anschließend nur noch data.
Wenn du das auch nicht möchtest.
Lösung 2
(nimm alles aus der en_mob ausser das can_set_mode)
####################
can_init(4, 0, 0);
// mob: 0, modus: senden, id 3, idm 0xffffffff
// can_enable_mob(0, 1, 0x70E, 0xffffffff);
uint8_t mob = 0;
uint32_t id = 0x70E;
uint32_t idm = 0xffffffff
// Objekt wählen
can_get_mob(mob);
// Interrupt für dieses Objekt aktivieren
can_set_mob_interrupt(mob);
// ID-Maske setzen
can_set_id_mask(idm);
// ID setzen
can_set_id(id);
while(1){
while ( !(PINE & (1 << PE5)) ) {
can_send_data(0, 8, data);
sleep(1000);
}
}
####################
Habe ich nicht getestet aber sollte so gehen.
Gruß Thomas
Datum:
Hallo Thomas danke für die Hilfe. Habe es mit der letzten LIB auch hinbekommen da macht es es nicht. can_init muss in die Schleife da ich knapp 80 id anspreche in knapp 9 sec da ich theoretisch 80 stg anspreche um einen Dienst auszuführen. Hab schon das zweite Projekt am laufen. Da hab ich aber das Problem wie schon von Autor: SinoTech (Gast) am Datum: 10.01.2011 01:46 mit der Lösung beschrieben, das wenn kein Empfänger da ist man in ner schleife hängen bleibt. Beim mir hilft diese Lösung aber nicht. Hat jemand noch ne Lösung dazu? Gruß Daniel
Datum:
Hi Daniel, can_init hat nichts mit den ids zu tun. can_init wird einmal aufgerufen und initialisiert den can controller. can_enable_mob setzt die mob id. wenn du zeit sparen willst kannst du in der while anstelle von can_enable_mob => can_set_id nutzten. das hängenbleiben beim send ohne Empfänger ist richtig geht mit einen timeout für die while zu lösen. while (!getbit(CANSTMOB, TXOK)); <= ohne Empfänger endlos. Gruß Thomas
Datum:
Hallo Thomas danke für die Hilfe, hat bei dem Problem geholfen. Was ich noch sagen muss ich finde das Forum klasse und es wird immer einem geholfen. Die Can Lib find ich genial, simpel und gut erklärt. So macht der Proggen Spaß. Gruß Daniel
Datum:
Hallo, ich habe mal ein paar Verständnisfragen. Laut Datenblatt (S.261 Register: CANSTMOB Bits: TXOK und RXOK) wird ein MOB nach dem Senden oder Empfangen wieder disabled. Also muss ich es vor jedem Senden wieder auf Senden stellen bzw. nach dem Empfangen wieder auf Empfang (CAN_setMode()). Beim Senden sehe ich so etwas in der Art in der Funktion CAN_sendData(), beim Empfangen sehe ich es nicht... Müsste ja irgendwo im Interrupt zu finden sein denke ich. Bleiben denn die anderen Einstellungen der MOBs beim Disablen erhalten? Wenn ich etwas empfange, wird doch die Filter-ID mit der Empfangenen ID überschrieben. Also muss ich danach wieder die Filter-ID neu setzen, wenn ich filtern möchte, oder? Im Beispiel werden leider keine ID-Filter verwendet. Wie wirkt sich das mit der MOB Priorität aus, wenn ich mehrere MOBs auf den Empfang unterschiedlicher IDs konfiguriere? Kann es passieren, dass ein höher priorisierter MOB ein anderes lahm legt? Danke für Hinweise!
Datum:
Hi Horst, Welche Version nimmst du ? Also von wann. Meine Anmerkungen beziehen sich auf : --- Autor: garphi (Gast) Datum: 03.08.2012 14:07 Angehängte Dateien: Clibs.zip (5,2 KB, 76 Downloads) --- Horst schrieb: > Hallo, > > ich habe mal ein paar Verständnisfragen. > > Laut Datenblatt (S.261 Register: CANSTMOB Bits: TXOK und RXOK) wird ein > MOB nach dem Senden oder Empfangen wieder disabled. > Also muss ich es vor jedem Senden wieder auf Senden stellen bzw. nach > dem Empfangen wieder auf Empfang (CAN_setMode()). > Beim Senden sehe ich so etwas in der Art in der Funktion CAN_sendData(), > beim Empfangen sehe ich es nicht... Müsste ja irgendwo im Interrupt zu > finden sein denke ich. Ist auch enthalten in der ISR vorletzter Befehl // MOB auf Empfang und CAN 2.0B Standard setzen can_set_mode(CAN_MODE_RECEIVE_DATA); > Bleiben denn die anderen Einstellungen der MOBs beim Disablen erhalten? Jop. > > Wenn ich etwas empfange, wird doch die Filter-ID mit der Empfangenen ID > überschrieben. Also muss ich danach wieder die Filter-ID neu setzen, > wenn ich filtern möchte, oder? Richtig. > Im Beispiel werden leider keine ID-Filter verwendet. > > Wie wirkt sich das mit der MOB Priorität aus, wenn ich mehrere MOBs auf > den Empfang unterschiedlicher IDs konfiguriere? > Kann es passieren, dass ein höher priorisierter MOB ein anderes lahm > legt? Die Filter werden der Reihe nach durchlaufen wenn du mit MOB 14 nur die ID 100 haben willst und mit MOD 1 die ID's 50..200 dann ist der letzt nutzlos. Wenn eine ID von einem Filter angenommen wird gilt die Nachricht als abgearbeitet. > > Danke für Hinweise! Gruß Thomas
Datum:
Thomas Schulz schrieb: > Welche Version nimmst du ? Ich beziehe mich auf: _____________________ Autor: MatMar (Gast) Datum: 02.12.2009 21:25 Angehängte Dateien: CAN-Lib.rar (8,2 KB, 794 Downloads) _____________________ Hatte den Beitrag nach .rar durchsucht und nicht nach .zip Bei dem von dir genannten Code ist es in der Tat drin. Ich hatte ja vermutet, dass es rein muss. Der von mir angesehene Code scheint wohl sehr auf das Beispiel zugeschnitten zu sein (ohne ID-Filterung). Ok, danke. Das erklärt dann vermutlich, warum es bei mir mit anderen CAN Funktionen noch nicht richtig geht. Hatte den Effekt, das beim zweiten Senden einer Nachricht die Filter wieder wirkungslos waren. Muss dann wohl die Filter-ID wieder neu setzen. Das ist bei dem von dir genannten Code dann aber auch nicht drin... Gruß Horst
Datum:
Hi Horst, ich habe es so gemacht das ich ein MOD nur zum senden nutzte und mit den anderen empfange. ich brauch aber auch lange keine 14 MOB's. Gruß Thomas
Datum:
Was macht das IDEMSK Bit im Page Register CANIDM4 eigentlich? Mein Problem ist, dass ID 0x00000202 als 29Bit ID und ID 0x202 als 11Bit ID beide meinen Filter passieren und dann in Software anhand des IDE Bits in CANCDMOB unterschieden werden müssen. Wie kann ich festlegen, dass nur 11Bit IDs meinen Empfangsfilter passieren?
Datum:
Ok, ich kann meine Frage jetzt selber beantworten. Beim Konfigurieren eines MOB sage ich mit
CANIDM4 = (1 << IDEMSK); |
dass es mir nicht egal ist, was (11 oder 29Bit-ID) ich empfangen möchte. Was ich empfangen möchte wird mit dem IDE Bit angegeben.
CANCDMOB |= (1 << IDE); |
Sagt, dass ich eine extended Nachricht (29Bit-ID) empfangen möchte.
CANCDMOB &= ~(1 << IDE); |
Sagt, dass ich eine Standard Nachricht (11Bit-ID) empfangen möchte. Oder ich lasse diese Zeile weg, wenn CANCDMOB vorher mit 0 initialisiert wurde. Wenn ich sowohl extended als auch Standard Nachrichten empfangen möchte, ist es mir also egal und ich kann den Vergleich auf TRUE zwingen mit:
CANIDM4 &= ~(1 << IDEMSK); |
Also indem ich sicher stelle, dass das IDEMSK Bit nicht gesetzt ist. Das ist also das gleiche Prinzip wie bei den Filter-IDs. Die empfangene Nachricht überschreibt die Konfiguration (CANIDT1 bis CANIDT4, setzt ggf. das IDE Bit, usw.) und danach muss man das MOB neu konfigurieren. Das ist aus dem Datenblatt schwer heraus zu lesen. Und auch aus Beispielcode hat es eine ganze Weile gedauert. Geholfen hat mir letztendlich die Lib von KreativesChaos (at90can_set_dyn_filter.c):
// ---------------------------------------------------------------------------- /* * Copyright (c) 2007 Fabian Greif, Roboterclub Aachen e.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: at90can_set_dyn_filter.c 6837 2008-11-16 19:05:15Z fabian $ */ // ---------------------------------------------------------------------------- #include "at90can_private.h" #ifdef SUPPORT_FOR_AT90CAN__ // ---------------------------------------------------------------------------- bool at90can_set_filter(uint8_t number, const can_filter_t *filter) { if (number > 14) { // it is only possible to serve a maximum of 15 filters return false; } // set CAN Controller to standby mode _enter_standby_mode(); CANPAGE = number << 4; CANSTMOB = 0; CANCDMOB = 0; #if SUPPORT_EXTENDED_CANID if (filter->flags.extended == 0x3) { // extended identifier CANIDT4 = (uint8_t) filter->id << 3; CANIDT3 = filter->id >> 5; CANIDT2 = filter->id >> 13; CANIDT1 = filter->id >> 21; CANIDM4 = ((uint8_t) filter->mask << 3) | (1 << IDEMSK); CANIDM3 = filter->mask >> 5; CANIDM2 = filter->mask >> 13; CANIDM1 = filter->mask >> 21; CANCDMOB |= (1 << IDE); } else { CANIDT4 = 0; CANIDT3 = 0; CANIDT2 = (uint8_t) filter->id << 5; CANIDT1 = (uint16_t) filter->id >> 3; if (filter->flags.extended) { CANIDM4 = (1 << IDEMSK); // receive only standard frames } else { CANIDM4 = 0; // receive all frames } CANIDM3 = 0; CANIDM2 = (uint8_t) filter->mask << 5; CANIDM1 = (uint16_t) filter->mask >> 3; } #else CANIDT4 = 0; CANIDT3 = 0; CANIDT2 = (uint8_t) filter->id << 5; CANIDT1 = (uint16_t) filter->id >> 3; CANIDM4 = (1 << IDEMSK); CANIDM3 = 0; CANIDM2 = (uint8_t) filter->mask << 5; CANIDM1 = (uint16_t) filter->mask >> 3; #endif if (filter->flags.rtr & 0x2) { CANIDM4 |= (1 << RTRMSK); if (filter->flags.rtr & 0x1) CANIDT4 |= (1 << RTRMSK); // only RTR-frames } CANCDMOB |= (1<<CONMOB1); _enable_mob_interrupt(number); // re-enable CAN Controller _leave_standby_mode(); return true; } #endif // SUPPORT_FOR_AT90CAN__ |
Datum:
Hallo zusammen,
nach mehrmaligem Lesen dieses Beitrages habe ich das Problem, welches
schon von Arno Schulz am 11.03.2009 mit der Lib von Marco Glietsch
beschrieben wurde:
1. Nach RESET wird jedes MoB bei Erstbenutzung doppelt gesendet
2. Wenn zwei CAN-Knoten zeitgleich eine Nachricht senden, kommt die
höhere Priorität ID auf den Bus und vom den anderen Knoten kommen die
Nachrichten sporadisch bzw. altenieren und dann doppelt durch.
Wenn ich richtig gelesen habe, liegt es wohl an der folgenden Funktion:
void CAN_sendData(uint8_t mob, uint8_t * data, uint8_t length){
uint8_t mode;
CAN_getMOB(mob); // Objekt wählen
mode = CAN_getMode(); // Aktuelle Betriebsart sichern
CAN_setData(data, length); // Nutzdaten in Register schreiben
CAN_setMode(TRANSMIT_DATA); // Datenübertragung starten
while (!getbit(CANSTMOB, TXOK)); // Warten bis die Datenübertragung
beendet ist (TXOK-Flag von CAN-Controller gesetzt)
clearbit(CANSTMOB, TXOK); // TXOK-Flag löschen
CAN_setMode(mode); // Alte Betriebsart wiederherstellen
}
Gibt es hierfür eine Lösung? Die im Beitrag beschriebenen Lösungsansätze
haben nicht leider funktioniert.
Vielen Dank für eure Unterstützung!
Datum:
Hi Sebastian, das Problem hatte ich auch, bei mit war es der Ablauf beim setzten für senden oder empfangen. CAN_setMode(TRANSMIT_DATA); setzten das Register des MOB's. CANCDMOB wird das Register beschrieben hat es zur Folge das ein Nachricht senden angestoßen wird. Schau dir mal den Ablauf an im Debugger und dann kannst du zuschauen das gesendet wird und an welche Stelle. Wenn das nicht Hilft kann ich dir auch meine Version von CAN_setMode geben. (habe ich nur gerade nicht auf diesen Rechner) Gruß Thomas
Datum:
Hallo Thomas, Danke für Deine Unterstützung. Ich bin in der Zwischenzeit auf die Lib vom Roboterclub Aachen e.V. umgestiegen. Dadurch haben sich die Probleme erledigt. Bei Start werden keine Nachrichten doppelt gesendet, wenn mehrere CAN-Knoten zeitgleich senden kommen alle Nachrichten richtig auf den Bus (das war ja mein Hauptproblem). Zusätzlich ist mir positiv aufgefallen, dass nun die Interrupts bei fehlender Quittierung nicht mehr blockiert werden. Denn ich hatte auch das Problem, dass dann die RS232 blockiert war. Gruß, Sebastian
