Forum: Projekte & Code CAN-Bibliothek für den at90CAN128 und das AVRStudio


von Marco G. (mg-programmer)


Angehängte Dateien:

Lesenswert?

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

von Werner A. (homebrew)


Lesenswert?

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

von Marco G. (mg-programmer)


Angehängte Dateien:

Lesenswert?

Ok, hier nochmal die Version mit ausgelagerten Funktionen.
Ich würde mich über Anregungen, Verbesserungen oder einfach nur eine 
Rückmeldung freuen...

Gruß Marco

von Gerhard (Gast)


Lesenswert?

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

von Marco G. (mg-programmer)


Lesenswert?

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:
1
main(){
2
  CAN_init (1000 , TX );
3
4
  // Zu sendende Daten
5
  CAN_message msg ;
6
  msg.id = 0 x12345678 ;
7
  msg.idm = 0 xffffffff ;
8
  msg.data [0] = 0 x11 ;
9
  msg.data [1] = 0 x22 ;
10
  msg.data [2] = 0 x33 ;
11
  msg.data [3] = 0 x44 ;
12
  msg.data [4] = 0 x55 ;
13
  msg.data [5] = 0 x66 ;
14
  msg.data [6] = 0 x77 ;
15
  msg.data [7] = 0 x88 ;
16
17
  // Objekt 0 auf Empfang setzen
18
  CAN_enableMOB (0, RECEIVE_DATA , msg );
19
20
  // Daten ¨uber Objekt 0 senden
21
  CAN_sendData (0, msg . data );
22
23
  while(1){}
24
}

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

von timo (Gast)


Lesenswert?

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

von Marco G. (mg-programmer)


Lesenswert?

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:
1
Für den Sender:
2
    #include "can.h"
3
    // Sonstige benötigte Bibliotheken
4
5
    // Hauptprogramm
6
    Int main(){
7
      CAN Nachrichtenobjekt erstellen
8
      CAN_message    msg1;
9
10
      ////////////////////////////////////////////////////////
11
      // Hier schreibst du deinen eigenen Programmcode rein //
12
      ////////////////////////////////////////////////////////
13
14
      // CAN initialisieren
15
      CAN_init(1000, RX);
16
17
      // Interrupts aktivieren
18
      sei();
19
20
      // ID-Maske festlegen
21
      msg1.idm      = 0xffffffff;  // Es kommt nur genau dieselbe ID durch
22
23
      // Endlosschleife. Fragt zyklisch deinen Port ab und sendet die Schalterstellungen
24
      while(1){
25
        // Schalterstellungen im ersten Datenbit abspeichern
26
        msg1.data[0]  = PORTA;
27
    
28
        // ID festlegen (1)
29
        msg1.id    = 0x00000001;
30
31
        // Objekt 0 aktivieren und Daten übergeben
32
        CAN_enableMOB(0, RECEIVE_DATA, msg1);
33
34
        // Daten senden
35
        CAN_sendData(0, msg1.data);
36
      }
37
38
      return 1;
39
    }
Für den Empfänger:
1
    #include "can.h"
2
    // Sonstige benötigte Bibliotheken
3
4
    // Hauptprogramm
5
    Int main(){
6
      CAN Nachrichtenobjekt erstellen
7
      CAN_message    msg1;
8
9
      ////////////////////////////////////////////////////////
10
      // Hier schreibst du deinen eigenen Programmcode rein //
11
      ////////////////////////////////////////////////////////
12
13
      // CAN initialisieren
14
      CAN_init(1000, RX);
15
16
      // Interrupts aktivieren
17
      sei();
18
19
      // ID-Maske festlegen
20
      msg1.idm      = 0xffffffff;  // Es kommt nur genau dieselbe ID durch
21
22
      // ID festlegen
23
      msg1.id      = 0x00000001;  // Selbe ID wie im Sender
24
25
      // Endlosschleife.
26
      while(1){
27
      }
28
29
      return 1;
30
    }
31
32
    //////////////////////////////////////////////////////////////////////////////
33
    //                          //
34
    // Funktion:    SIGNAL()                //
35
    //                          //
36
    // Beschreibung:   Interrupt für den Empfang einer Nachricht.      //
37
    //                          //
38
    //////////////////////////////////////////////////////////////////////////////
39
    SIGNAL(SIG_CAN_INTERRUPT1){
40
    uint8_t    save_canpage;
41
     static    CAN_message message;
42
43
    // Aktuelle CANPAGE sichern
44
     save_canpage  = CANPAGE;
45
    
46
    // Index des MOB ermitteln, der den Interrupt ausgelöst hat
47
    uint8_t mob   = CAN_getMOBInterrupt();
48
    
49
    // Falls es kein gültiges MOB war abbrechen
50
    if(mob == NOMOB){
51
      return;
52
    }
53
54
    // Objekt das den Interrupt ausgelöst hat holen
55
    CAN_getMOB(mob);
56
    
57
    // Daten des MOBs aus CANMSG auslesen
58
    message      = CAN_getData();
59
  
60
    // Id der Nachricht holen
61
    message.id    = CAN_getID();
62
63
64
    //////////////////////////////////
65
    // Daten verarbeiten / ausgeben //
66
    //////////////////////////////////
67
  
68
    // Hier verarbeitest du deine empfangenen Daten
69
    // Wären deine LEDs auf Port A dann steuerst du sie so an
70
71
    PORTA  = message.data[0];  // Nutzdaten aus 1. Byte verarbeiten
72
73
    //////////////////////////////////
74
    // Daten verarbeiten / ausgeben //
75
    //////////////////////////////////
76
77
78
    // RXOK-Flag löschen
79
    clearbit(CANSTMOB, RXOK);
80
    
81
    // MOB auf Empfang und CAN 2.0B Standard setzen
82
    CAN_setMode(RECEIVE_DATA);
83
    
84
    // CANPAGE wiederherstellen
85
    CANPAGE    = save_canpage;
86
  }

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

von timo (Gast)


Lesenswert?

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.

von Werner A. (homebrew)


Angehängte Dateien:

Lesenswert?

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.
1
SIGNAL(SIG_CAN_INTERRUPT1){
2
  uint8_t    save_canpage;
3
   static    CAN_message message;
4
5
  // Aktuelle CANPAGE sichern
6
   save_canpage  = CANPAGE;
7
8
    // Index des MOB ermitteln, der den Interrupt ausgelöst hat
9
  uint8_t mob   = CAN_getMOBInterrupt();
10
11
12
    if (LED2)
13
    LED2 = 0;
14
    else
15
    LED2 = 1;
16
   ...

Im main.c habe ich mit
1
   CAN_message msg0, msg1;
2
   CAN_init(83, RX);
3
   msg1.idm      = 0xffffffff;             // Es kommt nur genau dieselbe ID durch
4
   msg1.id      = 0x0B;                    // Selbe ID wie im Sender
5
   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

von Werner A. (homebrew)


Lesenswert?

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

von Werner A. (homebrew)


Lesenswert?

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:
1
//////////////////////////////////////////////////////////////////////////////////
2
//                                                                              //
3
// Funktion:        CAN_setIDMask()                                             //
4
//                                                                              //
5
// Parameter:       uint32_t idm    - ID-Maske in Dezimalschreibweise           //
6
//                                                                              //
7
// Rückgabe:        1               - Maske erfolgreich eingestellt             //
8
//                                                                              //
9
// Beschreibung:    Diese Funktion setzt die ID-Maske eines Objekts auf einen   //
10
//                  neuen Wert. In CANIDM4 bleiben dabei die Werte der unteren  //
11
//                  3 Bit (RTRTAG, Reserved und IDEMSK) erhalten.               //
12
//                                                                              //
13
//////////////////////////////////////////////////////////////////////////////////
14
int CAN_setIDMask(uint32_t idm){
15
16
    if (!getbit(CANCDMOB, IDE)){            //Standart identifier (11 bit)
17
       CANIDM2 = (uint8_t)(idm << 5); 
18
       CANIDM1 = (uint8_t)(idm >> 3);
19
    }
20
    else{                                   //extended identifier
21
       idm      <<= 3;
22
       idm      |= 7;
23
24
       CANIDM4 = (unsigned char) (idm);
25
       CANIDM3 = (unsigned char) (idm>>8);
26
       CANIDM2 = (unsigned char) (idm>>16);
27
       CANIDM1 = (unsigned char) (idm>>24);
28
   }
29
    return 1;
30
}
31
32
33
34
//////////////////////////////////////////////////////////////////////////////////
35
//                                                                              //
36
// Funktion:        CAN_setID()                                                 //
37
//                                                                              //
38
// Parameter:       uint32_t id     - ID in Dezimalschreibweise                 //
39
//                                                                              //
40
// Rückgabe:        1               - ID erfolgreich eingestellt                //
41
//                                                                              //
42
// Beschreibung:    Diese Funktion setzt die ID eines Objekts auf einen         //
43
//                  neuen Wert. In CANIDM4 bleiben dabei die Werte der unteren  //
44
//                  3 Bit (RTRTAG, RB1TAG und RB0TAG) erhalten.                 //
45
//                                                                              //
46
//////////////////////////////////////////////////////////////////////////////////
47
int CAN_setID(uint32_t id){
48
49
    if (!getbit(CANCDMOB, IDE)){            //Standart identifier (11 bit)
50
         CANIDT2 = (uint8_t)(id << 5); 
51
         CANIDT1 = (uint8_t)(id >> 3);
52
    }
53
    else{                                   //extended identifier
54
        id      <<= 3;
55
        id      &= 0xfffffff8;
56
        id      |= (CANIDT4 & 0x07);
57
58
        CANIDT4 = (unsigned char) (id);
59
        CANIDT3 = (unsigned char) (id>>8);
60
        CANIDT2 = (unsigned char) (id>>16);
61
        CANIDT1 = (unsigned char) (id>>24);
62
    }
63
    return 1;
64
}
65
66
67
68
//////////////////////////////////////////////////////////////////////////////////
69
//                                                                              //
70
// Funktion:        CAN_getID()                                                 //
71
//                                                                              //
72
// Parameter:                                                                   //
73
//                                                                              //
74
// Rückgabe:        uint32_t                - ID der empfangenen Nachricht      //
75
//                                                                              //
76
// Beschreibung:    Diese Funktion holt die ID der empfangenen Nachricht.       //
77
//                                                                              //
78
//////////////////////////////////////////////////////////////////////////////////
79
uint32_t CAN_getID(){
80
   uint32_t id;
81
   id = 0;
82
   if (!getbit(CANCDMOB, IDE)){            //Standart identifier (11 bit)
83
      id  = (uint8_t)  CANIDT2 >> 5;
84
      id |= (uint16_t) CANIDT1 << 3;
85
    }
86
    else{                                   //extended identifier
87
      id |= ((uint32_t) CANIDT1<<24);
88
      id |= ((uint32_t) CANIDT2<<16);
89
      id |= ((uint32_t) CANIDT3<<8);
90
      id |= (CANIDT4&0xF8);
91
      id >>= 3;
92
    }
93
    return id;
94
}

von Ruslan K. (idrisk)


Lesenswert?

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ß

von Michael (Gast)


Lesenswert?

Unter welcher Lizenz steht der Quellcode? Darf ich deinen Code in einem 
GPL-Projekt verwenden?

von Marco G. (mg-programmer)


Lesenswert?

Hallo Michael,

klar darfst du den Code für dein Projekt verwenden...

von Daniel (Gast)


Lesenswert?

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);

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

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:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <inttypes.h>
4
#include <stdbool.h>
5
6
#define F_CPU 16000000ULL
7
#include <util/delay.h>
8
9
#include "can.h"
10
11
void sleep(uint32_t i)
12
{
13
  while(i--)
14
    _delay_ms(1);
15
}
16
17
18
int main(void)
19
{
20
  int8_t  data[8];
21
  uint8_t i;
22
23
  data[0] = 'H';
24
  data[1] = 'i';
25
  data[2] = ' ';
26
  data[3] = 't';
27
  data[4] = 'h';
28
  data[5] = 'e';
29
  data[6] = 'r';
30
  data[7] = 'e';
31
32
  // baudrate: 250K, keine Interrupts, extended Id
33
  can_init(3, 0, 1);
34
35
  // mob: 0, modus: senden, id 3, idm 0xffffffff
36
  can_enable_mob(0, 1, 3, 0xffffffff);
37
38
  for(i = 1; i <= 8; i++)
39
  {
40
    sleep(1000);
41
    can_send_data(0, i, data);
42
  }
43
44
  while(1);
45
46
  return 0;
47
}

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. :)

von Wolfgang (Gast)


Lesenswert?

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.

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

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

von Marco G. (mg-programmer)


Lesenswert?

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

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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?

von Marco G. (mg-programmer)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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

von Marco G. (mg-programmer)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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

von Michael (Gast)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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

von Marco G. (mg-programmer)


Lesenswert?

Hallo Wolfgang,

Ich bin zur Zeit nicht mehr in KA.
Ich schreibe gerade meine Diplomarbeit.
Wieso? Bist/studierst du auch in KA?

Gruß Marco

von Wolfgang (Gast)


Lesenswert?

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

von Arno S. (schneeball)


Angehängte Dateien:

Lesenswert?

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

von C. H. (_ch_)


Lesenswert?

Hallo,

kleiner Bugfix in der can.c von
1
Autor:  Michael (Gast)
2
Datum: 15.09.2008 09:13
3
Dateianhang: can.tgz

Bug: MOb-Interrupts für MOb8..MOb14 werden nicht gesetzt

Bugfix:
1
// Parameter: uint8_t mob: Nummer des Objekts (0-14)
2
// Funktion setzt den Interrupt für das jeweilige Objekt
3
void can_set_mob_interrupt(uint8_t mob)
4
{
5
   if (mob < 8) { setbit(CANIE2, iemob[mob]); }
6
   else         { setbit(CANIE1, iemob[mob]); }
7
}

Gruß
Christian

von Martin (Gast)


Lesenswert?

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

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

hat einer ein Beispiel????

von E. M. (hias)


Lesenswert?

Schonmal in der Doku gelesen?

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

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 ;-)

von Thomas (Gast)


Lesenswert?

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.

von Hans J. (joker158)


Lesenswert?

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

von andre (Gast)


Angehängte Dateien:

Lesenswert?

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.

von andre (Gast)


Lesenswert?

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.

von andre (Gast)


Lesenswert?

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?

von M!ndfr34k M. (m1ndfr34k)


Lesenswert?

Schaut euch ma die CANPAGE genauer an!

Dann kommt ihr wahrscheinlich auf die LÖsung eurer Probleme!

von MatMar (Gast)


Angehängte Dateien:

Lesenswert?

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

von Siggi G. (bize)


Angehängte Dateien:

Lesenswert?

Hallo

Im Anhang: meine Send-Remote-Funktion.
Und in meiner main-Funktion eine while-Schleife mit folgendem Inhalt:
1
while(1)
2
{
3
can_send_remote(0,8);
4
led_blinken();
5
// Die LEDs blinken, damit ich weiß, wann die Schleife zu Ende ist...
6
}

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ß

von Siggi G. (bize)


Lesenswert?

Nob Ge. schrieb:
> Hallo
>
> Im Anhang: meine Send-Remote-Funktion.
> Und in meiner main-Funktion eine while-Schleife mit folgendem Inhalt:
>
1
> while(1)
2
> {
3
> can_send_remote(0,8);
4
> led_blinken();
5
> // Die LEDs blinken, damit ich weiß, wann die Schleife zu Ende ist...
6
> }
>
> 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 ;-)

von Siggi G. (bize)


Lesenswert?

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ß

von MatMar (Gast)


Lesenswert?

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 ;)

von MatMar (Gast)


Lesenswert?

Äh sorry, nicht "zyklisch Auto-Reply messages versendet", sondern 
natürlich remote frames !
Grüße

von Siggi G. (bize)


Lesenswert?

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 !!

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

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

von Wolframator (Gast)


Lesenswert?

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

von Andreas (Gast)


Lesenswert?

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

von Wolframator (Gast)


Lesenswert?

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? :)

von Tobias K. (kurzschluss81)


Lesenswert?

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.

von Marco G. (mg-programmer)


Lesenswert?

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.

von Tobias K. (kurzschluss81)


Lesenswert?

Ah so.
Naja das erklärt zumindetens die verblüfende Ähnlicheit der Doku

von Abel (Gast)


Lesenswert?

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)

von Fabian B. (fabs)


Lesenswert?

Es wird immer ein CAN Transceiver benötigt. Z.B. ein SN65HVD1050 von TI.

Gruß
Fabian

von Sven H. (nobody1984)


Lesenswert?

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:
1
...
2
CAN_message msg;
3
4
int main(void)
5
{
6
 ...
7
  msg.id = 0x099;
8
  msg.idm = 0xffff;
9
  msg.dlc = 2;
10
  msg.data[0] = 0x12;
11
  msg.data[1] = 0x34;
12
  ...
13
  while(1)
14
  {
15
    CAN_enableMOB(2, AUTO_REPLY, msg);
16
    ...
17
  }
18
  return(0);
19
}

Schöne Grüße,
der Sven

von Tobias (Gast)


Lesenswert?

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

von SinoTech (Gast)


Lesenswert?

Gleiches Problem hier.

von SinoTech (Gast)


Lesenswert?

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.

von SinoTech (Gast)


Lesenswert?

@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;


[...]

von patnze (Gast)


Lesenswert?

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

von Sven H. (nobody1984)


Lesenswert?

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:
1
int get_baudrate(void)
2
{
3
  int baudrate;
4
  switch(PINA & ((1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3)))
5
  {
6
    case 0x01:
7
      baudrate = 125;
8
      break;
9
10
    case 0x02:
11
      baudrate = 200;
12
      break;
13
14
    case 0x03:
15
      baudrate = 250;
16
      break;
17
18
    case 0x04:
19
      baudrate = 500;
20
      break;
21
22
    case 0x05:
23
      baudrate = 1000;
24
      break;
25
26
    default:
27
      baudrate = 100;
28
  }
29
  return(baudrate);
30
}
31
32
int get_node(void)
33
{
34
  // kann man wie get_baudrate() aufbauen und an entsprechender Stelle im Code verwenden.
35
  // Kenne das OpenCAN Protokoll nicht, daher weiss ich nicht genau wo das hin muss!
36
  // Aber das wirst du dann ja wissen, wie du es ins Protokoll verpacken musst...
37
}
38
39
int main(void) 
40
{
41
// Ports als Eingänge setzen
42
DDRA &= ~((1<<DDA0)|(1<<DDA1)|(1<<DDA2)|(1<<DDA3)); // DIP-Schalter für Baudrate
43
DDRC &= ~((1<<DDC0)|(1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4)|(1<<DDC5)|(1<<DDC6)); // DIP-Schalter für Node_ID
44
45
// Ich kenne deine Eingangsbeschaltung der DIP's nicht, aber vermutlich brauchst du noch die PullUps,
46
// falls du keinen externen hast?!
47
// PullUps für Eingänge aktivieren
48
PORTA |= (1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3);
49
PORTC |= (1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3)|(1<<PC4)|(1<<PC5)|(1<<PC6);
50
       
51
// CAN initialisieren
52
CAN_init(get_baudrate(), TX);
53
54
// ...wie das Senden und Empfangen funktioniert, hat Marco ja bereits gut beschrieben!
55
// Dann kannst du ja einfach dein CANopen Protokoll umsetzen :)
56
}
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

von patnze (Gast)


Lesenswert?

Danke Sven,
habe auch ein Kumpelt gefragt und seineErklärung war genau wie 
deine.nochmals danke.

von patnze (Gast)


Lesenswert?

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

von Sven H. (nobody1984)


Lesenswert?

Hi,
ich hatte dir bereits geraten, ein eigenen Thread aufzumachen, da das 
hier thematisch nicht rein passt!

von wikky (Gast)


Lesenswert?

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

von Davio51 (Gast)


Lesenswert?

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

von Bonzadog (Gast)


Lesenswert?

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

von Chris D. (myfairtux) (Moderator) Benutzerseite


Lesenswert?

Die CRC-Summe wird direkt vom CAN-Controller (in der Hardware des 
AT90CAN128) erzeugt und angehängt bzw. verglichen.

Chris D.

von Sven K. (mueslifresser)


Lesenswert?

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

von Tim R. (herrvorragend)


Lesenswert?

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)

von Davio51 (Gast)


Lesenswert?

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

von Davio51 (Gast)


Lesenswert?

Hat sich erledigt.

Mit HTerm klappt es.

von Markus B. (wolframator)


Lesenswert?

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?

von Dominik W. (Gast)


Lesenswert?

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

von garphi (Gast)


Lesenswert?

@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

von garphi (Gast)


Lesenswert?

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]); }
}

von Schorsch (Gast)


Lesenswert?

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ß

von garphi (Gast)


Angehängte Dateien:

Lesenswert?

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

von Dimpflmoser (Gast)


Lesenswert?

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

von JayB (Gast)


Lesenswert?

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?!

von lilhill (Gast)


Lesenswert?

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.

von JayB (Gast)


Lesenswert?

hey lilhill

welchen version von Atmel studio verwendest du ???

von lilhill (Gast)


Lesenswert?

ich verwende den Atmel Studio 6 (Version 6.0.1843)

von JayB (Gast)


Lesenswert?

Welche Lib verwendest du???

von Schorsch (Gast)


Lesenswert?

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ß

von Thomas S. (thomas_s82)


Lesenswert?

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

von Daniel S. (Firma: privat) (daniel_sun)


Angehängte Dateien:

Lesenswert?

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

von Thomas S. (thomas_s82)


Lesenswert?

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

von Daniel S. (Firma: privat) (daniel_sun)


Lesenswert?

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

von Thomas S. (thomas_s82)


Lesenswert?

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

von Daniel S. (Firma: privat) (daniel_sun)


Lesenswert?

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

von Horst (Gast)


Lesenswert?

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!

von Thomas S. (thomas_s82)


Lesenswert?

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

von Horst (Gast)


Lesenswert?

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

von Thomas S. (thomas_s82)


Lesenswert?

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

von Horst (Gast)


Lesenswert?

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?

von Horst (Gast)


Lesenswert?

Ok, ich kann meine Frage jetzt selber beantworten.

Beim Konfigurieren eines MOB sage ich mit
1
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.
1
CANCDMOB |= (1 << IDE);
Sagt, dass ich eine extended Nachricht (29Bit-ID) empfangen möchte.
1
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:
1
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):
1
// ----------------------------------------------------------------------------
2
/*
3
 * Copyright (c) 2007 Fabian Greif, Roboterclub Aachen e.V.
4
 *  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $Id: at90can_set_dyn_filter.c 6837 2008-11-16 19:05:15Z fabian $
28
 */
29
// ----------------------------------------------------------------------------
30
31
#include "at90can_private.h"
32
#ifdef  SUPPORT_FOR_AT90CAN__
33
34
// ----------------------------------------------------------------------------
35
bool at90can_set_filter(uint8_t number, const can_filter_t *filter)
36
{
37
  if (number > 14) {
38
    // it is only possible to serve a maximum of 15 filters
39
    return false;
40
  }
41
  
42
  // set CAN Controller to standby mode
43
  _enter_standby_mode();
44
  
45
  CANPAGE = number << 4;
46
  
47
  CANSTMOB = 0;
48
  CANCDMOB = 0;
49
  
50
  #if SUPPORT_EXTENDED_CANID
51
  
52
  if (filter->flags.extended == 0x3)
53
  {
54
    // extended identifier
55
    CANIDT4 = (uint8_t)  filter->id << 3;
56
    CANIDT3 =            filter->id >> 5;
57
    CANIDT2 =            filter->id >> 13;
58
    CANIDT1 =            filter->id >> 21;
59
    
60
    CANIDM4 = ((uint8_t) filter->mask << 3) | (1 << IDEMSK);
61
    CANIDM3 =            filter->mask >> 5;
62
    CANIDM2 =            filter->mask >> 13;
63
    CANIDM1 =            filter->mask >> 21;
64
    
65
    CANCDMOB |= (1 << IDE);
66
  }
67
  else {
68
    CANIDT4 = 0;
69
    CANIDT3 = 0;
70
    CANIDT2 = (uint8_t)  filter->id << 5;
71
    CANIDT1 = (uint16_t) filter->id >> 3;
72
    
73
    if (filter->flags.extended) {
74
      CANIDM4 = (1 << IDEMSK);    // receive only standard frames
75
    } else {
76
      CANIDM4 = 0;          // receive all frames
77
    }
78
    
79
    CANIDM3 = 0;
80
    CANIDM2 = (uint8_t)  filter->mask << 5;
81
    CANIDM1 = (uint16_t) filter->mask >> 3;
82
  }
83
  
84
  #else
85
  
86
  CANIDT4 = 0;
87
  CANIDT3 = 0;
88
  CANIDT2 = (uint8_t)  filter->id << 5;
89
  CANIDT1 = (uint16_t) filter->id >> 3;
90
  
91
  CANIDM4 = (1 << IDEMSK);
92
  CANIDM3 = 0;
93
  CANIDM2 = (uint8_t)  filter->mask << 5;
94
  CANIDM1 = (uint16_t) filter->mask >> 3;
95
  
96
  #endif
97
  
98
  if (filter->flags.rtr & 0x2) {
99
    CANIDM4 |= (1 << RTRMSK);
100
    
101
    if (filter->flags.rtr & 0x1)
102
      CANIDT4 |= (1 << RTRMSK);    // only RTR-frames
103
  }
104
  
105
  CANCDMOB |= (1<<CONMOB1);
106
  
107
  _enable_mob_interrupt(number);
108
  
109
  // re-enable CAN Controller 
110
  _leave_standby_mode();
111
  
112
  return true;
113
}
114
115
#endif  // SUPPORT_FOR_AT90CAN__

von Sebastian K. (megaei)


Lesenswert?

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!

von Thomas S. (thomas_s82)


Lesenswert?

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

von Sebastian K. (megaei)


Lesenswert?

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

von garphi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
war schon einige Zeit nicht mehr da, aber hier die globals.h und die 
timer.h

von Karin (Gast)


Lesenswert?

Hi zusammen
Ich bin neu auf dem Gebiet der can/Microcontroer und habe desshalb eine 
sehr grundegende Frage: Funktioniert die Lib von Marco auch mit CANOpen? 
Bisher habe ich nur versucht zu senden, doch mein CanOpenMaster findet 
gar keine Box bzw. sieht nicht was sie ist/sendet...
hat von euch ev jemand ein AVR Projekt das er mir zur verfügung sten 
würde um zu testen ob s an meinem Programm liegt?

von Manuel Wolfschwenger (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich verwende die CAN-Bibiliothek von Marko Glitsch um ein einfaches 
Signal zu senden, allerdings wird auf meinem CAN-analyzer weder ein 
Signal angezeigt noch leuchtet die TX,RX LED zum senden und empfangen. 
Den Programmcode habe ich als Zip-Datei hinzugefügt. Vielleicht weis 
irgendjemand hier eine Lösung oder einen Programmvorschlag wie ich am 
besten ein einfaches Signal senden kann.

verwendeter Mikrokontroller: At90CAN128

Mfg Woifi

von Thomas S. (thomas_s82)


Lesenswert?

Hi Manuel,

habe die lib noch nicht benutzt aber ist der Fehler manchmal hier ?

// CAN initialisieren
CAN_init(250,RX);

TXRX    - Daten gesendet und/oder empfangen

Gruß Thomas

von Daniel S. (Firma: privat) (daniel_sun)


Lesenswert?

Hallo zusammen

ich brauche dringend Hilfe!!!!!
Als erstes die Bibliothek ist toll aber ich habe ein kleines Problem.

Hatte letztes Jahr ein kleines Projekt gemacht (immer schön versioniert) 
und dann das Projekt erfolgreich beendet.

Leider musste ich jetzt doch ne Kleinigkeit ändern in der Anzeige (2x16 
Display). Wirklich nur ein Wort und der Rest blieb wie erst ist.

Kein Problem also kurz geändert und gut.
Aber nach dem Kompilieren das große Staunen es kommen keine CAN 
Botschaft mehr, der Rest geht LED Kontrolle, Display usw.

Da ich sauber Versioniert hatte, hatte ich zu jeder Version den immer 
den gesamten Projektordner archiviert (also Flachfiel und Sourcecode).

Flashe ich das alte File zum passenden Code gehts.
Compiliere ich den passenden Code zum Flachfile kommen keine Can 
Botschaften.

Ich habe in der Zeit meinen Rechner neu Installiert von XP (ich weiss 
ziemlich alt) auf WIN 7 Pro 64 bit und von AVR Studio 6.1 beta auf 6.1 
normal gewechselt.
Habe übrigens noch mehr CAN Projekte ebenfalls gut versioniert ist 
überall das gleiche, neu dompiliert keine CAN Botschaften, altes File 
und es geht.

Was mache ich falsch? AVR Studio 6.2 beta habe ich auch schon 
probiert!!!

Muss ich irgendwas einstellen an das ich mich nicht mehr erinnern kann 
in AVR Studio benutze das Olimex CAN Board.

Bitte helft mir ich verzweifle noch!!!!

Gruß
Daniel

von Sebastian (Gast)


Lesenswert?

Hallo Daniel,

mit welcher Version von AVR-Studio hast du denn deine "alten" Versionen 
compiliert? Ich kenn das auch mit dem neuen AVR-Studio 6. Nun benutzte 
ich weiterhin unter Win7, wie vorher unter XP, die Version 4.18. Aber 
auch mit den neuen Versionen von AVR-Studio geht es normalerweise. Du 
musst schauen das alle Bibs richtig eingebunden werden und die Angaben 
zu den Header-Files passen.
Viel Glück!

von hari (Gast)


Lesenswert?

Hallo,
ich habe die Can Library auf einem Olimex AVR CAN board ausprobiert, 
aber es scheint keine Nachricht gesendet zu werden.
In senddata läuft das program bis zu dem Punkt, wo es auf das TOXK Flag 
wartet, dies wird jedoch nie gesetzt. Wenn ich die Zeile auskommentiere 
funktioniert es auch nicht.
Habe den Code von Marco Glietsch probiert und stundenlang Fehler gesucht 
oder Änderungen vrsucht.
#define  _AVR_AT90CAN128_  1
#define OSCSPEED  16000000    /* in Hz */
#include <avr/io.h>
#include "can.h"
#define SIG_CAN_INTERRUPT1      _VECTOR(18)

void LedAn()
{
  PORTE=(0<<4);
}
void LedAus()
{
  PORTE=(1<<4);
}



main()
{
  PORTE=0b00010000;
  DDRE=0b00010000; //PE4 LED Ausgang
  CAN_init (1000 , TX );

  // Zu sendende Daten
  CAN_message msg ;
  msg.id = 1 ;
  msg.idm = 1 ;
  msg.data [0] = 0x11 ;
  msg.data [1] = 0x22 ;
  msg.data [2] = 0x33 ;
  msg.data [3] = 0x44 ;
  msg.data [4] = 0x55 ;
  msg.data [5] = 0x66 ;
  msg.data [6] = 0x77 ;
  msg.data [7] = 0x88 ;
 while(1)
  {
  // Objekt 0 auf Empfang setzen
  CAN_enableMOB (0, RECEIVE_DATA , msg );

  // Daten ¨uber Objekt 0 senden
  CAN_sendData(0, msg.data);


  LedAn();
  _delay_ms(1000);
  LedAus();
  _delay_ms(1000);
  }
}

Hat jemand den Code auf einem Olimex board zum Laufen bekommen, oder hat 
jemand ein Beispiel Code?
Danke
hari

von Dany (Gast)


Lesenswert?

Hast du dein Programm auf deinem Olimex Board zum laufen gebracht? um 
mit meinem board zu spieeln suche ich einen guten beispielcode welcher 
sicher auf dem olimex läuft.

von Ben (Gast)


Lesenswert?

Hy zusammen,
ich habe mich auch mit dem CAN-Bus beschäftigt, aber am ATMega16M1.
Es "läuft" auch, es sind noch kleine Fehler drin bzw. habe ich da noch 
ein paar Verständniß fragen.

Wieso speicher wird die CANPAGE zwischen gespeichert?
Wer die ISR ausgelöst wird ist doch klar wenn man die CANSIT2 ausliest 
und in der mainloop verarbeitet und dann wieder auf Empfang stellt.

Wenn Nachrichten (von PCAN) eingehen im Intervall von 1ms und der AVR 
diese durch einen Daten-Frame quittiere funktioniert dies auch und wenn 
vom AVR noch alle 100ms eine Nachricht gesendet wird zu PCAN. Werden im 
PCAN ACK-Fehler angezeigt und nach einer Zeit schaltet sich PCAN in 
BUSOFF.
Aber laut meiner Rechnung sollte das von der zeit ausreichen. CAN-Frame 
max 111+19 bits bei 1000kbps sollte pro 1ms 7 Frame ohne Problem klappen 
und sich nicht bei 2-3 Frames.

Habt ihr vielleicht eine Idee woran das liegen könnte?

Dickes danke im voraus.

mfg Ben

von Michael H. (windyboy)


Lesenswert?

Moin zusammen.

Ich beschäfitge mich jetzt seit längerer Zeit mit der 
Mikrocontrollerprogrammierung an einem AT90CAN128. Ich habe schon einige 
Funktionen geschrieben und versuche nun, in meinem Projekt den CAN-Bus 
zu implementieren.
Dazu verwende ich die Bibliothek, wie sie von Marco Glietsch oben 
hochgeladen wurde.

Bei der Ausführung stoße ich immer auf folgendes Problem, dass auch 
schon oben am 28.12.2010 angesprochen wurde.
Die programmausführung des Mikrocontrollers bleibt bei CAN_sendData in 
der Zeile
  while (!getbit(CANSTMOB, TXOK));
hängen.
Mit dem Lösungsvorschlag, dass mindestens ein Teilnehmer als Empfänger 
am Bus sein soll, komme ich nicht weiter.

Zu meinem Aufbau:
Derzeit habe ich den gesamten Aufbau auf einem Steckboard realisiert. 
Der CAN-Bus ist an beiden Enden mit 120Ohm terminiert.
Neben dem Sender befindet sich ein AT90CAN128 als Empfänger am Bus, 
zusätzlich ein PCAN-USB-Adapter, der die Daten auf dem Bus mitloggen 
soll.
CAN_HIGH und CAN_LOW werden gleichzeitig mit einem Oszilloskop überwacht 
und zeigen dauerhaft einen Signalpegel von ca. 2,4V.

Ich bin derzeit überfragt und komme absolut nicht weiter.
Kann mir jemand helfen?

Danke und Gruß,

Michael.

von Michael H. (windyboy)


Lesenswert?

Ich habe heute noch einiges ausprobiert, aber komme partout nicht 
weiter.

In der besagten Schleife hängt der Controller fest und auf dem Bus 
ergibt sich keine Pegeländerung.

Hat jemand noch Tipps oder Ratschläge, wonach ich suchen könnte?

von Sebastian (Gast)


Lesenswert?

Hallo Michael,

Wie sieht deine Hardware aus? Hast du einen passenden CAN-Transiver 
richtig angeschlossen?
Wenn deine Schleife an der beschriebenen Stelle hängen bleibt, ersetze 
es doch testweise mal mit einem kleinen delay zB 10ms.

Viel Glück!

von Michael H. (windyboy)


Lesenswert?

Hallo.

Ich habe ein fertiges Mikrocontrollerboard von Chip45, siehe Link:
http://www.chip45.com/products/crumb128-can-5.0_avr_atmega_module_board_at90can128_usb_rs232_can.php
Ich habe zwei Boards davon, die untereinander kommunizieren sollen.

von Sebastian (Gast)


Lesenswert?

Hallo,
ok das sollte passen. Hast du den PCAN so eingestellt das er alle 
Nachrichten quittiert?
Hat das mit dem delay statt dem Befehl im Code nicht funktioniert?

von Bernd K. (prof7bit)


Lesenswert?

1
  /////////////////////
2
  // Baudrate setzen //
3
  /////////////////////
4
  CAN_setBaudrate(baud);
5
6
7
  ///////////////////////////
8
  // Interrupts aktivieren //
9
  ///////////////////////////
10
  CAN_setInterrupt(intmode);

Wozu dienen die Kommentare? Um den Funktionsaufrufen mehr Nachdruck zu 
verleihen, mehr Gewicht? Oder soll es sich reimen, ist es Code-Lyrik?

von windyboy (Gast)


Lesenswert?

Die Einstellung des PCAN muss ich kontrollieren, das weiß ich so nicht 
auswendig.
Das Delay hat nichts gebracht. Der Controller wartet dann nur, auf den 
Bus wird aber trotzdem nichts gesendet.

von Michael H. (windyboy)


Lesenswert?

So, ich bin etwas weiter, aber keinesfalls schlauer.

Beim PCAN kann ich nur Message Filter auswählen, aber keine Quittierung. 
Oder übersehe ich etwas?

Ich betreibe den AT90CAN128 nun mit einem JTAG ICE 3 und bin das 
Programm mal im Einzelschrittmodus durchgegangen.
Es ist so, dass einzelne Codezeilen scheinbar nicht ausgeführt werden.
Beispielsweise wird die Funktion CAN_setBaudrate nicht ausgerufen. Somit 
wurden die Baudrate-Register garnicht beschrieben, das lässt sich ja 
über JTAG auslesen.
Später werden einzelne setbit bzw. clearbit-Befehle nicht ausgeführt.

Ich bin gerade echt überfragt.
Woran kann es liegen, dass einzelne Zeilen nicht ausgeführt werden?
Beim Compilieren erscheinen keine Fehler.

von -o0 (Gast)


Lesenswert?

Michael H. schrieb:
> Woran kann es liegen, dass einzelne Zeilen nicht ausgeführt werden?
> Beim Compilieren erscheinen keine Fehler.

weg optimiert. - de facto werden sie (bzw. zu diesem Zeitpunkt WURDEN 
sie) schon ausgeführt. Wenn Du jeden Befehl genau so wie beschrieben 
abgearbeitet haben willst, kannst Du probehalber in den Einstellungen 
mal die Optimierung auf Null stellen. Wird aber auf den fehlerhaften 
Ablauf Deines Programms keinen Einfluss haben

von Thomas F. (igel)


Lesenswert?

Michael H. schrieb:
> Beim PCAN kann ich nur Message Filter auswählen, aber keine Quittierung.
> Oder übersehe ich etwas?

Die PEAK CAN-USB Geräte senden meines Wissens immer ein ACK. Listen-Only 
habe ich noch nirgends gefunden.

von Michael H. (windyboy)


Angehängte Dateien:

Lesenswert?

Hallo Thomas.

Kannst du mir sagen, wo ich in PCAN View die Einstellung finde?

von Thomas F. (igel)


Lesenswert?

Michael H. schrieb:
> Kannst du mir sagen, wo ich in PCAN View die Einstellung finde?

Wie gesagt, ich habe auch noch keine Einstellung gefunden.
Sobald das CAN-Gerät über den Blitz verbunden wurde, wird immer ein ACK 
gesendet.

von Sebastian (Gast)


Lesenswert?

Hallo Michael,

wichtig für dich wäre ist doch ein Code der erstmal überhaupt eine 
CAN-Nachricht schickt, oder? Ich arbeite immer noch mit dem Atmel-Studio 
4. Der Umstieg auf die neueren Versionen hab ich irgendwann mal 
aufgegeben da der funktionierende Code übersetzt mit Atmel-Studio 4 z.B. 
mit Atmel-Studio 5 aus nicht nachvollziehbaren Gründen nicht mehr lief. 
Welches IDE hast du? Vielleicht liegt es bei dir auch daran. Ich hab 
aber, wie weiter oben mal beschrieben, die Bibliothek gewechselt. Das 
lag aber nicht an der grundsätzlichen Funktion der Bibliothek von Marco.

von Michael H. (windyboy)


Lesenswert?

Hallo Sebastian.

Genau so ist es. Ich suche einen Code, der zunächst ohne Modifikationen 
irgendwas per CAN verschickt.
So kann ich zumindest Fehlerquellen ausschließen.

Ich arbeite mit Atmel Studio 6 in der Version 6.2.1548, Service Pack 2. 
Habe ich auch nochmal alles auf den neusten Stand gebracht, aber 
vielleicht liegt es daran?
Zudem setze ich den JTAG ICE 3 ein.

Kannst du mir für das Studio 4 einen Code zur Verfügung stellen, der so 
(plug und play) funktioniert?
Wäre echt klasse!
Es muss ja nicht der vom Themenstarter hier sein.

Danke und Gruß,

Michael.

von Sebastian (Gast)


Lesenswert?

Hallo Michael,

ich hab für dich gerade mal ein Beispiel-Code erstellt der aller 100ms 
eine CAN-Nachricht sendet. Jedoch würde ich das vorher gern testen. Das 
kann ich erst morgen in Laufe des Tages erledigen da ich die Hardware 
nicht da habe. Also etwas Geduld!

Viele Grüße
Sebastian

von Michael H. (windyboy)


Lesenswert?

Hallo Sebastian.

Danke für deine Hilfe.
Ich werde in der Zwischenzeit mal das Atmel Studio 4 installieren, 
sodass ich damit dann testen kann.

Gruß,

Michael.

von Tobias (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich möchte mit der Bibliothek von Marco Glietsch CAN Botschaften senden.
Vielen Dank erstmal für diese Bibliothek!
Allerdings komme ich nicht voran.
Bisher möchte ich nur eine Botschaft senden.
Ich verwende:
- AT90CAN128 (auf einem Board von Olimex)
- STK600
- Atmel Studio 6.2

Im Anhang habe ich die Header Datei sowie mein Hauptprogramm
Das Programm läuft durch bis zu diesem Punkt:

  PORTB = 0b00001000;    //LED 1 blinkt
  _delay_ms(1000);
  PORTB = 0b00000000;

  while (!getbit(CANSTMOB, TXOK));
  clearbit(CANSTMOB, TXOK);

  PORTB = 0b00000100;    //LED 2 blinkt
  _delay_ms(1000);
  PORTB = 0b00000000;

Dadurch, dass die erste LED blinkt die zweite allerdings nicht weiß ich, 
dass ich wohl nicht über die while Schleife hinaus komme.
Das bedeutet doch das er darauf wartet fertig zu senden, dies aber nicht 
passiert. Oder?
Kann mir jemand sagen wo in meinem Programm der Fehler ist?
Vielen Dank schon mal im Voraus!!
Viele Grüße
Tobias

von Steffen R. (steffen_rose)


Lesenswert?

Die Bilbliothek nutze ich nicht.
Aber TXOK sollte erst nach einer erfolgreichen Übertragung des CAN 
Telegramms kommen. Was hast Du als Gegenstelle? Hast Du dort etwas 
empfangen?

von Tobias (Gast)


Lesenswert?

Danke für die Antwort!
als Gegenstelle habe ich entweder das gleiche Board nochmal auf Empfang 
oder CANAlycer mit dem CANcaseXL

von MArkus S. (markus1991)


Lesenswert?

Kann mir jemand dabei helfen die Kommunikation über CANoe darzustellen? 
Welche Vorkehrungen muss ich da treffen?

Bzw könnt ihr mir eine Alternative nennen, wie ich mir die gesendeten 
Nachrichten ansehen kann?

von petra (Gast)


Lesenswert?

Michael schrieb:
> 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

Hallo MIchael,

deine Bib funktioniert bei mir bisher am besten.
Habe nur eine frage zum empfang.
du sagst ja, dass der interrupt ausgelöst wird, sobald eine nachricht 
mit der id 4 von einem anderen busteilnehmer ankommt.
was muss ich in der main (außer sei();) noch hinzufügen,damit der 
interrupt auch ausgelöst wird.
im moment sende ich nämlich eine nachricht von canoe mit der id 4 und es 
passiert leider nichts.

von Rafał Walisko (Gast)


Lesenswert?

Hi. Please help me. I have to use 2 different CAN_id to send data. Can i 
use your library?

Hallo. Bitte hilf mir. Ich muss 2 verschiedene CAN_id verwenden, um 
Daten zu senden. Kann ich deine Bibliothek benutzen?

von Robert (Gast)


Lesenswert?

alter Thread, habe aber dazu eine Frage:

Kann ich mit dem AT90CAN128 irgendwie das Reservierte Bit im 
Controllfeld auf Dominant setzen ?

Also: Bit: Request
      Bit: IDE
      BIT: Reserviert   <<<---- das hier
      Bit: DL3
      usw.

Habe da einen AT90CAN128 mit der oberen Lib (Mischung)
Normale 11Bit Adressierung und 8 Daten Bytes

Ich habe da eine Hardware, die sendet mir bei dem Reservierten Bit ein 
Dominates Bit.
Ich möchte mit dem AVR diese Hardware nachbilden

Der AVR sendet dort aber nur ein Recessives Bit.

Normal sollte dieses Bit unwichtig sein, möchte aber mit dem AVR ,genau 
das so nachstellen.

Darum müsste ich dieses Reservierte Bit auf Dominant bekommen !

Geht das irgendwie ?

Hat jemand dazu bitte einen Tipp ?
DANKE :-)

l.G. Robert

von Thomas (kosmos)


Lesenswert?

probier mal das Bit 0 oder 1 im CANIDT4 Register zu setzen

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
Noch kein Account? Hier anmelden.