Forum: Mikrocontroller und Digitale Elektronik extended id at90can128


von Günther M. (Gast)


Lesenswert?

Hallo Leute,
Bin gerade dabei ein kleines Programm mit Can-Bus zu schreiben. 
Funktioniert auch soweit mit der 11 Bit-ID. Nub benötige ich die 
extended ID. Leider funktioniert das nicht so wie ich mir das vorstelle. 
Ich bekomme immer eine andere ID als die, die ich deklariert habe.
Vieleicht fällt ja jemanden der Fehler auf.
Danke im vorraus!

hier der Code:

 */

#include <avr/io.h>                // Einbinden der Bibliothek
#include <avr/interrupt.h>            // Einbinden der Bibliothek

volatile uint8_t ms_tick = 0;


  // wird alle 10ms aufgerufen

    ISR (TIMER3_COMPA_vect)              // Interrupt aufrufen
  {
    ms_tick = 42;
  }


void timer3_init(void)
{

// EMPFANGEN VON DATEN

  // Timer3 - 10ms bei 2 Mhz

  TCCR3B = 0x00;                // Stop ---> timer/counter control 
register
    //TCCR3A = 0x00;
    //TCCR3C = 0x00;
  OCR3A = 19999;                // TOP - Timer zählt bis zum maximalen 
wert von 19999 und gibt einen Interrupt aus      (Seite 140 im 
Datenblatt)

  TIMSK3 |= (1<<OCIE3A);            // Timer/Counter Interrupt Mask 
Register                          (Seite 142 im Datenblatt)

  TCCR3B |= (1<<WGM32) | (1<<CS31);      // Modus = CTC, Vorteiler 
(prescaler) = 8 dies entspricht dann 2 MHz            (Seite 138 im 
Datenblatt)
}



void can_init(void)                // CAN initialisieren
{
  uint8_t i,j;                // deklarienen von Variabeln

    //uint16_t id;              // Kurze ID aktiviren durch entfernen 
von

  uint32_t id;                // Lange ID aktiv

  CANGCON = (1<<SWRES);            // Reset ---> can general control 
register                          (Seite 252 im Datenblatt)



// reset all message objekts

  for (i=0; i<15; i++)            // Schleife
  {
    CANPAGE = (i<<4);            // select message objekt
    CANCDMOB = 0x00;            // disable message objekt
    CANSTMOB = 0x00;            // Statusregister zurücksetzen

// clear CAN identifier tag registers 
(Seite 263 im Datenblatt)
    CANIDT1 = 0x00;              // Register 1 zurücksetzen
    CANIDT2 = 0x00;              // Register 2 zurücksetzen
    CANIDT3 = 0x00;              // Register 3 zurücksetzen
    CANIDT4 = 0x00;              // Register 4 zurücksetzen

// clear CAN identifier mask registers 
(Seite 265 im Datenblatt)
    CANIDM1 = 0x00;              // Register 1 zurücksetzen
    CANIDM2 = 0x00;              // Register 2 zurücksetzen
    CANIDM3 = 0x00;              // Register 3 zurücksetzen
    CANIDM4 = 0x00;              // Register 4 zurücksetzen

// clear CAN data message register 
(Seite 266 im Datenblatt)
    for (j=0; j<8; j++)
    {
      CANMSG = 0x00;            // Register 1 zurücksetzen
    }
  }



// Einstellung für eine 250 kBit/s Baudrate mit 16 MHz Quarzoszillator 
(Seite 267 im Datenblatt)

  //CÁN bit timing register

    CANBT1 = 0x06;              //  Register 1
    CANBT2 = 0x0C;              //  Register 2
    CANBT3 = 0x37;              //  Register 3

    CANGCON = (1<<ENASTB);          // Aktivieren des CAN-Busses


  // CAN-Einstellung für den Mikrocontroller
  id = 0x18FF50E5;                        // ID vom Mikrocontroller
  CANPAGE = (0<<4);                        // Auswählen des MOB0
  CANIDT1 = (id >> 3);                      // Setzen der Bits 3-10 der 
Nachrichten-ID in das CANIDT1 Register
  CANIDT2 = (id << 5);                      // Setzen der Bits 0-2 der 
Nachrichten-ID in das CANIDT2 Register
  CANIDM1 = 0xFF;                          // alles auf High-Pegel 
setzten
  CANIDM2 = 0xE0;
  CANIDM4 = (1<<IDEMSK);                      // setzten des identifier 
extension mask                        (Seite 265 im Datenblatt)
  CANCDMOB = (1<<CONMOB1) | (1<<IDE) | 8;                  // 
Empfangsmodus eingeschaltet für 8 Byte Nachrichtenlänge


  // CAN-Einstellung für den emfänger
  id = 0x1806E5F4;                        // ID vom Ladegerät
  CANPAGE = (1<<4);                        // Auswählen des MOB1
  CANIDT1 = (id >> 3);                      // Setzen der Bits 3-10 der 
Nachrichten-ID in das CANIDT1 Register
  CANIDT2 = (id << 5);                      // Setzen der Bits 0-2 der 
Nachrichten-ID in das CANIDT2 Register
  CANIDM1 = 0xff;                          // alles auf High-Pegel 
setzten
  CANIDM2 = 0xe0;
  CANIDM4 = (1<<IDEMSK);                      // setzten des identifier 
extension mask                        (Seite 265 im Datenblatt)
  CANCDMOB = (1<<IDE) | 8;                          // Sendemodus 
eingeschaltet für 8 Byte Nachrichtenlänge
  CANSTMOB |= (1<<TXOK);                      // Interruptaufruf bei 
Versandbestätigung einleiten





  // CAN general interrupt enable register

    CANGIE =  0x00;              // gesamtes CAN general interrupt 
enable register deaktivieren              (Seite 255 im Datenblatt)
    CANIE1 =  0x00;              // message objekt interrupts 8-14 
deaktiviert                      (Seite 257 im Datenblatt)
    CANIE2 =  0x00;              // message objekt interrupts 0-7 
deaktiviert
    CANSIT1 = 0x00;              // CAN status interrupt message objekt 
register 1 deaktivieren              (Seite 257 im Datenblatt)
    CANSIT2 = 0x00;              // CAN status interrupt message objekt 
register 2 deaktivieren
}

int main(void)
{

  uint8_t data[8];              // deklaration von Variabeln
  uint8_t can_delay = 0;            // deklaration von Variabeln
  int  i;                    // deklaration von Variabeln
  float current;                // deklaration von Variabeln
  current=32;                  // deklaration von Variabeln

                        // deklaration der emfangenen Datenbytes
  int Byte1;                  // Ausgangsspannung HighByte
  int Byte2;                  // Ausgangsspannung LowByte
  int Byte3;                  // Ausgangsstrom HighByte
  int Byte4;                  // Ausgangsstrom LowByte
  int Byte5;                  // Fehlermeldungen
  int Byte6;                  // nicht belegt
  int Byte7;                  // nicht belegt
  int Byte8;                  // nicht belegt

  Byte1 = 0;                  // alle DatenBytes auf 0 setzten
  Byte2 = 0;
  Byte3 = 0;
  Byte4 = 0;
  Byte5 = 0;
  Byte6 = 0;
  Byte7 = 0;
  Byte8 = 0;
                    //
  cli();
  timer3_init();                //TIMER3 initalisieren
  can_init();                  // CAN initalisieren
  sei();                    // alle Interrupts aktivieren
  DDRB=0b00010101;
  PORTB=(0<<PB0) | (0<<PB2) | (0<<PB4);

    while (1)
    {
    if(ms_tick)
    {
      ms_tick = 0;

      CANPAGE = (0<<4);          // Auswählen des MOB0
      if(CANSTMOB & (1<<RXOK))      // Wurden Daten Empfangen?
      {


        Byte1= CANMSG;          //Empfangene Nachricht in Byte1-8 
abspeichern
        Byte2= CANMSG;
        Byte3= CANMSG;
        Byte4= CANMSG;
        Byte5= CANMSG;
        Byte6= CANMSG;
        Byte7= CANMSG;
        Byte8= CANMSG;
        if (Byte5==0b00000001)      //Wenn im Byte5=1 steht
        {
          PORTB=(1<<PB0);        // Fehler: Hardwarefehler PB0 aktiv
        }


        else if  (Byte5==0b00000010)  //Wenn im Byte5=2 steht
        {
          PORTB=(1<<PB2);         //Fehler: Übertemperatur PB2 aktiv
        }


        else if  (Byte5==0b00000100)  // Wenn in Byte 5=4 steht
        {
          PORTB=(1<<PB0) | (1<<PB2);
                        // Fehler: Eingangsspannung unzulässig
        }


        else if  (Byte5==0b00001000)  // Wenn in Byte 5=8 steht
        {
          PORTB=(1<<PB4);        // Fehler Batterie nicht verbunden
        }


        else if  (Byte5==0b00010000)  //wenn in Byte 5=16 steht (in 
Hex=10)
        {
          PORTB=(1<<PB0) | (1<<PB4);
                        //Fehler Can-Bus Fehler
        }


        else if  (Byte5==0b00001100)  // Wenn in Byte 5= 12 steht (in 
Hex=C)
        {
          PORTB=(1<<PB2) | (1<<PB4);
                        //Fehler Keine Eingangsspannung
        }


        else
        {
          PORTB = (0<<PB0) | (0<<PB2) | (0<<PB4) ;
        }
        CANSTMOB &= ~(1<<RXOK);      // Reset Flag
        CANCDMOB = (1<<CONMOB1) | 8;  // Empfangsmodus eingeschaltet für 
8 Byte Nachrichtenlänge
      }

      can_delay++;
      if(can_delay > 99)
      {
        can_delay = 0;

        CANPAGE = (1<<4);        // Auswählen des MOB1
        if(CANSTMOB & (1<<TXOK))    // Senden beendet?
        {
          CANSTMOB &= ~(1<<TXOK);    // Reset flag


            CANMSG = 1;
            CANMSG = 2;
            CANMSG = 3;
            CANMSG = 4;
            CANMSG = 0;
            CANMSG = 0;
            CANMSG = 0;
            CANMSG = 0;


          CANCDMOB |= (1<<CONMOB0);  // CAN übertragung einleiten
        }

      }
    }
  }
}                      //Fehler Can-Bus Fehler
        }


        else if  (Byte5==0b00001100)  // Wenn in Byte 5= 12 steht (in 
Hex=C)
        {
          PORTB=(1<<PB2) | (1<<PB4);

        }


        else
        {
          PORTB = (0<<PB0) | (0<<PB2) | (0<<PB4) ;
        }
        CANSTMOB &= ~(1<<RXOK);      // Reset Flag
        CANCDMOB = (1<<CONMOB1) | 8;  // Empfangsmodus eingeschaltet für 
8 Byte Nachrichtenlänge
      }

      can_delay++;
      if(can_delay > 9)
      {
        can_delay = 0;

        CANPAGE = (1<<4);        // Auswählen des MOB1
        if(CANSTMOB & (1<<TXOK))    // Senden beendet?
        {
          CANSTMOB &= ~(1<<TXOK);    // Reset flag


            CANMSG = current;
            CANMSG = current;
            CANMSG = current;
            CANMSG = current;
            CANMSG = current;
            CANMSG = current;
            CANMSG = current;
            CANMSG = current;


          CANCDMOB |= (1<<CONMOB0);  // CAN übertragung einleiten
        }

      }
    }
  }
}

von Rudolph (Gast)


Lesenswert?

Du setzt die ID falsch.
1
id = 0x18FF50E5;
2
id = (id << 3);
3
CANPAGE = (0<<4);
4
CANIDT = id;
5
CANIDM1 = 0xff;
6
CANIDM2 = 0xff;
7
CANIDM3 = 0xff;
8
CANIDM4 = 0xf8 | (1<<IDEMSK);
9
CANCDMOB = (1<<CONMOB1) | (1<<IDE) | 8;

von Günther M (Gast)


Lesenswert?

Danke schon mal, habe allerdings immmer noch das Problem das ich zwar 
die lange id bekomme aber gesendet wird mit ID:17d00000 aber er sollte 
ja mit 18FF50E5 senden.

von Rudolph (Gast)


Lesenswert?

Du löscht ja auch das IDE Bit aus CANCDMOB wieder raus.

von Günther M (Gast)


Angehängte Dateien:

Lesenswert?

hmm, habe das ganze jetzt noch einmal kontrolliert, und es um deine 
tipps erweitert, weiterhin bekomme ich am Can-Bus Interface die 
ID:17D00000 angezeigt  und nicht wie gewünscht 18FF50E5.
Danke für die bisherigen Tipps!:)

Der aktualisierte Code befindet sich im Anhang, vielleicht findet ja 
noch jemand einen weiteren Fehler, bin um jede Hilfe dankbar.

von Rudolph R. (rudolph)


Lesenswert?

Der Fehler ist in der Init.

CANIDT1  = id;

Das muss sein:

CANIDT = id;

Wenn das dann auch bei der Sende-ID alles richtig steht, dann klappt das 
auch mit dem Senden, im Moment ist das immer noch so als ob für 11 Bit 
ID eingestellt werden soll.
Um das zu Testen habe ich extra eine Platine mit einem 90CAN128 
ausgegraben.

von Günther M (Gast)


Lesenswert?

Habe das ganze heute nochmals probiert, und genau so programmiert wie 
gesagt. Passt alles so, besten Dank!!

von Günther M (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Rudolph R. ,

ich hab da leider noch immer ein kleines Problem mit der langen CAN ID.
Sobald ich die lagen CAN ID aktiviere indem ich im CANCDMOB eine 
(1<<IDE) setze fängt das erste Byte an der Nachricht an irgendwelche 
Werte rauszusenden welche ich garnicht verschicken möchte.
Wenn ich die ID wieder auf die kurze umstelle wird die Nachricht 
korreckt gesendet.
Hast du vielleicht eine Idee woran das liegen könnte? Habe meinen 
Testcode nochmal im Anhang angefügt.

Wie gesagt das mit der langen ID passt alles ich bekomme mit langer ID 
lediglich falsche Nachrichten gesendet (willkürliche Werte) und mit der 
kurzen nicht...

von Rudolph R. (rudolph)


Lesenswert?

Unter zwei verschiedenen Namen und als .txt gepostet ist schon nicht 
nett.

Eine Menge Deiner Kommentare ist übrigens überflüssig und ein paar 
falsch.

Beispiele:
#include <avr/io.h> // Einbinden der Bibliothek
uint8_t i,j; // deklarienen von Variabeln
if (Byte5==0b00000001) //Wenn im Byte5=1 steht

Wenn Dir das hilft, super, so machen.
Ich finde das anstrengend.

Wie auch immer, schau Dir mal die Zeilen 102 und 114 genauer an.

von Günther M (Gast)


Lesenswert?

ja, genau die beiden zeilen meine ich ja auch mit dem CANCDMOB.
CANCDMOB =  (1<<CONMOB1) | (0<<CONMOB0)| 8;
CANCDMOB =  (0<<CONMOB1) | (1<<CONMOB0)| 8;

wenn ich dort dann (1<<IDE) bei beiden hinzufüge:
CANCDMOB =  (1<<CONMOB1) | (0<<CONMOB0)| (1<<IDE) | 8;
CANCDMOB =  (0<<CONMOB1) | (1<<CONMOB0)| (1<<IDE) | 8;

dann ändert der zwar auf die  extended ID, schreibt aber Mist in die CAN 
Nachricht.

von Rudolph R. (rudolph)


Lesenswert?

Das ist alles ein wenig verwirrend.
In der can_init() steht als Kommentar für MOB0 Sender und für MOB1 
Empfänger.
Obwohl das genau anders herum konfiguriert und benutzt wird.

Und diese "(0<<CONMOB1)" Konstrukte machen das auch nicht lesbarer.

In Zeile 114 steht:
CANCDMOB =  (0<<CONMOB1) | (1<<CONMOB0) | 8;

Damit wird sofort eine Botschaft auf einer 11-Bit ID gesendet, obwohl 
die ID im 29-Bit Format in das CANIDT Register geschrieben wurde.

Was da stehen sollte ist:
CANCDMOB = (1<<IDE) | 8;

Das CONMOB0 Bit wird nur gesetzt um die Botschaft einmal abzuschicken.

von Günther M (Gast)


Lesenswert?

Rudolph R. schrieb:
> Was da stehen sollte ist:
> CANCDMOB = (1<<IDE) | 8;

auch das ist nun geändert, aber leider keine Besserung.
Noch immer macht das erste Byte was es will...

Und ja bei den Kommentaren hast du recht, die waren vertauscht.
So sollte es sein:

// Sender

id = 0x1806E5F4;  // ID vom Sender
id = (id << 3);
CANPAGE = (0<<4);       // Auswählen des MOB0
CANIDT  = id;
CANIDM1 = 0xFF;
CANIDM2 = 0xFF;
CANIDM3 = 0xFF;
CANIDM4 = 0xF8 | (1<<IDEMSK);  // setzten des identifier extension mask
CANCDMOB = (1<<IDE) | 8;
CANSTMOB |= (1<<TXOK);    // Interruptaufruf bei Versandbestätigung


//Empfänger

id = 0x18FF50E5;    // ID vom Empfänger
id = (id << 3);
CANPAGE = (1<<4);    // Auswählen des MOB1
CANIDT = id;
CANIDM1 = 0xFF;
CANIDM2 = 0xFF;
CANIDM3 = 0xFF;
CANIDM4 = 0xF8 | (1<<IDEMSK);  // setzten des identifier extension mask
CANCDMOB = (1<<IDE)|8;

von Rudolph R. (rudolph)


Angehängte Dateien:

Lesenswert?

Günther M schrieb:
> auch das ist nun geändert, aber leider keine Besserung.
> Noch immer macht das erste Byte was es will...

Da nuss immer noch irgendwas verdreht sein, probier es mal  mit dem 
angehängten Test-Projekt.
Das sendet alle 100ms auf 0x1806E5F4 und spiegelt dabei die Daten einer 
mit ID 0x18FF50E5 empfangenen Nachricht.

> CANSTMOB |= (1<<TXOK);    // Interruptaufruf bei Versandbestätigung

Das ist nicht was damit ausgelöst wird, also der Kommentar passt nicht.

> //Empfänger
> CANCDMOB = (1<<IDE)|8;

Damit wird noch nichts empfangen.

CANCDMOB = (1<<CONMOB1) | (1<<IDE) | 8;

von Günther M (Gast)


Angehängte Dateien:

Lesenswert?

Rudolph R. schrieb:
> Da nuss immer noch irgendwas verdreht sein, probier es mal  mit dem
> angehängten Test-Projekt.
> Das sendet alle 100ms auf 0x1806E5F4 und spiegelt dabei die Daten einer
> mit ID 0x18FF50E5 empfangenen Nachricht.

wie im Bild zusehen sendet das erste Byte auch in diesem Programm 
einfach irgendwelche willkürlichen Daten.

von Günther M (Gast)


Angehängte Dateien:

Lesenswert?

Günther M schrieb:
>> Das sendet alle 100ms auf 0x1806E5F4 und spiegelt dabei die Daten einer
>> mit ID 0x18FF50E5 empfangenen Nachricht.

hier nochmal ein kleines Video darüber dort kann man es besser sehen

von Rudolph R. (rudolph)


Angehängte Dateien:

Lesenswert?

Was ist das für eine Software und was für ein CAN-Interface?

Ich bin jetzt extra noch mal mit der Schaufel in den Keller gegangen um 
das Board mit dem AT90CAN128 noch mal auszugraben.

Und hier funktioniert das wie es soll.
Das erste Bild ist einfach die Sende-Botschaft, das zweite Bild zeigt 
wie die Empfangs-Botschaft auf die Sende-Botschaft gespiegelt wird.

Das ist eine proprietäre Software und das Interface ein Vector VN1630.

Edit: die Forums-Software killt fast die Daten-Bytes, warum auch immer 
die .png überhaupt automatisch neu komprimiert werden.
Dann eben noch mal als .jpg.

: Bearbeitet durch User
von Günther M (Gast)


Angehängte Dateien:

Lesenswert?

Rudolph R. schrieb:
> Das erste Bild ist einfach die Sende-Botschaft, das zweite Bild zeigt
> wie die Empfangs-Botschaft auf die Sende-Botschaft gespiegelt wird.


ersteinmal vielen vielen Dank für deine große Mühe!!!

dann scheint es vielleicht wirklich einfach an der Software zu liegen, 
diese nennt sich CAN-Monitor mit deren CAN Interface.
http://www.kmtecsoft.de/index.html

ich hab im Anhang jetzt nochmal mein aktuelles Programm eingefügt und 
nochmal ein Video was meine Software mir gerade anzeigt, könntest du 
diesen code vielleicht mit deiner Software einmal auslesen? Dies würde 
mir enorm helfen, nochmals vielen vielen Dank!

von Rudolph R. (rudolph)


Lesenswert?

Dein Testprogramm sendet hier gerade fröhlich vor sich hin, einmal pro 
Sekunde kommt da auf ID 0x1806E5F4: 01 02 03 04 00 00 00 00

Ich habe das direkt so wie das im Archiv ist compiliert und gebrannt.
Auf meiner Platine ist ausser dem CAN nichts am Controller 
angeschlossen, da sind dann auch irgendwelche I/Os mit denen zusätzlich 
gewackelt wird egal.

Mit 11 Bit IDs passiert sowas in der Software aber nicht?
Schick denen auf jeden Fall mal einen Bug-Report.
Das scheint schon etwas angestaubt zu sein, vor allem die Hardware, das 
wird aber wohl noch gepflegt.


Die Ordner-Struktur von Deinem Testprojekt ist etwas seltsam, wo fallen 
solche Projekte raus?

von Günther M (Gast)


Lesenswert?

Rudolph R. schrieb:
> Dein Testprogramm sendet hier gerade fröhlich vor sich hin, einmal pro
> Sekunde kommt da auf ID 0x1806E5F4: 01 02 03 04 00 00 00 00

Guten Morgen,
bin heute morgen direkt einen anderes CAN Interface ausprobiert, siehe 
da funktioniert :)
Danke die für deine ganze Mühe und Hilfe, hätte wahrscheinlich noch ewig 
gesucht...

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.