Hi zusammen,
ich bin so langsam mit meinem Latein am Ende, wobei mein Problem
folgendes ist:
Ich habe 2 Boards mit je einem AT90CAN128, wovon einer Sender, der
andere Empfänger ist. Anfangs möchte ich über CAN ein einfaches
Datenbyte senden, welches empfangen und angezeigt wird. (Später, wenn
alles funktioniert, schicke ich mehrere Bytes). Das Ganze geschieht bei
100 kbit/s. Mein benutzter C-Compiler ist CodeVision. Für Sender und
Empfänger arbeite ich je mit einem Message Object (MOb), und zwar MOb2.
Die Mask-Register für den Empfänger sind so geschaltet, dass sie alle
Identifier durchlassen.
Auf der Sendeseite überprüfe ich in 1. Linie, ob das TXOK-flag gesetzt
wird. Da dies jedoch nicht passiert ist, habe ich auch auf andere Flags
getestet und sehe nun, dass auf der Sendeseite BERR (bit errors)
auftreten und letztendlich ein BOFF-flag (bus off) gesetzt wird.
Letzteres macht ja auch Sinn, da CAN immer wieder erneut versucht zu
senden, bis der Fehlercounter so hoch ist, dass der Teilnehmer
abschaltet wird.
Auf beiden Seiten habe ich einen nahezu identischen Code. Natürlich
überprüfe ich für den Sender das TXOK-flag und für den Empfänger das
RXOK-flag. Entsprechende Interrupt-enable-Bits habe ich jeweils im
CANGIE-Register gesetzt.
Das Sendeprogramm geht in die Interrupt-Service-Routine (schließlich
werden die Flags BERR und BOFF gesetzt). Das Empfangsprogramm erreicht
seine ISR jedoch nie (was ich komisch finde, denn die Programme sind
gleich aufgebaut, zumindest müsste irgendein Fehler-Interrupt ausgelöst
werden meiner Meinung nach...).
Ich habe meinen Empfangscode hier im Anschluss mal gepostet. Der
Sendecode unterscheidet sich nur durch die darunter gepostete
can_tx()-Funktion anstelle von can_rx(). (und natürlich durch die
entsprechenden Registereinstellungen, die nun auf Tx und nicht Rx
gesetzt sind.)
Sieht von euch jemand einen Bock in meinem Programm oder hat einen Tipp
für mich? Üebr jede Hilfe bin ich sehr dankbar...
Viele Grüße, Xine
1 |
|
2 | interrupt [CAN_IT] void can_isr(void) // CANIT interrupt vector code
|
3 | {
|
4 | unsigned char save_canpage;
|
5 | save_canpage = CANPAGE;
|
6 |
|
7 | CANPAGE = (1 << MOBNB1); // Select MOb2.
|
8 |
|
9 | if (CANSTMOB & (1 << RXOK))
|
10 | {
|
11 | can_data = CANMSG;
|
12 | lcd_int2bin(can_data); // Show received data byte
|
13 | CANSTMOB &= (~(1 << RXOK));
|
14 | }
|
15 | if (CANGSTA & (1 << BOFF)) // Bus off error flag
|
16 | {
|
17 | lcd_putsf("Bus off");
|
18 | lcd_int2bin(CANREC); // Show CANTEC register
|
19 | CANGSTA &= (~(1 << BOFF));
|
20 | }
|
21 | if (CANSTMOB & (1 << DLCW)) // DLC warning flag
|
22 | {
|
23 | lcd_putsf("DLCW");
|
24 | CANSTMOB &= (~(1 << DLCW));
|
25 | delay_ms(200);
|
26 | }
|
27 | if (CANSTMOB & (1 << CERR)) // CRC error flag
|
28 | {
|
29 | lcd_putsf("CERR");
|
30 | CANSTMOB &= (~(1 << CERR));
|
31 | delay_ms(200);
|
32 | }
|
33 | if (CANSTMOB & (1 << SERR)) // Stuff error flag
|
34 | {
|
35 | lcd_putsf("SERR");
|
36 | CANSTMOB &= (~(1 << SERR));
|
37 | }
|
38 | if (CANSTMOB & (1 << FERR)) // Form error flag
|
39 | {
|
40 | lcd_putsf("FERR");
|
41 | CANSTMOB &= (~(1 << FERR));
|
42 | }
|
43 | if (CANSTMOB & (1 << AERR))
|
44 | {
|
45 | lcd_putsf("CAN MOb ACK error");
|
46 | CANSTMOB &= (~(1 << AERR));
|
47 | }
|
48 | if (CANSTMOB & (1 << AERR)) // MOb ACK error flag
|
49 | {
|
50 | lcd_putsf("CAN MOb ACK error");
|
51 | CANSTMOB &= (~(1 << AERR));
|
52 | }
|
53 | if (CANGIT & (0 << AERG))
|
54 | {
|
55 | lcd_putsf("CAN general ACK error");
|
56 | CANGIT &= (~(0 << AERG));
|
57 | }
|
58 | if (CANGIT & (1 << CANIT))
|
59 | {
|
60 | lcd_putsf("Some interrupt happened");
|
61 | }
|
62 | CANPAGE = save_canpage;
|
63 | }
|
64 |
|
65 |
|
66 | void can_init(void) // CAN Controller initialization
|
67 | {
|
68 | int i;
|
69 | int j;
|
70 |
|
71 | #asm("cli")
|
72 |
|
73 | // CAN general initialization:
|
74 |
|
75 | CANTCON = 0x00; // CAN Timer Clock Period: 0,500 us
|
76 |
|
77 | CANBT1 = 0x12; // CAN baudrate: 100 kbit/s
|
78 | CANBT2 = 0x0C;
|
79 | CANBT3 = 0x36;
|
80 |
|
81 | CANGIE = (1<<ENRX) | (1<<ENIT) | (1<<ENERR); // Enable interrupt sources
|
82 |
|
83 | CANIE2 = (1 << IEMOB2); // MOb2 interrupts.
|
84 | CANIE1 = 0x00;
|
85 |
|
86 |
|
87 | // MOb initialization: Clear all MObs.
|
88 |
|
89 | for (i=0; i<15; i++)
|
90 | {
|
91 | CANPAGE = (i << 4); // Select MOb
|
92 |
|
93 | CANSTMOB = 0x00;
|
94 | CANCDMOB = 0x00;
|
95 |
|
96 | CANIDT4 = 0x00; // Delete Id.
|
97 | CANIDT3 = 0x00;
|
98 | CANIDT2 = 0x00;
|
99 | CANIDT1 = 0x00;
|
100 |
|
101 | CANIDM4 = 0x00; // Delete mask.
|
102 | CANIDM3 = 0x00;
|
103 | CANIDM2 = 0x00;
|
104 | CANIDM1 = 0x00;
|
105 |
|
106 | for (j=0; j<8; j++) // Delete data
|
107 | {
|
108 | CANMSG = 0x00;
|
109 | }
|
110 | }
|
111 |
|
112 | // Enable CAN module:
|
113 |
|
114 | CANGCON = (1 << ENASTB); // Enable CAN. <=> CANGCON=0x02;
|
115 | }
|
116 |
|
117 |
|
118 |
|
119 | void can_rx(void)
|
120 | {
|
121 | CANPAGE = (1 << MOBNB1) | (1 << AINC); // 2. Select MOb2.
|
122 | CANCDMOB = (1 << CONMOB1) | (1 << DLC0); // Enable rx, DLC = 1 (1 byte)
|
123 | }
|
124 |
|
125 |
|
126 |
|
127 | void main(void)
|
128 | {
|
129 |
|
130 | init();
|
131 | can_init();
|
132 | #asm("sei")
|
133 | can_rx();
|
134 |
|
135 | while (1)
|
136 | {
|
137 | };
|
138 | }
|