www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT90CAN mehrere Mobs


Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

bisher kann ich ein einziges Mob versckicken und auch empfangen. Nun 
will ich zwei Mobs versckicken und empfangen nur es klappt irgendwie 
nicht. Die CAN Initialisierung in main sieht so aus:
//CAN-Initialisierung
CANBT1=0x08;
CANBT2=0x0C;
CANBT3=0x37;
CANGIE|=(1<<ENIT)|(1<<ENTX);
CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
CANPAGE=0x08; //Auto Increment off
CANIDT1=0x55;
CANIDT2=0x00;
CANIDT3=0x00;
CANIDT4=0x00;
CANSTMOB=0x00;
CANCDMOB=0x48;  
CANGCON|=(1<<ENASTB);
sei();
In der while(1) Schleife des Senders mache ich prinzipiell folgendes.
if((Eingabe!=Eingabe_old)&&(!My_CAN_Flag))//if new input and message sent
    {
      My_CAN_Flag=0x01;//trying to send
      for(int i=0;i<8;i++)//Mob0
      {
      CANPAGE=8+i;
      CANMSG=latitude[i];
      }
      for(int i=0;i<3;i++)//Mob1
      {
      CANPAGE=40+i;
      CANMSG=latitude[i+8];
      }
    
      CANSTMOB=0x00;//Status reset
      CANCDMOB=0x48;//enable transmission, set 11bit identifier, send 8 bytes
    }
Die Init beim Empfänger sieht so aus:
//CAN-Init
  CANBT1=0x08;
  CANBT2=0x0C;
  CANBT3=0x37;
  CANGIE|=(1<<ENIT)|(1<<ENRX);
  CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
  CANPAGE=0x08;//Mob0, auto increment off, Byte0
  CANIDT1=0x55;
  CANIDT2=0x00;
  CANIDT3=0x00;
  CANIDT4=0x00;
  CANIDM1=0xFF;
  CANIDM2=0xE0;
  CANIDM3=0x00;
  CANIDM4=0x05;
  CANSTMOB=0x00;
  CANCDMOB=0x88;
  CANGCON|=(1<<ENASTB);
  sei();  
Und die Empfangsroutine in der while(1) so:
if(My_Interrupt_Flag)
    {
      
      for(int i=0;i<8;i++)
      {
      CANPAGE=8+i;
      latitude[i]=CANMSG;
      }
      for(int i=0;i<3;i++)
      {
      CANPAGE=40+i;
      latitude[i+8]=CANMSG;
      }
      CANSTMOB=0x00;
      CANCDMOB=0x88;//enable receiver, receive 8 bytes
      My_Interrupt_Flag=0;
    
    }
Wenn ich beim Sender
for(int i=0;i<3;i++)//Mob1
      {
      CANPAGE=40+i;
      CANMSG=latitude[i+8];
      }
weglasse und beim Empfänger
for(int i=0;i<3;i++)
      {
      CANPAGE=40+i;
      latitude[i+8]=CANMSG;
      }
weglasse und jeweils in CANIE2 nur den Mob0 Interrupt freischalte, also 
quasi nur Mob0 benutze kann ich prima senden und empfangen. Warum gehts 
mit Mob0 und Mob1 nicht?

Vielen Dank schon mal im Voraus!
Gruß
Franz

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab jetzt versucht jedem Mob0 und Mob1 jeweils eine eigene ID zu geben 
kann aber trotzdem nichts empfangen.

Empfänger Init:
//CAN-Init
  CANBT1=0x08;
  CANBT2=0x0C;
  CANBT3=0x37;
  CANGIE|=(1<<ENIT)|(1<<ENRX);
  CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
  CANPAGE=0x08;//Mob0, auto increment off, Byte0
  CANIDT1=0x55;
  CANIDT2=0x00;
  CANIDT3=0x00;
  CANIDT4=0x00;
  CANIDM1=0xFF;
  CANIDM2=0xE0;
  CANIDM3=0x00;
  CANIDM4=0x05;
  CANSTMOB=0x00;//reset status register
  CANCDMOB=0x88;//Enable receiver, receive 8 bytes
  
  CANPAGE=0x28;//Mob1, auto increment off, Byte0
  CANIDT1=0x56;
  CANIDT2=0x00;
  CANIDT3=0x00;
  CANIDT4=0x00;
  CANIDM1=0xFF;
  CANIDM2=0xE0;
  CANIDM3=0x00;
  CANIDM4=0x05;
  CANSTMOB=0x00;//reset status register
  CANCDMOB=0x88;//Enable receiver, receive 8 bytes
  CANGCON|=(1<<ENASTB);

Sender Init:
//CAN-Initialisierung
CANBT1=0x08;
CANBT2=0x0C;
CANBT3=0x37;
CANGIE|=(1<<ENIT)|(1<<ENTX);
CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);

CANPAGE=0x08; //Mob0, auto increment off
CANIDT1=0x55;
CANIDT2=0x00;
CANIDT3=0x00;
CANIDT4=0x00;
CANSTMOB=0x00;
CANCDMOB=0x48;  

CANPAGE=0x28;//Mob1, auto increment off
CANIDT1=0x56;
CANIDT2=0x00;
CANIDT3=0x00;
CANIDT4=0x00;
CANSTMOB=0x00;//reset status register
CANCDMOB=0x48;//Enable transmitter, send 8 bytes

CANGCON|=(1<<ENASTB);

Irgendjemand ne Idee?
Gruß Franz

Autor: tex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da Du immer nur ein MOB initialisierst, kann auch nur ein MOB aktiv 
sein.

Autor: tex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal eine Routine um alle MOBs zu bereinigen.
Die Initialisierung erfolgt auf genau die gleiche Weise
void Can_clear_all_MOB (void)
{
  int num_mob, num_data;

  for (num_mob = 0; num_mob < 15; num_mob++)
  {
    CANPAGE  = (num_mob << 4);
    CANSTMOB = 0;
    CANCDMOB = 0;
    CANIDT4  = 0;
    CANIDT3  = 0;
    CANIDT2  = 0;
    CANIDT1  = 0;
    CANIDM4  = 0;
    CANIDM3  = 0;
    CANIDM2  = 0;
    CANIDM1  = 0;
    for (num_data = 0; num_data < 8; num_data++)
    {
      CANMSG = 0;
    }
  }
}

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke tex für deine Antwort. Wenn ich die einzelnen Mobs aktiviere kann 
ich nun auch beide Empfangen. Nun habe ich erweitert auf insgesamt 4 
Mobs und kann aber nur die ersten zwei emfpangen (Interrupt für mob2 und 
mob3 wird nich aufgerufen). Ich habe jetzt die Verarbeitung allerdings 
in die ISR ausgelagert was aber nichts ausmachen dürfte da es mit nur 2 
mobs ja funktioniert. Wäre super wenn mal jemand grob über den etwas 
länglichen code schauen könnte warum ich nur die ersten zwei mobs 
empfangen kann.
Vielen Dank
Franz

Sender init:
void InitCAN(void)
{
  // baud rate = 500 Kbps
  CANBT1  = 0x08;
  CANBT2  = 0x0C;
  CANBT3  = 0x37;
  // interrupt in message reception
  CANGIE  |= (1<<ENIT)|(1<<ENTX);
  // interrupt on message objects 0 and 1
  CANIE2  |= (1<<IEMOB0) | (1<<IEMOB1)| (1<<IEMOB2)| (1<<IEMOB3);

  // message object 0 configuration, index auto increment
  CANPAGE  = 0x00;
  // message identifier: 0x00A
  CANIDT1  = 0x55;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x48;

  // message object 1 configuration, index auto increment
  CANPAGE  = 0x10;
  // message identifier: 0x032
  CANIDT1  = 0x56;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x48;
  // message object 2 configuration, index auto increment
  CANPAGE  = 0x20;
  // message identifier: 0x032
  CANIDT1  = 0x57;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x48;

  // message object 3 configuration, index auto increment
  CANPAGE  = 0x30;
  // message identifier: 0x032
  CANIDT1  = 0x58;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x48;

  // enable mode
  CANGCON  |= (1<<ENASTB);
}
Sender ISR
ISR(CANIT_vect)
{
  //if(Eingabe!=Eingabe_old)
  //{
    // check message object number of most important pending interrupt
    if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==0)
    {
        // set data pointer to register for message object 0
        CANPAGE = 0x00;

        for(int i=0;i<8;i++)
        {
          CANMSG=latitude[i];
        }
        // every status flags cleared
        CANSTMOB  = 0x00;
        // transmission enabled (must be performed after data transfer)
        // data length = 8 Byte
        CANCDMOB  = 0x48;
        Eingabe_old=Eingabe;
        //break;
    }
    else
    if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==0)
    {
        // set data pointer to register for message object 1
        CANPAGE = 0x10;
      
        for(int i=0;i<8;i++)
        {
          CANMSG=latitude[i+8];
        }
        // every status flags cleared
        CANSTMOB  = 0x00;
        // transmission enabled (must be performed after data transfer)
        // data length = 8 Byte
        CANCDMOB = 0x48;
        Eingabe_old=Eingabe;
        //break;
    }
    else
    if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==1)
    {
        // set data pointer to register for message object 2
        CANPAGE = 0x20;
      
        for(int i=0;i<8;i++)
        {
          CANMSG=longitude[i];
        }
        // every status flags cleared
        CANSTMOB  = 0x00;
        // transmission enabled (must be performed after data transfer)
        // data length = 8 Byte
        CANCDMOB = 0x48;
        Eingabe_old=Eingabe;
        //break;
    }
    else
    if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==1)
    {
        // set data pointer to register for message object 3
        CANPAGE = 0x30;
      
        for(int i=0;i<8;i++)
        {
          CANMSG=longitude[i+8];
        }
        // every status flags cleared
        CANSTMOB  = 0x00;
        // transmission enabled (must be performed after data transfer)
        // data length = 8 Byte
        CANCDMOB = 0x48;
        Eingabe_old=Eingabe;
        //break;
    }
  
}
Emfänger Init:
void InitCAN(void)
{
  // baud rate = 500 Kbps
  CANBT1  = 0x08;
  CANBT2  = 0x0C;
  CANBT3  = 0x37;
  // interrupt in message reception
  CANGIE  |= (1<<ENIT)|(1<<ENRX);
  // interrupt on message objects 0 and 1
  CANIE2  |= (1<<IEMOB0) | (1<<IEMOB1)| (1<<IEMOB2)| (1<<IEMOB3);

  // message object 0 configuration, index auto increment
  CANPAGE  = 0x00;
  // message identifier: 0x00A
  CANIDT1  = 0x55;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // only the defined message identifier is regarded
  CANIDM1  = 0xFF;
  CANIDM2  = 0xE0;
  CANIDM3  = 0x00;
  CANIDM4  = 0x05;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x88;

  // message object 1 configuration, index auto increment
  CANPAGE  = 0x10;
  // message identifier: 0x032
  CANIDT1  = 0x56;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // only the defined message identifier is regarded
  CANIDM1  = 0xFF;
  CANIDM2  = 0xE0;
  CANIDM3  = 0x00;
  CANIDM4  = 0x05;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x88;


  // message object 2 configuration, index auto increment
  CANPAGE  = 0x20;
  // message identifier: 0x032
  CANIDT1  = 0x57;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // only the defined message identifier is regarded
  CANIDM1  = 0xFF;
  CANIDM2  = 0xE0;
  CANIDM3  = 0x00;
  CANIDM4  = 0x05;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x88;


  // message object 3 configuration, index auto increment
  CANPAGE  = 0x30;
  // message identifier: 0x032
  CANIDT1  = 0x58;
  CANIDT2  = 0x00;
  CANIDT3  = 0x00;
  CANIDT4  = 0x00;
  // only the defined message identifier is regarded
  CANIDM1  = 0xFF;
  CANIDM2  = 0xE0;
  CANIDM3  = 0x00;
  CANIDM4  = 0x05;
  // every status flags cleared
  CANSTMOB  = 0x00;
  // reception enabled (must be performed after data transfer)
  // data length = 8 Byte
  CANCDMOB  = 0x88;

  // enable mode
  CANGCON  |= (1<<ENASTB);
}
Empfänger ISR:
ISR(CANIT_vect)
{
  // check message object number of most important pending interrupt
  if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==0 )
  {
      // set data pointer to register for message object 0
      CANPAGE = 0x00;

      for(int i=0;i<8;i++)
      {
        latitude[i]=CANMSG;
      }
      // every status flags cleared
      CANSTMOB  = 0x00;
      // reception enabled (must be performed after data transfer)
      // data length = 8 Byte
      CANCDMOB  = 0x88;
      //break;
  }
  if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==0)
  {
      // set data pointer to register for message object 1
      CANPAGE = 0x10;
      
      for(int i=0;i<8;i++)
      {
        latitude[i+8]=CANMSG;
      }

      //CANPAGE = 0x10;

      // every status flags cleared
      CANSTMOB  = 0x00;
      // reception enabled (must be performed after data transfer)
      // data length = 8 Byte
      CANCDMOB = 0x88;
      //break;
  }
  if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==1)
  {
      // set data pointer to register for message object 2
      CANPAGE = 0x20;

      for(int i=0;i<8;i++)
      {
        longitude[i]=CANMSG;
      }
      // every status flags cleared
      CANSTMOB  = 0x00;
      // reception enabled (must be performed after data transfer)
      // data length = 8 Byte
      CANCDMOB  = 0x88;
      //break;
  }
  if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==1)
  {
      // set data pointer to register for message object 3
      CANPAGE = 0x30;

      for(int i=0;i<8;i++)
      {
        longitude[i+8]=CANMSG;
      }
      // every status flags cleared
      CANSTMOB  = 0x00;
      // reception enabled (must be performed after data transfer)
      // data length = 8 Byte
      CANCDMOB  = 0x88;
      //break;
  }
}

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun nochmal ne allgemeinere Frage. Wie seht ihr welches Mob die ISR 
aufgerufen hat? Anscheinend kann werden nur Interrupts für Mob0 und Mob1 
aufgerufen was wahrscheinlich daran liegt, dass Mob0 und Mob1 von der 
Priorität her höher sind und deswegen Mob2 und 3 nicht zum zuge kommen 
können. Wenn ich wüsste ob mob0 oder 1 den Interrupt aufgerufen hat 
könnte ich die beiden ja solange sperren bis mob 2 und 3 abgearbeitet 
wurden. Mit der Abfrage auf CANHPMOB hauts nicht hin und es zeigt bei 
jedem ISR Aufruf 0x00 an.
Vielen Dank
Franz

Autor: cskulkw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da mußt Du dazu jedes mal CANSIT1 und/ oder CANSIT2 bemühen.

Weil das Auswerten dieser Register seine Zeit braucht, habe ich mich von 
diesem Chip verabschiedet, weil jeder Zugriff stets über Register 
abgewickelt wird.

Autor: Franz Weidner (woppi666)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe ich jetzt versucht mit CANSIT2 nur ist das Problem dass wenn ich in 
die ISR springe zeigt mit CANSIT2 an dass meistens alle 4 Interrupts auf 
einmal gekommen sind oder bestens mal dass Interrupt von Mob0 und 1 
gemeinsam gekommen sind. Also was kann ich machen damit nur jeweils ein 
Interrupt aufgerufen wird?

Autor: cskulkw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, willkommen in der Interruptprogrammierung des 90CANxxx.


CAN Enable Interrupt MOb Registers - CANIE2 and CANIE1



hier schaltest Du nur die MOBs frei, die reagieren sollen.


Eigentlich ganz einfach.

Aber wenn man das Datasheet sich das erste Mal zu Gemüte führt raucht 
der Kopf.

Es hilft nichts -> dran bleiben.

Viel Erfolg

Autor: tex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf den letzten Seiten des Datenblattes findest Du die Zeiten, die die 
einzelnen Prozesse in Anspruch nehmen. Es ist ausgesprochen 
unschicklich, sein Programm mit hunderten von IRSs zu traktieren, ohne 
sich zuvor Gedanken darüber gemacht zu haben, was eine ISR eigentlich im 
Prozessor und den Registern bewirkt. Da Du vermutlich genau so 
rücksichtslos mit den übrigen ISRs umgesprungen bist, wie mit den hier 
dargestellten ISRs würde ich behaupten, dass Dein Problem nicht an dem 
Befehl oder der Zeile liegt, sondern schlicht in der Struktur Deines 
Programms zu suchen ist.
Vermutlich läuft Deine komplette Datums- und Uhrzeitberechnung ebenso in 
einer ISR wie die UART- Verarbeitung usw.
Die ISR entbindet nicht von der Verpflichtung, über eine geordnete 
Programmstruktur nachdenken zu müssen, die setzt diese voraus.
Schau Dir nur mal diese beiden Monstren an die Du hier als ISR gepostet 
hast und überlege Dir mal, wie lange Dein Prozessor damit beschäftigt 
ist, diese abzuarbeiten.
ISRs sollte man nach Möglichkeit vermeiden und wirklich nur für 
zeitkritische Anwendungen verwenden.
Hast Du irgend wo in Deinem Programm, Z.B. für das Display noch 
Warteschleifen? ... Und warum muss der Prozessor da sinnlos rumsitzen 
und Däumchen drehen, statt mal eben die UART und CAN-Register 
abzufragen, die Uhrzeit und den Kalender berechnen oder was sonst noch 
so sinnloses zu tun ist? Klar, dann kann man ihn ja nicht via IRS aus 
seiner Arbeit reißen, wenn er wirklich was zu tun hat.

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank Leute mittlerweile hab dich die Sache zum laufen gebracht. 
Ich hab auch die Verarbeitung wieder ins Hauptprogramm geholt und frage 
ein CAN Interrupt Flag ab. Erkennen welches Mob gerade an der Reihe ist 
mache ich über CANHPMOB. Nach der Abarbeitung eines Mobs schalte ich das 
CANIE dieses Mobs aus und die anderen je nach Priorität an. Ein 
Ringpuffer also sozusagen. Damit dürte ich nun auch in der Lage sein 
alle 14 Mobs zu versenden/empfangen falls benötigt.

Gruß Franz

Autor: wikky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Franz,

meinste Du könntest mir mal Dein Programm posten??

Da mein Programm nicht in die ISR sprinen möchte..............ich 
verzweifle noch!!!
Sendest Du die Daten über TXCAN???

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.