mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT90CAN64 Fehler beim senden


Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich versuche derzeit einen AT90CAN64 zur programmieren.
Das Programm liest einen ADC über die SPI aus und speichert die Daten in 
einen Buffer.
Wenn ein Receive Interrupt vom CAN bus ausgelöst wird, soll er diesen 
Buffer über den CAN bus an den rechner senden.
Die CAN Nachrichten sind dabei 4 Byte lang. Erstes Byte steht für die 
Kanalnummer, Zweites und drittes Byte für die ADC Daten und das vierte 
Byte ist eine 8-bit LRC.

Das Problem dabei: Bei der letzten Nachricht ist immer das 1te Byte 0 
ist, obwohl im CANMSG register der richtige Wert steht. Es ist auch egal 
ob ich nur 1 Nachricht schicke, oder mittels for-Schleife alle 64 
Nachrichten hintereinander. Jedesmal ist bei der letzten Nachricht das 1 
Byte eine 0.

Hier Auszüge aus meinem Code:
volatile uint16_t id_tag = 0x068F;
volatile uint16_t adc_data_buffer[64];

ISR(CANIT_vect)
{
  cli();

  uint8_t rx_data[8];
  uint16_t meanValue = 0;
  uint8_t channel;
  uint8_t rx_dlc = CANCDMOB & ((1<<DLC3)|(1<<DLC2)|(1<<DLC1)|(1<<DLC0));

  CANPAGE = CANHPMOB & 0xF0;
  for (uint8_t data_index = 0; data_index < rx_dlc; data_index++)
    *(rx_data + data_index) = CANMSG;

  can_clear_mob();

  switch(rx_data[0]){
  case (1):
    for (int i=0; i<64; i++)
      txCan(adc_data_buffer[i], i);
    break;

  case (2):
    if (rx_data[1] >= 64){ // --- invalid channel number
      channel = 0xE2;
      meanValue = 0;
    }
    else {
      channel = rx_data[1];
      meanValue = adc_data_buffer[channel];
    }
    txCan(meanValue, channel);
    break;

  } // switch (rx_data[0])    

  rxCan();
  sei();
}

void rxCan(void)
{
  can_msg rx_data_msg;
  
  rx_data_msg.status = 0;
  rx_data_msg.ext = 0;              // CAN 2.0A
  rx_data_msg.id = id_tag;          // CAN Identifier
  rx_data_msg.dlc = 2;              // Data Length
  rx_data_msg.cmd = RX_DATA_MASKED; // Receive Data frame
  
  // --- use first free MOb
  // --- if no MOb is available wait for one
  rx_data_msg.handle = 0x00;

  can_config_mob(&rx_data_msg);
}

void txCan(uint16_t tx_data, uint8_t channel)
{
  can_msg tx_data_msg;
  uint8_t tx_data_buffer[4];
  uint8_t chk = 0;

  tx_data_buffer[0] = channel;
  tx_data_buffer[1] = (uint8_t)(tx_data >> 8);
  tx_data_buffer[2] = (uint8_t)(tx_data);

  // --- calculate 8-bit LRC
  for (int i=0; i<3; i++)
    chk = chk^tx_data_buffer[i];
  tx_data_buffer[3] = chk;

  tx_data_msg.status = 0;
  tx_data_msg.pt_data = tx_data_buffer;
  tx_data_msg.ext = 0;        // CAN 2.0A
  tx_data_msg.id = id_tag;    // CAN Identifier
  tx_data_msg.dlc = 4;        // Data Length
  tx_data_msg.cmd = TX_DATA;  // Transmit

  // --- use first free MOb
  // --- if no MOb is available wait for one
  tx_data_msg.handle = can_get_free_mob();
  while(tx_data_msg.handle == NO_MOB)
    tx_data_msg.handle = can_get_free_mob_ext();

  can_config_mob(&tx_data_msg);
}

void can_clear_mob(void)
{
  // --- Set all MOb registers to 0
  CANIDM4 = 0x00; CANIDM3 = 0x00; CANIDM2 = 0x00; CANIDM1 = 0x00;
  CANIDT4 = 0x00; CANIDT3 = 0x00; CANIDT2 = 0x00; CANIDT1 = 0x00;
  CANSTMOB=0x00;
  CANCDMOB = 0;
  for (int num_data = 0; num_data < 8; num_data++)
    CANMSG = 0;
}

void can_config_mob (can_msg* mob_conf)
{
  CANPAGE = (mob_conf->handle << 4);
  can_clear_mob();   // to be sure MOb is cleared

  switch(mob_conf->cmd){

  case TX_DATA:    
    can_set_id(mob_conf->ext, mob_conf->id);
    for (int cpt=0; cpt<mob_conf->dlc; cpt++)
      CANMSG = *(mob_conf->pt_data + cpt);    
    CANCDMOB |= (mob_conf->dlc);
    CANCDMOB |= (1  << CONMOB0); }    
    break;

  case RX_DATA_MASKED:
    can_set_id(mob_conf->ext, mob_conf->id);
    CANIDM4=0xFD; CANIDM3=0xFF; CANIDM2=0xFF; CANIDM1=0xFF;
    CANIDT4  &= ~(1<<RTRTAG)
    CANCDMOB |= (mob_conf->dlc);
    CANCDMOB |= (2  << CONMOB0); }
    break;
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.