Forum: Mikrocontroller und Digitale Elektronik Can-Bus mehrere Bytes hintereinander senden


von Alexander G. (illness)


Lesenswert?

Hallo, ich habe hier gerade ein kleines Verständnisproblem mit dem 
CAN-Bus.

Ich habe 2 µC Boards mit Can verbunden. Einer sendet ein Byte und der 
andere empfängt dies. (Mit Atmel AT90CAN128)

Hier mal die Programme:

Sender
1
// Definitionen  MOb-Konfiguration
2
#define TX 1
3
#define DLC_1 1
4
#define NO_IDE 0
5
#define NO_Reply 0
6
         
7
const char info1[]PROGMEM = "CAN_Transmit_Data"; 
8
const char info2[]PROGMEM = "20kBis/s, ID: 123h";    
9
//////////////////////////////////////////////////////////
10
// Funktionen für CAN Initialisierung
11
//////////////////////////////////////////////////////////
12
 
13
// Löschen der Konfigurationen von MOb0 ... MOb14
14
void CanClearMOB(void)
15
{  
16
   unsigned char i, j;
17
   for(i=0;i<=14;i++)
18
   {
19
      CANPAGE = (i << 4);  // XXXX0000 -> Autoincrement aktiviert    
20
      CANSTMOB = 0;
21
      CANCDMOB = 0;
22
      CANIDT4 = 0;  
23
      CANIDT3 = 0;
24
      CANIDT2 = 0;      
25
      CANIDT1 = 0;      
26
      CANIDM4 = 0;  
27
      CANIDM3 = 0;
28
      CANIDM2 = 0;      
29
      CANIDM1 = 0;
30
      for(j=0;j<=8;j++)
31
      {
32
         CANMSG=0;        //Autoincrement aktiv     
33
      }      
34
   }
35
}        
36
 
37
///////////////////////////////////
38
//      CAN-Initialisierungen    //
39
///////////////////////////////////
40
41
void CanInit(void)
42
{
43
   CanClearMOB();                         // Alle MOb's löschen
44
45
// Einstellung der Baudrate 20kBit/s
46
    CANBT1 = 0x62;                       // Teiler = 49 
47
    CANBT2 = 0x0C;                       // PRS = 7 TQs, PHS1= 7 TQs, PHS2= 7 TQs
48
    CANBT3 = 0x36;                       // ==> Sample Point bei  75 %
49
   
50
// Initialisierung MOb1 (Sender)    
51
   CANPAGE = (1<<MOBNB1);         // Selektierung von MOb1
52
   //CANPAGE = (1<<MOBNB2);         // Selektierung von MOb2
53
   CANCDMOB|=1;                      // 1 Datenbyte senden
54
   CANCDMOB|=NO_IDE<<4;                  // Botschaft als Standard Frame
55
   CANCDMOB|=NO_Reply<<5;
56
   //CANCDMOB|=TX<<6;                      // Sendemodus einstellen
57
58
// Initialisierung des Identifier (ID=0x123)   
59
   CANIDT1 = 0x123 >>3;                  // Zuweisung ID-Bit 10 - 3
60
   CANIDT2 = 0x123 <<5;                  // Zuweisung ID-Bit  2 - 0
61
62
// CAN Controller aktivieren   
63
   CANGCON |= 0X02;   
64
65
   //CANMSG =0x35;                         // Nutzdatenbyte 35h eintragen
66
}    
67
68
// Hauptprogramm
69
int main(void)
70
{
71
  char display_buffer[21];
72
  unsigned int i=0;
73
  unsigned int k=1;
74
  lcd_init( LCD_DISP_ON );
75
  G_DISPLAY = (1<<BELEUCHTUNG);  
76
  lcd_puts_p(info1);  //Ausgabe von "ROM-Texten" Überschrift
77
  lcd_gotoxy(0,1);
78
  lcd_puts_p(info2);
79
  CanInit();       // Konfiguration und Sendung der Botschaft 
80
81
  while(1)
82
  {
83
84
    //if(k==1) CANMSG =0x11;
85
  //if(k==2) CANMSG =0x22;
86
  //if(k==3) CANMSG =0x33;
87
  //if(k==4) CANMSG =0x44;
88
  //if(k>=5) k=0;
89
     
90
   CANCDMOB = (1 << CONMOB0);    // Botschaft abschicken
91
     
92
   i++;
93
   //k++;
94
   lcd_gotoxy(0,2);
95
     sprintf(display_buffer,"Umlauf: %5d",i);
96
     lcd_puts(display_buffer);
97
     lcd_gotoxy(0,3);
98
     sprintf(display_buffer,"Data: %02x",CANMSG); // Kontrolle auf LCD
99
     lcd_puts(display_buffer);
100
     _delay_ms(1000);
101
  }
102
  return 0;
103
}



************Empfänger*************************************************** 
***************************************
1
// Definitionen  MOb-Selektierung
2
#define MO_1 1
3
4
// Definitionen  MOb-Konfiguration
5
#define RX 2
6
#define DLC_1 1
7
#define NO_IDE 0
8
#define NO_Reply 0
9
         
10
const char info1[]PROGMEM = "CAN_Receive_Data"; 
11
const char info2[]PROGMEM = "20kBis/s, ID: 123h";    
12
//////////////////////////////////////////////////////////
13
// Funktionen für CAN Initialisierung
14
//////////////////////////////////////////////////////////
15
 
16
// Löschen der Konfigurationen von MOb0 ... MOb14
17
void CanClearMOB(void)
18
{  
19
   unsigned char i, j;
20
   for(i=0;i<=14;i++)
21
   {
22
      CANPAGE = (i << 4);  // XXXX0000 -> Autoincrement aktiviert    
23
      CANSTMOB = 0;
24
      CANCDMOB = 0;
25
      CANIDT4 = 0;  
26
      CANIDT3 = 0;
27
      CANIDT2 = 0;      
28
      CANIDT1 = 0;      
29
      CANIDM4 = 0;  
30
      CANIDM3 = 0;
31
      CANIDM2 = 0;      
32
      CANIDM1 = 0;
33
      for(j=0;j<=8;j++)
34
      {
35
         CANMSG=0;        //Autoincrement aktiv     
36
      }      
37
   }
38
}        
39
 
40
///////////////////////////////////
41
//      CAN-Initialisierungen    //
42
///////////////////////////////////
43
44
void CanInit(void)
45
{
46
   CanClearMOB();                         // Alle MOb's löschen
47
48
// Einstellung der Baudrate 20kBit/s
49
    CANBT1 = 0x62;                       // Teiler = 49 
50
    CANBT2 = 0x0C;                       // PRS = 7 TQs, PHS1= 7 TQs, PHS2= 7 TQs
51
    CANBT3 = 0x36;                       // ==> Sample Point bei  75 %
52
   
53
// Initialisierung MOb1 (Sender)    
54
   CANPAGE = (MO_1 << 4) | (AINC << 1);         // Selektierung von MOb1
55
   CANCDMOB|=1;                      // 1 Datenbyte empfangen
56
   CANCDMOB|=NO_IDE<<4;                  // Botschaft als Standard Frame
57
   CANCDMOB|=NO_Reply<<5;
58
   CANCDMOB|=RX<<6;                      // Empfangsmodus einstellen
59
60
// Initialisierung des Identifier (ID=0x123)   
61
   CANIDT1 = 0x123 >>3;                  // Zuweisung ID-Bit 10 - 3
62
   CANIDT2 = 0x123 <<5;                  // Zuweisung ID-Bit  2 - 0
63
64
// CAN Controller aktivieren   
65
   CANGCON |= 0X02;   
66
67
   //CANMSG =0x35;                         // Nutzdatenbyte 35h eintragen
68
}    
69
70
// Hauptprogramm
71
int main(void)
72
{
73
  char display_buffer[21];
74
  unsigned int i=0;
75
  unsigned char data=0;
76
  lcd_init( LCD_DISP_ON );
77
  G_DISPLAY = (1<<BELEUCHTUNG);  
78
  lcd_puts_p(info1);  //Ausgabe von "ROM-Texten" Überschrift
79
  lcd_gotoxy(0,1);
80
  lcd_puts_p(info2);
81
  CanInit();       // Konfiguration und Sendung der Botschaft 
82
83
  while(1){
84
     CANPAGE = (MO_1 << 4);         // Selektierung von MOb1
85
   if(CANSTMOB & 0X20){                // nur wenn Botschaft vorhanden
86
        i++;
87
      lcd_gotoxy(0,2);                      // Anzahl der empfangenen Botschaften 
88
          sprintf(display_buffer,"Anz: %5d",i);
89
          lcd_puts(display_buffer);
90
          data=CANMSG;
91
          lcd_gotoxy(0,3);
92
          sprintf(display_buffer,"Data:   %02X          ",data);  // Botschaftsinhalt
93
          lcd_puts(display_buffer);
94
      CANSTMOB=0X00;      //MO-Status löschen
95
      CANCDMOB|=RX<<6;    // Empfangsmodus einstellen
96
97
   }
98
   else{
99
      if(i==0){
100
          lcd_gotoxy(0,3);
101
          lcd_puts("Keine Daten auf BUS!");
102
        }
103
   }
104
  }
105
  return 0;
106
}
(Habe die includes hier weggelassen)

Ein Byte zu senden ist soweit kein Problem. Aber mehr geht nicht...


Im Register CANCDMOB (CAN MOb Control and DLC Register)kann mit den Bits 
DLC3:0 festgelegt werden wie viele Bytes übertragen werden. Aber ich 
weiss nicht wie ich damit umgehen soll.

Im Empfänger Programm habe ich wie man sieht eine Abfrage eingebaut, das 
er jede Sekunde ein andres Byte sendet (ausgeklammert). Von diesen wird 
am Empfänger jedoch nur das Letzte Byte wiedergegeben. Als wenn er 
Empfänger sagt, "nö ich nehm nur den letzen egal was du tust"...

Wenn ich in dem Register die Byte Anzahl erhöhe, hab ich dann EINEN 
längeren Wert`? Also zum 16Bit oder werden die Bytes nacheinander auf 
die einzelnen Objektregister geschrieben oder wie läuft das ab?

Mein Plan war es zum ausprobieren, mal eben ein Paar Bytes 
hintereinander zu verschicken. Ging beim TWI ja auch...Tja aber falsch 
gedacht :D

Ich hoffe es hat jemand einen Tipp für mich...aber keine Komplettlösung 
bitte....

Gruß Alexander

von TestX .. (xaos)


Lesenswert?

ein CAN frame hat zwischen 1..8bytes -> das ist der DLC wert..
beschäftige dich mal ne runde mit den CAN grundlagen und lies dir im 
datenblatt zum at90can128 mal die funktionsweise der register durch

von Peter D. (peda)


Lesenswert?

Ja, wenn Du nur ein Byte aus dem Puffer ausliest, wird auch nur 1 Byte 
angezeigt.
Leg Dir ein Array aus 8 Bytes an und kopier die komplette Nachricht da 
hinein.


Peter

von nix_guru (Gast)


Lesenswert?

header auslesen, gucken was im dlc für ein wert drin steht, so anzahl an 
byte entsprechend dem wert im dlc auslesen und schon hast du dein 
datenpaket.

von Alexander G. (illness)


Lesenswert?

Das Datenblatt Akker ich schon seit 2 Stunden durch, gott hat das teil 
viele register.....aber Interrups und so interessieren mich ja erstmal 
nicht.

Den wert vom dlc kann ich ja selber festlegen.

Wie soll ich mir da denn nen array reinstopfen? das Register "CANMSG" 
hat ja nur 8Bit.

Wenn ich also den DLC auf "2" stelle, hät ich ja 16Bit...wo bleibt die 
andere Hälfte, wer sagt mir denn wann welche Daten im CANMSG stehen.
Die letzen 8 Bit stehen ja drin....

Hat das was mit den "Pages" zu tun? Das kapier ich nämlich noch nicht ^^

von cskulkw (Gast)


Lesenswert?

Alexander G. schrieb:
> Wie soll ich mir da denn nen array reinstopfen? das Register "CANMSG"
>
> hat ja nur 8Bit.
>
>
>
> Wenn ich also den DLC auf "2" stelle, hät ich ja 16Bit...wo bleibt die
>
> andere Hälfte, wer sagt mir denn wann welche Daten im CANMSG stehen.
>
> Die letzen 8 Bit stehen ja drin....



Alexander G. schrieb:

unit8 var[8];

> for(j=0;j<=8;j++)
>
>       {
>
>          CANMSG=0;        //Autoincrement aktiv

/* so einfach geht das Auslesen. */
           var[j] = CANMSG;

>
>       }

Allerdings muß das AINC - BIt im CANPAGE auf logisch 0 sein.

Viel Erfolg

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.