Forum: Mikrocontroller und Digitale Elektronik Senden mit MCP2515 Fehler


von kevin m. (kevinm)


Lesenswert?

Guten Tag,

leider hab ich noch immer Probleme mit dem MCP2515. Ich weiß das es 
schon viele Themen hier über diesen Baustein gibt, aber ich komme 
einfach nicht weiter.

Also das Empfangen Klappt mit meinem Aufbau schon mal ohne Probleme. 
Danke nochmal an cskulkw der mir in einem anderem Beitrag hier viel 
geholfen hat.

Jetzt zum Problem: Wenn ich mit meiner Sende Funktion eine Nachricht 
verschicken möchte erkenn ich am Oszi erstmal nichts. Im Register 
TXB0CTRL werden TXREQ und TXERR auf 1 gesetzt. Außerdem wird das 
Register TEC bei jedem Sende-versuch erhöht. Die Register für den Sende 
Buffer sind i.O (ID, DLC und daten passen). Ich bin mir jetzt leider 
nicht mehr sicher aber entweder im Normal Modus oder im One Shot Modus 
kann ich beim versenden erkennen, dass die Spannung kurzzeitig 1x auf 
low geht ( wie eine Spannungspitze halt nur negativ).


Zu erst dachte ich es liegt daran dass ich kein ACK bekomme aber dann 
müsste zumindest etwas auf dem oszi zu sehen sein?

Aufbau:
Atmega644 mit 14,7456 MHZ Quarz
MCP2515 mit 16 MHZ Quarz
MCP2551 als Transiver

1
void can_send_message(CANMessage *p_message)
2
{    
3
4
  uint8_t length = p_message->length;
5
   
6
    SPI_PORT &= ~(1<<SPI_SS);    // CS Low
7
    spi_Transfer(MCP_WRITE_TX | 0x00);
8
9
    // SID
10
    spi_Transfer((uint8_t) (p_message->id>>3));
11
    spi_Transfer((uint8_t) (p_message->id<<5));
12
  
13
    // EID
14
    spi_Transfer(0x00);
15
    spi_Transfer(0x00);
16
17
    // DLC+RTR
18
    if (p_message->rtr)
19
    { 
20
       
21
        // RTR
22
        spi_Transfer((1<<RTR) | length);
23
    }
24
    else
25
    {
26
        // DLC
27
        spi_Transfer(length);
28
       
29
        // Daten
30
        for (uint8_t i=0;i<length;i++) {
31
            spi_Transfer(p_message->data[i]);
32
        }
33
    }
34
  //Fertig! BUFFER 1 VOLLSTÄNDIG
35
    SPI_PORT |= (1<<SPI_SS);      
36
   
37
    asm volatile ("nop");
38
39
  //ABSCHLIEßEN! DATEN SENDEN
40
    SPI_PORT &= ~(1<<SPI_SS);    
41
    spi_Transfer(SPI_RTS | 0x01);
42
    SPI_PORT |= (1<<SPI_SS);      
43
      
44
    
45
      
46
        lcd_clrscr();
47
       char bufferString[500]; 
48
      uint8_t spidata;
49
      char i[10];
50
      spidata = mcp2515_read_register(TXB0CTRL); 
51
      itoa(spidata, i, 2);
52
      sprintf(bufferString, "TXBCTRL: %s \n", i);
53
      lcd_puts(bufferString);  
54
      spidata = mcp2515_read_register(TXB0DLC); 
55
      sprintf(bufferString, "DLC: %x \n", spidata);
56
      lcd_puts(bufferString);    
57
      spidata = mcp2515_read_register(CANCTRL); 
58
      itoa(spidata, i, 2);
59
      sprintf(bufferString, "CANCTRL: %s \n", i);
60
      lcd_puts(bufferString);    
61
      spidata = mcp2515_read_register(TEC); 
62
      itoa(spidata, i, 2);
63
      sprintf(bufferString, "TEC: %s \n", i);
64
      lcd_puts(bufferString);  
65
}

von kevin m. (kevinm)


Lesenswert?

Habe jetzt nochmal probiert und wie es scheint, funktioniert es wenn der 
MCP im LoopBack modus ist ohne Probleme. Kann es sein das es an meinem 
Datenbus liegt?

von Lutz (Gast)


Lesenswert?

kevin mitn schrieb:
> Jetzt zum Problem: Wenn ich mit meiner Sende Funktion eine Nachricht
> verschicken möchte erkenn ich am Oszi erstmal nichts. Im Register
> TXB0CTRL werden TXREQ und TXERR auf 1 gesetzt. Außerdem wird das
> Register TEC bei jedem Sende-versuch erhöht.

kevin mitn schrieb:
> Kann es sein das es an meinem
> Datenbus liegt?

Bingo!

kevin mitn schrieb:
> Aufbau:
> Atmega644 mit 14,7456 MHZ Quarz
> MCP2515 mit 16 MHZ Quarz

Es ist generell unschön bzw. hier durch die räumliche Nähe auch unnötig, 
2 unterschiedliche Taktquellen zu wählen.

von Lutz (Gast)


Lesenswert?

Irgendwie scheinst du auch eine Vermischung der einzelnen Schritte 
(Register laden etc.) gemacht zu haben. Strukturiere lieber jeden 
Schritt gemäß Datenblatt in einer Funktion durch, damit der logische 
Fluß auch verfolgbar bleibt. Wegen der Codegröße kannst du ja inline 
nehmen.

von cskulkw (Gast)


Lesenswert?

kevin mitn schrieb:
> SPI_PORT &= ~(1<<SPI_SS);    // CS Low
>
>     spi_Transfer(MCP_WRITE_TX | 0x00);

Welchen Wert hat MCP_WRITE_TX ?   0x03 ?

Was bzw. warum wird hier verodert?

kevin mitn schrieb:
> // DLC
>
>         spi_Transfer(length);
>
>
>
>         // Daten
>
>         for (uint8_t i=0;i<length;i++) {
>
>             spi_Transfer(p_message->data[i]);
>
>         }

In der for-Schleife wird aber nicht die Registeradresse geladen. Oder?

Die unterschiedlichen Taktfrequenzen sind irrelevant, weil die Systeme 
von eineander nur über SPI gekoppelt sind.

von kevin m. (kevinm)


Lesenswert?

Erstmal Danke für eure Antworten.

Lutz schrieb:
> Es ist generell unschön bzw. hier durch die räumliche Nähe auch unnötig,
> 2 unterschiedliche Taktquellen zu wählen.

Am Anfang hatte ich alles auf 16Mhz. Leider konnte ich aber die höheren 
Übertragungsraten dann bei Visual Basic (MSComm objekt das keine 
"Geraden" baudraten also 250k, 500k ... zulässt) nicht nutzen. Deshalb 
habe ich auf 14,7456 Mhz umgestellt und somit eine kleinerer Fehlerquote 
bei höheren "ungeraden" Baudraten. Hatte aber bis jetzt keine Probleme 
mit der SPI Übetragung.

Lutz schrieb:
>> Kann es sein das es an meinem
>> Datenbus liegt?
>
> Bingo!

Mhh, also der Datenbus zum testen bei mir besteht aus einem CAN Gateway 
aus einen KFZ. Vll. kann es sein das hier wirklich der Fehler liegt. 
Dagegen spricht aber für mich, dass der Empfang von CAN Messages 
Funktioniert.

Lutz schrieb:
> Irgendwie scheinst du auch eine Vermischung der einzelnen Schritte
> (Register laden etc.) gemacht zu haben.

Hab die letzten Tage versucht nochmals alles zu überprüfen. Kann sein 
das du recht hast. Habe mir den Text in Datenblatt jetzt schon zig mal 
durchgelesen und verglichen. Finde aber nichts was ich falsch mache. 
Kannst du mir genauer sagen was du meinst mit vermischen?

cskulkw schrieb:
> Welchen Wert hat MCP_WRITE_TX ?   0x03 ?
>
> Was bzw. warum wird hier verodert?

MCP_WRITE_TX  hat den Wert 0x40.
0x40 | 0x00 = 0x40 = 01000000 = TX Buffer 0, Start at TXB0SIDH (0x31)
0x40 | 0x02 = 0x42 = 01000010 = TX Buffer 1, Start at TXB1SIDH (0x41)
0x40 | 0x04 = 0x44 = 01000100 = TX Buffer 2, Start at TXB2SIDH (0x51)
Damit ich später (sollte es irgendwann funktionieren) alle 3 Buffer 
einfacher nutzen kann. So ist das eigentlich gedacht. Dürfte passen 
oder?

cskulkw schrieb:
> In der for-Schleife wird aber nicht die Registeradresse geladen. Oder?
Wie meinst du das? In der Schleife werden dann die Bytes in das Register 
TXBnDm geladen. Allerdings ist mir aufgefallen, dass immer das erste 
Byte "Verschluckt" wird. Aber bei LoopBack wird alles richtig 
zurückgesenden.

von Lutz (Gast)


Lesenswert?

kevin mitn schrieb:
>>> Kann es sein das es an meinem
>>> Datenbus liegt?
>>
>> Bingo!
>
> Mhh, also der Datenbus zum testen bei mir besteht aus einem CAN Gateway
> aus einen KFZ. Vll. kann es sein das hier wirklich der Fehler liegt.
> Dagegen spricht aber für mich, dass der Empfang von CAN Messages
> Funktioniert.

kevin mitn schrieb:
> Im Register
> TXB0CTRL werden TXREQ und TXERR auf 1 gesetzt.
TXERR: Transmission Error Detected bit
1 = A bus error occurred while the message was being transmitted
0 = No bus error occurred while the message was being transmitted

Da es im Loopback-Modus funktioniert, kann es sowieso nur am Bus liegen.

kevin mitn schrieb:
> Lutz schrieb:
>> Irgendwie scheinst du auch eine Vermischung der einzelnen Schritte
>> (Register laden etc.) gemacht zu haben.
kevin mitn schrieb:
> Kannst du mir genauer sagen was du meinst mit vermischen?

Das ist eine laaaange Geschichte mit vielen Punkten. Da aber nur eine 
Funktion sichtbar ist, läßt sich nur raten bzw. daran orientieren:
Du schiebst gleich als erstes etwas in TXB0, ohne etwas über seinen 
Zustand zu wissen (ob es überhaupt gerade frei ist). Entweder machst du 
das an anderer Stelle (wie einige andere Sachen auch?) oder du machst es 
gar nicht. Und letzteres geht natürlich nicht.
Ich habe schon länger nichts mehr mit dem MCP2515 gemacht und weiß daher 
nicht mehr, ob er sich ohne prüfen oder flag resetten da so einfach ins 
Senderegister schreiben läßt. Wenn diese Prüfung an anderer Stelle 
gemacht wird, könnte das erklären, warum das erste byte "verschluckt" 
wird.

von kevin m. (kevinm)


Angehängte Dateien:

Lesenswert?

So hab mich schon länger nicht mehr gemeldet. Hab viel probiert in der 
Zeit.
Leider besteht das Problem weiterhin.

Ich hab jetzt einen zweiten Can-Controller aufgebaut damit ich 
Nachrichten vom ersten zum zweiten schicken und überprüfen kann.

Das beschreiben der Register für das Versenden der Nachrichten 
funktioniert jetzt soweit. Ich kann meine Nachrichte auf dem Bus richtig 
erkennen.

Wenn ich jetzt eine Nachricht vom 1. CAN zum 2. CAN Gerät sende wird 
beim 2. Gerät ein Error Interrupt ausgelöst. Nur das dumme ist der 
MCP2515 kann mir anscheinend keine genauen Informationen geben warum er 
den Error ausgelöst hat. Alle fehler möglichkeiten werden zusammen 
gewürfelt. Ich kann also anhand der Register nicht unterscheiden ob es 
sich um einen CRC Stuff Bit Form... Fehler handelt.

Im Anhang hab ich das Versenden einer Nachricht von einem zum anderen 
CAN-Gerät aufgezeichet inkl error. Handelt es sich bei diesem Fehler um 
ein ERRROR FRAME? Ich hätte gemeind das ERROR Frame wird nach einer 
NAchricht gesendet aber bei diesem Verlauf ist der Error vor dem EOF 
meiner Nachricht?

Versendet habe ich eine Standard Message, identify 0x7FF, 1 Datenbyte 
0xFF
Kann man erkennen warum der Fehler gesetzt wird?

von kevin m. (kevinm)


Lesenswert?

Hallo nochmal, also ich muss noch einmal nachfragen. Es ist mir wirklich 
wichtig. Vielleicht hat jemand eine Idee von euch wie ich vorgehen kann 
um den fehler doch irgendwie besser einzukreisen? Oder vll. weiß einer 
Literatur über CAN Error Frames?

Vielen Dank

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.