Forum: Mikrocontroller und Digitale Elektronik Übertragungszeit MCP2551


von Stefan S. (humus)


Lesenswert?

Hallo Zusammen,

ich versuche gerade via Labview mit meinem PIC18F66K80 (mit 18Mhz 
externem Oszillator) und dem dazugehörigen CAN-Transceiver MCP2551 zu 
kommunizieren. Ich habe eine Übertragungsgeschwindigkeit von 1Mbit/s 
eingestellt. Der uC hat die Rolle eines Slave und antwortet nur auf 
Befehl des Master. Das funktioniert im Sekundenbereich einwandfrei:

Messdatenanforderung an PIC -> Senden von 12 CAN-Datenframes mit je 8 X 
Datenbytes an den Master -> Wieder Messdatenanforderung. Jedoch muss ich 
an meinem Master eine Wartezeit von mind. 1300 ms zwischen Senden und 
Empfangen einhalten, um alle 12 CAN-Datenframes zu empfangen. Je weiter 
ich die Zeit reduziere, desto chaotischer und unvollständiger sind die 
Daten. Ich kann sehen das mein uC-Code ca. 700us zum durchlaufen der 
FOR-Schleife mit 12 Durckläufen benötigt. Die theoretische 
Übertragungszeit für den CAN-Datenframe sind 126 us -> 12 x 126 = ca. 
1,5 ms. Zusammen sind das, großzügig gerechnet, 3ms vom Empfang der 
Nachricht bis die Daten theoretische auf dem Bus sein müssten. Ich kann 
mir einfach nicht erklären woher die Differenz von den theoretischen 3 
ms zu den praktischen 1300 ms kommt. Das Datenblatt des MCP hat mir die 
Antwort auch nicht verraten.

Hier mein C-Code:
1
      while (!Msg_Rcvd) Msg_Rcvd = CANRead(&Rx_ID, Rx_Data, &Rx_Data_Len, &Can_Rcv_Flags);
2
      PORTC = 0xff;
3
      if(Rx_ID == IDmodule)
4
      {
5
          Lcd_Cmd(_LCD_CLEAR);               // Clear display
6
          Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
7
          sprintf(lcd_line1, "ID Module = %u OK", IDmodule);                                                                                                                        //The pec_error variable is simply set negative if any PEC errors
8
          Lcd_Out(1,1, lcd_line1);
9
          Delay_ms(1000);
10
          
11
        if (Rx_Data[0] == 9)                     //CAN-Init from master
12
          {
13
          Lcd_Cmd(_LCD_CLEAR);               // Clear display
14
          Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
15
          sprintf(lcd_line1, "ID Module = %u", IDmodule);                                                                                                                        //The pec_error variable is simply set negative if any PEC errors
16
          Lcd_Out(1,1, lcd_line1);
17
          Lcd_Out(2,1, "CAN INIT OK");
18
19
          Tx_ID = IDmaster;
20
          cell_count[0] = 12;                  //LTC1 Cellcount
21
          cell_count[1] = 5;                  //LTC2 Cellcount
22
          Tx_Data[0]= IDmodule-1;
23
          Tx_Data[1]= cell_count[0];
24
          Tx_Data[2]= cell_count[1];
25
          CANWrite(Tx_ID, Tx_Data,3, Can_Send_Flags);
26
          }
27
          
28
          if (Rx_Data[0] == 10)                      //Data acquisation from master
29
         {
30
31
          for (j=0; j<12; j++)
32
            {
33
            Tx_ID = IDmaster;                    //ID receiver
34
            Tx_Data[0]= 0x40;                  //Lowbyte voltage
35
            Tx_Data[1]= 0x9C;                  //Highbyte voltage
36
            Tx_Data[2]= 0x45;                  //Lowbyte temperature
37
            Tx_Data[3]= 0x9C;                  //Highbyte temperature
38
            Tx_Data[4]= 0x50;                  //Lowbyte current
39
            Tx_Data[5]= 0x9C;                  //Highbyte current
40
            Tx_Data[6]= j;                   //Lowbyte cell information (Cellnumber)
41
            Tx_Data[7]= 0x0;                    //Highbyte cell information  (Modulenumber)
42
43
            CANWrite(Tx_ID, Tx_Data,8, Can_Send_Flags);
44
            Delay_ms(1);
45
            PORTC = 0x00;
46
            }
47
48
          }
49
          if(Rx_Data[0] != 9 && Rx_Data[0]!=10)                                         //Send errorcode
50
          {
51
          Tx_ID = IDmaster;
52
          Tx_Data[0]= 0xAB;
53
          CANWrite(Tx_ID, Tx_Data,1, Can_Send_Flags);
54
//          PORTC = 0x3;
55
//          delay_ms(10000);
56
          }
57
      }

Ich gehe von einer korrekten Beschaltung des MCP's aus, da das 
prinzipielle Kommunizieren sauber funktioniert. Jemand hier der 
unterstützen kann, ich weiß echt nicht mehr weiter.

VG und DANKE!!!!

: Bearbeitet durch User
von Harald (Gast)


Lesenswert?

Ein paar Ideen:

- Abschlusswiderstände vorhanden? Bei 1MBit an beiden Seiten wichtig!
- Widerstand an MCP2551 für Flankensteilheit? Der MCP2551 hat recht 
lasche Flanken, kann unter gewissen Umständen zum Problem führen
- Klappen niedrigere Baudraten?
- Lass Dir mal die BusWarnings/Errors mit ausgeben (Im Falle eines 
Errors könnte das die lange Recovery-Zeit erklären)
- Hast Du ein Scope zur Hand? Falls nicht, kauf Dir zumindest ein 
Logic-Analyzer-Clone für 8Euro und schaue mit SIGROK auf den Bus

von CANNOT (Gast)


Lesenswert?

Diese Zeile aus deinem Code sieht verdächtig aus:
Delay_ms(1000);

von Stefan S. (humus)


Lesenswert?

Hallo Zusammen,

Harald danke für deine Ideen! Das sind Dinge die man als Anfänger nur 
teilweise überprüft. Vor alle Danke für den Tipp mit dem 
Logic-Analyzer-Clone für 8Euro! Die habe ich bis jetzt nur für teuer 
Geld gesehen.

CANNOT, da war der Hund begraben. Ich habe die Zeit auf 0 gesetzt und 
jetzt kann ich alle 30 ms Werte abfragen, das hilft erstmal. Super! 
Manchmal sieht man den Wald vor Bäumen nicht mehr...

VG André

von CANNOT (Gast)


Lesenswert?

Freut mich. Das delay nach dem Senden würde ich noch versuchen durch 
eine passende Zustandsabfrage des CAN controllers zu ersetzen/ergänzen. 
Mailbox frei? Fehler? Die Sorte. Ansosten wirst du dich irgendwann 
wieder wundern wo deine Nachrichten bleiben...

...
CANWrite(Tx_ID, Tx_Data,8, Can_Send_Flags);
Delay_ms(1);
...

Wie bist du denn auf die 700us für die Schleife gekommen?

Viel Erfolg

von Stefan S. (humus)


Lesenswert?

CANNOT schrieb:
> Freut mich. Das delay nach dem Senden würde ich noch versuchen durch
> eine passende Zustandsabfrage des CAN controllers zu ersetzen/ergänzen.
> Mailbox frei? Fehler? Die Sorte. Ansosten wirst du dich irgendwann
> wieder wundern wo deine Nachrichten bleiben...
>
> ...
> CANWrite(Tx_ID, Tx_Data,8, Can_Send_Flags);
> Delay_ms(1);
> ...

-> Ne Idee wie ich das abfragen kann? Ich habe mir da auch schon 
Gedanken darüber gemacht und habe bei der Beschreibung der Library von 
MicroC nur folgendes gefunden: "Returns zero if message cannot be queued 
(buffer full)." 
(http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/can_library.htm#canwrite)

>
> Wie bist du denn auf die 700us für die Schleife gekommen?


-> Auf die 700us bin ich gekommen, indem ich einen Eingang vor Beginn 
der Codesequenz auf High gesetzt habe und nach Beendigung der Schleife 
auf Low. Das ganze habe ich mir am Oszi angesehen.

Nebenbei: Ich frage gerade mit 1Mbit/s ca. 7000 mal hintereinander ab, 
dann ist mein LabView abgestürtzt wegen zu großem Array, aber der 
Controller lief sehr stabil und fehlerfrei! Sehr schön!!!!

: Bearbeitet durch User
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.