Moin,
ich habe hier ein kleines, selbstgebautes Testboard mit einem
ATMEGA16m1. Ich möchte mit dem vorhandenen CAN-Controller Nachrichten
versenden und auch empfangen. Zum Teil funktioniert das auch schon:
Ich kann Nachrichten in Form von MessageObjects erstellen und versenden.
Die kommen bei meiner Gegenstation auch an (PEAK CAN/USB-Adapter). Der
ATMEGA16m1 empfängt auch Nachrichten meiner Gegenstation und tütet diese
korrekt in die MessageObjects ein. Die Nachrichten kann ich dann auch
aus dem MOb herausholen, allerdings muss ich dazu das RXOK-Bit des
CAN-Controllers anpollen. Das möchte ich nicht machen, ich will den
Controller hiermit nicht blockieren.
Ich habe es bisher jedoch nicht geschafft, beim erfolgreichen Empfang
einer Nachricht einen Interrupt auszulösen. Ich verstehe nicht warum,
denn meiner Meinung nach habe ich alles getan, was dazu notwendig wäre.
Meinem Verständnis nach muss ich die Interrupts in den Registern CANIE2
und CANIE1 für die MOb's aktivieren und zusätzlich noch die
CAN-Interrupts generell aktivieren. Hierzu habe ich im CANGIE das ENIT
und ENRX (für den Empfangsinterrupt) gesetzt.
Es passiert leider absolut gar nichts. Für den Anfang will ich mit dem
Interrupt einfach nur mal einen globalen Boolean toggeln, mit dem ich
dann eine simple LED einschalte. Es tut sich aber nichts. Über Polling
funktioniert das Ganze, daher vermute ich mal, dass ich meinen Interrupt
nicht richtig eingestellt habe (der Polling-Code ist auskommentiert).
Vielleicht hat ja jemand eine gute Idee und kann mir helfen.
Gruß
Nils
1 | #define F_CPU 16000000UL
|
2 |
|
3 | #include <avr/io.h>
|
4 | #include <avr/interrupt.h>
|
5 | #include <stdbool.h>
|
6 |
|
7 | #include <util/delay.h>
|
8 |
|
9 | bool led = false;
|
10 |
|
11 | void can_init(void)
|
12 | {
|
13 | uint8_t i,j;
|
14 |
|
15 | CANGCON = (1<<SWRES); // off and reset
|
16 |
|
17 | // Alle CAN-MOB's zurücksetzen
|
18 | for (i=0; i<6; i++)
|
19 | {
|
20 | CANPAGE = (i<<4); // MOb auswählen
|
21 | CANCDMOB = 0x00; // MOb deaktivieren
|
22 | CANSTMOB = 0x00; // Status zurücksetzen
|
23 | CANIDT1 = 0x00; // ID zurücksetzen
|
24 | CANIDT2 = 0x00;
|
25 | CANIDT3 = 0x00;
|
26 | CANIDT4 = 0x00;
|
27 | CANIDM1 = 0x00; // MASK zurücksetzen
|
28 | CANIDM2 = 0x00;
|
29 | CANIDM3 = 0x00;
|
30 | CANIDM4 = 0x00;
|
31 | for (j=0; j<8; j++)
|
32 | {
|
33 | CANMSG = 0x00; // Daten zurücksetzen
|
34 | } // for(..
|
35 | } // for(..
|
36 |
|
37 | // Einstellungen für 500 kBit/s mit 16 MHz Quarz
|
38 | /*
|
39 | CANBT1 = (1<<BRP0);
|
40 | CANBT2 = (1<<PRS2) | (1<<PRS1);
|
41 | CANBT3 = (1<<PHS21) | (1<<PHS20) | (1<<PHS11) | (1<<PHS10) | (1<<SMP);
|
42 | */
|
43 | // Einstellungen für 125 kBit/s mit 16 MHz Quarz
|
44 | CANBT1 = 0x1E;
|
45 | CANBT2 = 0x04;
|
46 | CANBT3 = 0x13;
|
47 |
|
48 | CANEN2 = 0x00;
|
49 | CANEN2 = 0x3F; // Alle MObs aktivieren
|
50 | CANIE1 = 0x3F; // Alle MOb Interrupts aktivieren
|
51 |
|
52 | CANGIE = (1<<ENIT) | (1<<ENRX); // Interrupts aktivieren
|
53 |
|
54 | CANPAGE = (1<<MOBNB0); // MOb0 auswählen
|
55 |
|
56 |
|
57 | CANGCON = (1<<ENASTB); // CAN-Controller aktivieren
|
58 | CANSTMOB = 0x00; // Statusregister zurücksetzen
|
59 | CANCDMOB = (1<<CONMOB1) | (8<<DLC0); // CONMOB1 und DLC0 setzen, rest auf 0
|
60 | }
|
61 |
|
62 | int main(void)
|
63 | {
|
64 | cli();
|
65 |
|
66 | can_init();
|
67 |
|
68 | DDRB |= (1<<DDB4);
|
69 |
|
70 | sei();
|
71 |
|
72 | while(1)
|
73 | {
|
74 | // Polling Methode: RXOK anpollen
|
75 |
|
76 | /*
|
77 | if (CANSTMOB & (1<<RXOK))
|
78 | {
|
79 | CANSTMOB &= ~(1<<RXOK);
|
80 | CANCDMOB = (1<<CONMOB1) | (1<<RPLV);
|
81 | if (led)led = false;
|
82 | else led = true;
|
83 | } */
|
84 |
|
85 |
|
86 | if (led) PORTB |= (1<<PORTB4);
|
87 | else PORTB &= ~(1<<PORTB4);
|
88 |
|
89 | }
|
90 | }
|
91 |
|
92 | // ISR für CAN
|
93 | ISR(CAN_INT_vect)
|
94 | {
|
95 |
|
96 | if (led) led = false; // LED-Bit Toggle
|
97 | else led = true;
|
98 | CANSTMOB &= ~(1<<RXOK); // RXOK zurücksetzen
|
99 | }
|