Atmega64M1 CAN TX Interrupt

#6923724
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.
#6929328
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.
Gast #6939632
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."
#6940171
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren