Forum: Mikrocontroller und Digitale Elektronik Atmega64M1 CAN TX Interrupt


von Christian S. (vivus)


Lesenswert?

Hallo,

ich nutze den Atmega64M1 um Nachrichten auf den Bus zu senden/empfangen. 
Dies funktioniert auch soweit, allerdings springt nach dem Senden einer 
Nachricht die ISR nicht an, obwohl ich das entsprechende Bit gesetzt 
habe (ENTX in CANGIE). Senden kann ich aber trotzdem mehrere Nachrichten 
hintereinander.

Anders als bei erfolgreichem Empfang einer Nachricht. Hier springt die 
IRS an. Mehrere Nachrichten hintereinander empfangen ist kein Problem.

Kann jemand sagen, was ich falsch mache?
Nochmal was ich will: Nachricht senden und dann soll die IRS 
CAN_INT_vect starten ausgelöst durch TXOK Bit.

Eigentlich dachte ich, ich könne mit folgendem Code prüfen, ob 
erfolgreich gesendet wurde und entsprechend die Register zurücksetzen:
1
ISR (CAN_INT_vect)
2
{
3
  if(CANSTMOB & (1 << TXOK))
4
  {
5
    CANCDMOB = 0x00;  // Disable Transmission
6
    CANSTMOB = 0x00;  // Clear TXOK flag
7
    // CANSTMOB &= ~(1 << TXOK); // clear interrupt flag
8
  }
9
}

Hier zum einen meine Initialisierung:
1
void can_init(void){
2
3
  CANGCON = ( 1 << SWRES );      // Software reset
4
  CANTCON = 0x00;            // CAN timing prescaler set to 0;
5
6
  // Aus EEPROM
7
  CANBT1 = geraetedaten_info[5];            // 500kb/s
8
  CANBT2 = geraetedaten_info[6];            // http://www.bittiming.can-wiki.info/
9
  CANBT3 = geraetedaten_info[7];            //
10
11
  for ( anzahl = 0; anzahl < 3; anzahl++ )
12
  {
13
    // TX
14
    // Mob 0 bis 2 werden als Tx genutzt
15
    
16
    CANPAGE = ( anzahl << MOBNB0 );       // Selects Message Object 0-2
17
    CANCDMOB = 0x00;                 // Disable mob
18
    CANSTMOB = 0x00;               // Clear mob status register;
19
20
    // TAG
21
    CANIDT4 = 0x00;
22
    CANIDT3 = 0x00;
23
    CANIDT2 = 0x00;
24
    CANIDT1 = 0b0000000;
25
    
26
    // MASK
27
    CANIDM4 = 0x00;
28
    CANIDM3 = 0x00;
29
    CANIDM2 = 0x00;
30
    CANIDM1 = 0b00000000;
31
  }
32
  
33
  
34
  for ( anzahl = 3; anzahl < 6; anzahl++ )
35
  {
36
    // RX
37
    // Mob 3 bis 5 werden als RX genutzt
38
    CANPAGE = ( anzahl << MOBNB0 );       // Selects Message Object 3-5
39
    CANCDMOB = 0x00;                 // Disable mob
40
    CANSTMOB = 0x00;               // Clear mob status register;
41
  
42
    // TAG
43
    CANIDT4 = 0x00;
44
    CANIDT3 = 0x00;
45
    CANIDT2 = 0x00;
46
    CANIDT1 = 0b00010000;
47
48
    // MASK
49
    CANIDM4 = 0x01; // IDEMSK = 1
50
    CANIDM3 = 0x00;
51
    CANIDM2 = 0x00;
52
    CANIDM1 = 0b11110000;
53
54
    CANCDMOB = ( 1 << CONMOB1) | ( 1 << IDE ) | ( 8 << DLC0);  // Enable Reception 29 bit IDE DLC8
55
  }
56
  
57
  CANGIE = ( 1 << ENIT ) | ( 1 << ENRX ) | ( 1 << ENTX );                      // ( 1 << ENIT ) | ( 1 << ENBOFF) | ( 1 << ENRX ) | ( 1 << ENTX ) | (1 << ENERR) | (1 << ENBX) | (1 << ENERG);
58
  CANIE1 = 0xFF;
59
  CANIE2 = (1<<IEMOB5) | (1<<IEMOB4) | (1<<IEMOB3) | (1<<IEMOB2) | (1<<IEMOB1) | (1<<IEMOB0);     // Enable interrupts on all MObs
60
61
  CANGIT = 0xff;                                          // RESET aller Interrupt Flags
62
  CAN_ENABLE;                                            // Enable mode. CAN channel enters in enable mode once 11 recessive bits have been read
63
}



Zum anderen die Funktion, mit der ich sende:
1
void can_tx (uint8_t dlc, uint8_t bl_befehl, uint8_t * tx_data)
2
{
3
4
  for (select_free_mob = 0; select_free_mob < 3; select_free_mob++)
5
  {
6
    if (!(CANEN2 & (1 << select_free_mob)))
7
    {
8
      break;
9
    }
10
  }
11
12
  CANPAGE = select_free_mob << MOBNB0;    // Select MOb0 for transmission
13
  CANSTMOB = 0x00;                // Clear mob status register
14
15
  // CAN ID setzen:
16
  CANIDT1 = SEKTION_BL << 4 | (geraete_id >> 5);
17
  CANIDT2 = (geraete_id << 3) | bl_befehl;
18
  CANIDT3 = (BL_VERSION << 3) | (geraetedaten_info[3] >> 5);
19
  CANIDT4 = geraetedaten_info[3] << 3;
20
21
  // Nachrichten
22
  for ( uint8_t i = 0; i < dlc; ++i )
23
  {
24
    CANMSG = tx_data[i];
25
  }
26
27
  CANCDMOB = ( 1 << CONMOB0 ) | ( 1 << IDE ) | ( dlc << DLC0 );   // Enable transmission, data length,  (CAN Standard rev 2.0B(29 bit identifiers))
28
}

Freue mich sehr über Hinweise. Vielen Dank.

von H.Joachim S. (crazyhorse)


Lesenswert?

Gibts denn irgendwo ein "sei"?

von Christian S. (vivus)


Lesenswert?

H.Joachim S. schrieb:
> Gibts denn irgendwo ein "sei"?

Hallo, guter Punkt, aber ja, eine sei gibt es. Wie gesagt, eine 
eingehende Nachricht springt in die ISR, sprich Interrupts sind schon 
aktiv.

von Christian S. (vivus)


Lesenswert?

Frohes neues Jahr!

Fällt einem von euch noch etwas auf?

Das TXOK Bit wird auf jeden Fall gesetzt. Wenn ich nach dem Senden einer 
Nachricht das TXOK Bit polle:
1
while ( ! ( CANSTMOB & ( 1 << TXOK ) ) );

Läuft er durch und ich kann heiter die nächste Nachricht senden.

Würde mich über jeden Hilfreichen Tipp sehr freuen.

von Christian S. (vivus)


Lesenswert?

Hat keiner einen Tipp für mich? Gar nicht?

von Simon (Gast)


Lesenswert?

1
    CANSTMOB = 0x00;  // Clear TXOK flag
2
    // CANSTMOB &= ~(1 << TXOK); // clear interrupt flag
warum hast du die zweite Zeile auskommentiert?
Im Datenblatt steht:

"Bit 6 – TXOK: Transmit OK
This flag can generate an interrupt. It must be cleared using a 
read-modify-write software routine on the
whole CANSTMOB register."

von Christian S. (vivus)


Lesenswert?

Simon schrieb:
> CANSTMOB = 0x00;  // Clear TXOK flag
>     // CANSTMOB &= ~(1 << TXOK); // clear interrupt flag
> warum hast du die zweite Zeile auskommentiert?
> Im Datenblatt steht:
>
> "Bit 6 – TXOK: Transmit OK
> This flag can generate an interrupt. It must be cleared using a
> read-modify-write software routine on the
> whole CANSTMOB register."

Guter Einwand, allerdings komme ich soweit ja garnicht. Sprich ein 
Interrupt wird nicht ausgelöst.

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.