Forum: Mikrocontroller und Digitale Elektronik AT90CAN mehrere Mobs


von Franz (Gast)


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:
1
//CAN-Initialisierung
2
CANBT1=0x08;
3
CANBT2=0x0C;
4
CANBT3=0x37;
5
CANGIE|=(1<<ENIT)|(1<<ENTX);
6
CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
7
CANPAGE=0x08; //Auto Increment off
8
CANIDT1=0x55;
9
CANIDT2=0x00;
10
CANIDT3=0x00;
11
CANIDT4=0x00;
12
CANSTMOB=0x00;
13
CANCDMOB=0x48;  
14
CANGCON|=(1<<ENASTB);
15
sei();
In der while(1) Schleife des Senders mache ich prinzipiell folgendes.
1
if((Eingabe!=Eingabe_old)&&(!My_CAN_Flag))//if new input and message sent
2
    {
3
      My_CAN_Flag=0x01;//trying to send
4
      for(int i=0;i<8;i++)//Mob0
5
      {
6
      CANPAGE=8+i;
7
      CANMSG=latitude[i];
8
      }
9
      for(int i=0;i<3;i++)//Mob1
10
      {
11
      CANPAGE=40+i;
12
      CANMSG=latitude[i+8];
13
      }
14
    
15
      CANSTMOB=0x00;//Status reset
16
      CANCDMOB=0x48;//enable transmission, set 11bit identifier, send 8 bytes
17
    }
Die Init beim Empfänger sieht so aus:
1
//CAN-Init
2
  CANBT1=0x08;
3
  CANBT2=0x0C;
4
  CANBT3=0x37;
5
  CANGIE|=(1<<ENIT)|(1<<ENRX);
6
  CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
7
  CANPAGE=0x08;//Mob0, auto increment off, Byte0
8
  CANIDT1=0x55;
9
  CANIDT2=0x00;
10
  CANIDT3=0x00;
11
  CANIDT4=0x00;
12
  CANIDM1=0xFF;
13
  CANIDM2=0xE0;
14
  CANIDM3=0x00;
15
  CANIDM4=0x05;
16
  CANSTMOB=0x00;
17
  CANCDMOB=0x88;
18
  CANGCON|=(1<<ENASTB);
19
  sei();
Und die Empfangsroutine in der while(1) so:
1
if(My_Interrupt_Flag)
2
    {
3
      
4
      for(int i=0;i<8;i++)
5
      {
6
      CANPAGE=8+i;
7
      latitude[i]=CANMSG;
8
      }
9
      for(int i=0;i<3;i++)
10
      {
11
      CANPAGE=40+i;
12
      latitude[i+8]=CANMSG;
13
      }
14
      CANSTMOB=0x00;
15
      CANCDMOB=0x88;//enable receiver, receive 8 bytes
16
      My_Interrupt_Flag=0;
17
    
18
    }
Wenn ich beim Sender
1
for(int i=0;i<3;i++)//Mob1
2
      {
3
      CANPAGE=40+i;
4
      CANMSG=latitude[i+8];
5
      }
weglasse und beim Empfänger
1
for(int i=0;i<3;i++)
2
      {
3
      CANPAGE=40+i;
4
      latitude[i+8]=CANMSG;
5
      }
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

von Franz (Gast)


Lesenswert?

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

Empfänger Init:
1
//CAN-Init
2
  CANBT1=0x08;
3
  CANBT2=0x0C;
4
  CANBT3=0x37;
5
  CANGIE|=(1<<ENIT)|(1<<ENRX);
6
  CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
7
  CANPAGE=0x08;//Mob0, auto increment off, Byte0
8
  CANIDT1=0x55;
9
  CANIDT2=0x00;
10
  CANIDT3=0x00;
11
  CANIDT4=0x00;
12
  CANIDM1=0xFF;
13
  CANIDM2=0xE0;
14
  CANIDM3=0x00;
15
  CANIDM4=0x05;
16
  CANSTMOB=0x00;//reset status register
17
  CANCDMOB=0x88;//Enable receiver, receive 8 bytes
18
  
19
  CANPAGE=0x28;//Mob1, auto increment off, Byte0
20
  CANIDT1=0x56;
21
  CANIDT2=0x00;
22
  CANIDT3=0x00;
23
  CANIDT4=0x00;
24
  CANIDM1=0xFF;
25
  CANIDM2=0xE0;
26
  CANIDM3=0x00;
27
  CANIDM4=0x05;
28
  CANSTMOB=0x00;//reset status register
29
  CANCDMOB=0x88;//Enable receiver, receive 8 bytes
30
  CANGCON|=(1<<ENASTB);

Sender Init:
1
//CAN-Initialisierung
2
CANBT1=0x08;
3
CANBT2=0x0C;
4
CANBT3=0x37;
5
CANGIE|=(1<<ENIT)|(1<<ENTX);
6
CANIE2|=(1<<IEMOB0)|(1<<IEMOB1);
7
8
CANPAGE=0x08; //Mob0, auto increment off
9
CANIDT1=0x55;
10
CANIDT2=0x00;
11
CANIDT3=0x00;
12
CANIDT4=0x00;
13
CANSTMOB=0x00;
14
CANCDMOB=0x48;  
15
16
CANPAGE=0x28;//Mob1, auto increment off
17
CANIDT1=0x56;
18
CANIDT2=0x00;
19
CANIDT3=0x00;
20
CANIDT4=0x00;
21
CANSTMOB=0x00;//reset status register
22
CANCDMOB=0x48;//Enable transmitter, send 8 bytes
23
24
CANGCON|=(1<<ENASTB);

Irgendjemand ne Idee?
Gruß Franz

von tex (Gast)


Lesenswert?

Da Du immer nur ein MOB initialisierst, kann auch nur ein MOB aktiv 
sein.

von tex (Gast)


Lesenswert?

Hier mal eine Routine um alle MOBs zu bereinigen.
Die Initialisierung erfolgt auf genau die gleiche Weise
1
void Can_clear_all_MOB (void)
2
{
3
  int num_mob, num_data;
4
5
  for (num_mob = 0; num_mob < 15; num_mob++)
6
  {
7
    CANPAGE  = (num_mob << 4);
8
    CANSTMOB = 0;
9
    CANCDMOB = 0;
10
    CANIDT4  = 0;
11
    CANIDT3  = 0;
12
    CANIDT2  = 0;
13
    CANIDT1  = 0;
14
    CANIDM4  = 0;
15
    CANIDM3  = 0;
16
    CANIDM2  = 0;
17
    CANIDM1  = 0;
18
    for (num_data = 0; num_data < 8; num_data++)
19
    {
20
      CANMSG = 0;
21
    }
22
  }
23
}

von Franz (Gast)


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:
1
void InitCAN(void)
2
{
3
  // baud rate = 500 Kbps
4
  CANBT1  = 0x08;
5
  CANBT2  = 0x0C;
6
  CANBT3  = 0x37;
7
  // interrupt in message reception
8
  CANGIE  |= (1<<ENIT)|(1<<ENTX);
9
  // interrupt on message objects 0 and 1
10
  CANIE2  |= (1<<IEMOB0) | (1<<IEMOB1)| (1<<IEMOB2)| (1<<IEMOB3);
11
12
  // message object 0 configuration, index auto increment
13
  CANPAGE  = 0x00;
14
  // message identifier: 0x00A
15
  CANIDT1  = 0x55;
16
  CANIDT2  = 0x00;
17
  CANIDT3  = 0x00;
18
  CANIDT4  = 0x00;
19
  // every status flags cleared
20
  CANSTMOB  = 0x00;
21
  // reception enabled (must be performed after data transfer)
22
  // data length = 8 Byte
23
  CANCDMOB  = 0x48;
24
25
  // message object 1 configuration, index auto increment
26
  CANPAGE  = 0x10;
27
  // message identifier: 0x032
28
  CANIDT1  = 0x56;
29
  CANIDT2  = 0x00;
30
  CANIDT3  = 0x00;
31
  CANIDT4  = 0x00;
32
  // every status flags cleared
33
  CANSTMOB  = 0x00;
34
  // reception enabled (must be performed after data transfer)
35
  // data length = 8 Byte
36
  CANCDMOB  = 0x48;
37
  // message object 2 configuration, index auto increment
38
  CANPAGE  = 0x20;
39
  // message identifier: 0x032
40
  CANIDT1  = 0x57;
41
  CANIDT2  = 0x00;
42
  CANIDT3  = 0x00;
43
  CANIDT4  = 0x00;
44
  // every status flags cleared
45
  CANSTMOB  = 0x00;
46
  // reception enabled (must be performed after data transfer)
47
  // data length = 8 Byte
48
  CANCDMOB  = 0x48;
49
50
  // message object 3 configuration, index auto increment
51
  CANPAGE  = 0x30;
52
  // message identifier: 0x032
53
  CANIDT1  = 0x58;
54
  CANIDT2  = 0x00;
55
  CANIDT3  = 0x00;
56
  CANIDT4  = 0x00;
57
  // every status flags cleared
58
  CANSTMOB  = 0x00;
59
  // reception enabled (must be performed after data transfer)
60
  // data length = 8 Byte
61
  CANCDMOB  = 0x48;
62
63
  // enable mode
64
  CANGCON  |= (1<<ENASTB);
65
}
Sender ISR
1
ISR(CANIT_vect)
2
{
3
  //if(Eingabe!=Eingabe_old)
4
  //{
5
    // check message object number of most important pending interrupt
6
    if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==0)
7
    {
8
        // set data pointer to register for message object 0
9
        CANPAGE = 0x00;
10
11
        for(int i=0;i<8;i++)
12
        {
13
          CANMSG=latitude[i];
14
        }
15
        // every status flags cleared
16
        CANSTMOB  = 0x00;
17
        // transmission enabled (must be performed after data transfer)
18
        // data length = 8 Byte
19
        CANCDMOB  = 0x48;
20
        Eingabe_old=Eingabe;
21
        //break;
22
    }
23
    else
24
    if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==0)
25
    {
26
        // set data pointer to register for message object 1
27
        CANPAGE = 0x10;
28
      
29
        for(int i=0;i<8;i++)
30
        {
31
          CANMSG=latitude[i+8];
32
        }
33
        // every status flags cleared
34
        CANSTMOB  = 0x00;
35
        // transmission enabled (must be performed after data transfer)
36
        // data length = 8 Byte
37
        CANCDMOB = 0x48;
38
        Eingabe_old=Eingabe;
39
        //break;
40
    }
41
    else
42
    if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==1)
43
    {
44
        // set data pointer to register for message object 2
45
        CANPAGE = 0x20;
46
      
47
        for(int i=0;i<8;i++)
48
        {
49
          CANMSG=longitude[i];
50
        }
51
        // every status flags cleared
52
        CANSTMOB  = 0x00;
53
        // transmission enabled (must be performed after data transfer)
54
        // data length = 8 Byte
55
        CANCDMOB = 0x48;
56
        Eingabe_old=Eingabe;
57
        //break;
58
    }
59
    else
60
    if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==1)
61
    {
62
        // set data pointer to register for message object 3
63
        CANPAGE = 0x30;
64
      
65
        for(int i=0;i<8;i++)
66
        {
67
          CANMSG=longitude[i+8];
68
        }
69
        // every status flags cleared
70
        CANSTMOB  = 0x00;
71
        // transmission enabled (must be performed after data transfer)
72
        // data length = 8 Byte
73
        CANCDMOB = 0x48;
74
        Eingabe_old=Eingabe;
75
        //break;
76
    }
77
  
78
}
Emfänger Init:
1
void InitCAN(void)
2
{
3
  // baud rate = 500 Kbps
4
  CANBT1  = 0x08;
5
  CANBT2  = 0x0C;
6
  CANBT3  = 0x37;
7
  // interrupt in message reception
8
  CANGIE  |= (1<<ENIT)|(1<<ENRX);
9
  // interrupt on message objects 0 and 1
10
  CANIE2  |= (1<<IEMOB0) | (1<<IEMOB1)| (1<<IEMOB2)| (1<<IEMOB3);
11
12
  // message object 0 configuration, index auto increment
13
  CANPAGE  = 0x00;
14
  // message identifier: 0x00A
15
  CANIDT1  = 0x55;
16
  CANIDT2  = 0x00;
17
  CANIDT3  = 0x00;
18
  CANIDT4  = 0x00;
19
  // only the defined message identifier is regarded
20
  CANIDM1  = 0xFF;
21
  CANIDM2  = 0xE0;
22
  CANIDM3  = 0x00;
23
  CANIDM4  = 0x05;
24
  // every status flags cleared
25
  CANSTMOB  = 0x00;
26
  // reception enabled (must be performed after data transfer)
27
  // data length = 8 Byte
28
  CANCDMOB  = 0x88;
29
30
  // message object 1 configuration, index auto increment
31
  CANPAGE  = 0x10;
32
  // message identifier: 0x032
33
  CANIDT1  = 0x56;
34
  CANIDT2  = 0x00;
35
  CANIDT3  = 0x00;
36
  CANIDT4  = 0x00;
37
  // only the defined message identifier is regarded
38
  CANIDM1  = 0xFF;
39
  CANIDM2  = 0xE0;
40
  CANIDM3  = 0x00;
41
  CANIDM4  = 0x05;
42
  // every status flags cleared
43
  CANSTMOB  = 0x00;
44
  // reception enabled (must be performed after data transfer)
45
  // data length = 8 Byte
46
  CANCDMOB  = 0x88;
47
48
49
  // message object 2 configuration, index auto increment
50
  CANPAGE  = 0x20;
51
  // message identifier: 0x032
52
  CANIDT1  = 0x57;
53
  CANIDT2  = 0x00;
54
  CANIDT3  = 0x00;
55
  CANIDT4  = 0x00;
56
  // only the defined message identifier is regarded
57
  CANIDM1  = 0xFF;
58
  CANIDM2  = 0xE0;
59
  CANIDM3  = 0x00;
60
  CANIDM4  = 0x05;
61
  // every status flags cleared
62
  CANSTMOB  = 0x00;
63
  // reception enabled (must be performed after data transfer)
64
  // data length = 8 Byte
65
  CANCDMOB  = 0x88;
66
67
68
  // message object 3 configuration, index auto increment
69
  CANPAGE  = 0x30;
70
  // message identifier: 0x032
71
  CANIDT1  = 0x58;
72
  CANIDT2  = 0x00;
73
  CANIDT3  = 0x00;
74
  CANIDT4  = 0x00;
75
  // only the defined message identifier is regarded
76
  CANIDM1  = 0xFF;
77
  CANIDM2  = 0xE0;
78
  CANIDM3  = 0x00;
79
  CANIDM4  = 0x05;
80
  // every status flags cleared
81
  CANSTMOB  = 0x00;
82
  // reception enabled (must be performed after data transfer)
83
  // data length = 8 Byte
84
  CANCDMOB  = 0x88;
85
86
  // enable mode
87
  CANGCON  |= (1<<ENASTB);
88
}
Empfänger ISR:
1
ISR(CANIT_vect)
2
{
3
  // check message object number of most important pending interrupt
4
  if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==0 )
5
  {
6
      // set data pointer to register for message object 0
7
      CANPAGE = 0x00;
8
9
      for(int i=0;i<8;i++)
10
      {
11
        latitude[i]=CANMSG;
12
      }
13
      // every status flags cleared
14
      CANSTMOB  = 0x00;
15
      // reception enabled (must be performed after data transfer)
16
      // data length = 8 Byte
17
      CANCDMOB  = 0x88;
18
      //break;
19
  }
20
  if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==0)
21
  {
22
      // set data pointer to register for message object 1
23
      CANPAGE = 0x10;
24
      
25
      for(int i=0;i<8;i++)
26
      {
27
        latitude[i+8]=CANMSG;
28
      }
29
30
      //CANPAGE = 0x10;
31
32
      // every status flags cleared
33
      CANSTMOB  = 0x00;
34
      // reception enabled (must be performed after data transfer)
35
      // data length = 8 Byte
36
      CANCDMOB = 0x88;
37
      //break;
38
  }
39
  if((CANHPMOB >> 4)==0 && (CANHPMOB >> 5)==1)
40
  {
41
      // set data pointer to register for message object 2
42
      CANPAGE = 0x20;
43
44
      for(int i=0;i<8;i++)
45
      {
46
        longitude[i]=CANMSG;
47
      }
48
      // every status flags cleared
49
      CANSTMOB  = 0x00;
50
      // reception enabled (must be performed after data transfer)
51
      // data length = 8 Byte
52
      CANCDMOB  = 0x88;
53
      //break;
54
  }
55
  if((CANHPMOB >> 4)==1 && (CANHPMOB >> 5)==1)
56
  {
57
      // set data pointer to register for message object 3
58
      CANPAGE = 0x30;
59
60
      for(int i=0;i<8;i++)
61
      {
62
        longitude[i+8]=CANMSG;
63
      }
64
      // every status flags cleared
65
      CANSTMOB  = 0x00;
66
      // reception enabled (must be performed after data transfer)
67
      // data length = 8 Byte
68
      CANCDMOB  = 0x88;
69
      //break;
70
  }
71
}

von Franz (Gast)


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

von cskulkw (Gast)


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.

von Franz W. (woppi666)


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?

von cskulkw (Gast)


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

von tex (Gast)


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.

von Franz (Gast)


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

von wikky (Gast)


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

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.