Forum: Mikrocontroller und Digitale Elektronik PIC18Fxxx8 CAN Protokoll Frage


von MAX (Gast)


Lesenswert?

Hallo!

Ich bin gerade dabei das ECAN Modul mit einem PIC18F4680 zum laufen zu
bringen um eine Kommunikation zwischen zwei PICs herzustellen. ich habe
eine Routine geschrieben um eine Nachricht zu senden. Der Empfang wird
Interruptgesteuert abgewickelt. Im Loopback mode funktioniert alles
einwandfrei. Die gesendete Nachricht wird richtig empfangen und eine
RTR (Request to Send) anfrage wird auch mit einem Antwortframe
beantwortet.
jedoch sobald ich 2 PICS zusammenhänge und in den Normal Mode gehe,
wird beim Empfänge immer die gleiche Nachricht empfangen, obwohl die
Nachricht nur einmal beim Sender gesendet wurde. Muss der Empfang vom
Empfänger irgendwie durch ein Frame bestätigt werden? Außerdem wird
eine gesehdete RTR nicht beantortet. - ich kenn mich, was die frames
und die genaue BOSCH norm anbelangt leider nicht 100%ig aus. Vielleicht
könnt ihr mir weiter helfen?


Vielen dank schon mal für Antworten!
gruß,
MAX

von MAX (Gast)


Lesenswert?

achja, was ich noch vergessen habe: zwischen den 2 PICs habe ich jeweils
 2 MCP2551 CAN Tranceiver und auf beiden seiten einen 120Ohm
abschlusswiderstand. - kann ich die 2 PICs auf direkt zusammenhängen
TXCAN1->RXCAN2 und RXCAN1<-TXCAN2?

gruß,
MAX

von PICcer (Gast)


Lesenswert?

>kann ich die 2 PICs auf direkt zusammenhängen
>TXCAN1->RXCAN2 und RXCAN1<-TXCAN2?

das dürfte nicht funktionieren

>jedoch sobald ich 2 PICS zusammenhänge und in den Normal Mode gehe,
>wird beim Empfänge immer die gleiche Nachricht empfangen, obwohl die
>Nachricht nur einmal beim Sender gesendet wurde. Muss der Empfang vom
>Empfänger irgendwie durch ein Frame bestätigt werden?

Genau das ist die Ursache für das ständige neu Senden. Der Empfänger
sendet dir selbe Message mit geseztem ACK Bit zurück. Dann weiß der
Sender, dass die Message korrekt empfangen wurde. Falls dies nicht der
Fall ist, wird die Message eben immer wieder gesendet.

von MAX (Gast)


Lesenswert?

Hallo PICer,

diese überprüfung mit dem ACK bit macht das die CAN engine oder muss
ich das softwaremäßig machen? kannst du mir vielleicht kurz den
gesamten ablauf einer erfolgreichen übertragung einer Nachricht
erklären. d.h. wer sendet wem was?

Wäre nett, danke
MAX

von Stefan K. (_sk_)


Lesenswert?

>Genau das ist die Ursache für das ständige neu Senden. Der Empfänger
>sendet dir selbe Message mit geseztem ACK Bit zurück. Dann weiß der

Das ist etwas undeutlich.
Der Empfänger setzt am Schluss einer msg ds ACK-Bit. Er erzeugt also
nicht nochmal die komplette msg (was ja die Datenrate halbieren würde).

An EINER msg sind sowohl der Sender als auch der Empfänger beteiligt:
der Sender sendet den "Body" und der Empfänger das ACK.

Das ACK wird vom Empfänger selbstständig erzeugt. Ausnahme könnte
höchstens ein Listen-Mode sein, in dem der Empfänger zwar hören, aber
nicht aktiv am Busgeschehen teilnehmen darf.

Wenn Dein Empfänger korrekt empfängt, es aber trotzdem zu mehrfachem
Senden kommt, dann kann ich mir das höchstens durch o.g.Listen-Mode
oder durch einen Hardware-Defekt (TX-Leitung des Empfängers defekt?)
erklären.

Gruß, Stefan

von MAX (Gast)


Lesenswert?

hallo stefan,
danke für die antwort!
jetzt ist mir auch klar, warum das bei mir auch so war, als ich den
listen mode ausprobiert habe. ich werd mal die 2 pics ersetzten, um
auszuschließen, dass eine TX-Leitung defekt ist.

MAX

von MAX (Gast)


Lesenswert?

also hier, wen's interessiert die main und interrupt routine;

...

can_msg *nachricht, *tx_temp, *rx_temp;

void Interrupt_CAN_RXB0(void)
{
  if(can_get_rx_buffer(rx_temp, RXB0)){
    if(rx_temp->DLC&0x40){  //if RTR bit set, transmit RTR answer
      tx_temp->SID=rx_temp->SID;
      tx_temp->EID=rx_temp->EID;
      tx_temp->DLC=0x08;
      tx_temp->DATA[0]='R';
      tx_temp->DATA[1]='T';
      tx_temp->DATA[2]='R';
      tx_temp->DATA[3]=' ';
      tx_temp->DATA[4]='A';
      tx_temp->DATA[5]='N';
      tx_temp->DATA[6]='S';
      tx_temp->DATA[7]='W';

      can_load_tx_buffer(nachricht,TXB1);
      can_tx_buffer(TXB1,2);  //TXn senden
    }
    else
    {
      show_msg(rx_temp);  //message ausgeben
    }
  }
}

void main(void)
{
  unsigned char buffer[5];
  unsigned int i, temp;

  i2c_init((CPU_FREQ/I2C_CLK-4)/4);
  lcd_init(LCD_DISP_ON);
  usart_init((CPU_FREQ/USART_BAUDRATE-16)/16);
  can_init((CPU_FREQ/CAN_BAUDRATE)/2/8-1, MODE_NORMAL);

  /*Global Interrupt*/
  RCONbits.IPEN=1;    //enable priority
   INTCONbits.GIEH=1;    //enable all high priority interrupts
  INTCONbits.GIEL=1;    //enable all low priority interrupts

  /*CAN Interrupts*/
  INTCONbits.PEIE=1;  //Peripheral Interrupt Enable
  PIE3bits.RXB0IE=1;  //enable RXB0 Interrupt enable
  IPR3bits.RXB0IP=1;  //enable high priority for RXB0
  PIE3bits.RXB1IE=0;  //enable RXB1 Interrupt enable
  IPR3bits.RXB1IP=0;  //enable high priority for RXB1
  PIE3bits.TXB0IE=0;  //enable TXB0 Interrupt enable
  IPR3bits.TXB0IP=0;  //enable high priority for TXB0

  RXB0CON=0b00100000;  //Config RXB0;
  RXB1CON=0b00100000;  //Config RXB1;

  for(;;){
    nachricht->SID=5;
    nachricht->EID=0;
    nachricht->DLC=0x05;
    nachricht->DATA[0]='M';
    nachricht->DATA[1]='S';
    nachricht->DATA[2]='G';
    nachricht->DATA[3]=' ';
    nachricht->DATA[4]='1';

    can_load_tx_buffer(nachricht,TXB0);
    can_tx_buffer(TXB0,2);  //TXn senden

    delay_ms(1000);

    nachricht->SID=99;
    nachricht->EID=0;
    nachricht->DLC=0x07|0x40;
    nachricht->DATA[0]='R';
    nachricht->DATA[1]='T';
    nachricht->DATA[2]='R';
    nachricht->DATA[3]=' ';
    nachricht->DATA[4]='R';
    nachricht->DATA[5]='E';
    nachricht->DATA[6]='Q';

    can_load_tx_buffer(nachricht,TXB0);
    can_tx_buffer(TXB0,1);  //TXn senden

    delay_ms(2000);
  }
}

...

von MAX (Gast)


Lesenswert?

hab grad gesehen, hab vorher noch einer variable einen sinnvollen namen
gegeben deshalb muss es in der ISR statt "
can_load_tx_buffer(nachricht,TXB1);"
"can_load_tx_buffer(tx_temp,TXB1);" heißen!

von Profi (Gast)


Lesenswert?

>kann ich die 2 PICs auf direkt zusammenhängen
>TXCAN1->RXCAN2 und RXCAN1<-TXCAN2?

So nicht, aber anders: mit wired or, denn alle Rx müssen alle Tx hören,
und dominant (low) soll recessiv (high) übertönen:
          +5V
         PullUp
           |
Rx1  ------*------ Rx2
           |
Tx1  --|<|-*-|>|-- Tx2     (sollen 2 schnelle Dioden sein)

geht auch mit mehr als 2 Teilnehmern, wenn die Leitungen relativ kurz
sind.

von MAX (Gast)


Lesenswert?

Hallo,

ich hab jetzt mal beide PICs ausgetauscht und jetzt funktionierts
einwadfrei, es muss also einer der beiden beim probeaufbau was
abgekriegt haben :) - Danke für den hinweis!

hab jetzt nur mehr ein paar kleine fragen und zwar:

1) im TXB0CON (Transmit buffer 0 control) gibts ein bit TXLARB
(Transmission lost arbitration), was bedeutet lost arbitration. ich
fermute es heißt, dass er das adressierungsfeld (Identifier)
"verpasst" hat?

2) im TXB0CON, das bit TXERR wird das gesetzt, sobald der Sender keine
Ack vom empfänger erhalten hat und probiert es somit noch einmal und
die anzahl der versuche wird im TXERRCNT mitgezählt, seh ich das
richtig so? wie sollte man so ein Transmition error am besten in der
software behandeln, d.h. wie eird das in der praxis gemacht?

so das wärs eigentlich. danke denen die mir hier immer antworten!

gruß,
MAX

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.