Hallo Leute! Seit Wochen programmiere ich an der CAN-Schnittstelle des AT90CAN128 rum, jedoch lässt sich keine Nachricht empfangen. Nachrichten möchte ich keine senden. Meine Vermutung ist, dass etwas mit der Interupt-Vektortabelle nicht in Ordnung ist. Kann mir vielleicht jemand weiterhelfen? Im Anhang findet ihr meine main.c-Datei mit allen Initialisierungen... Gruß Thomas
Dann schalte ich mich mal auch noch mit ein: Das Senden mit dem AT90CAN128 klappt bei mir ohne Probleme. Empfangen lässt sich bis jetzt nichts (jeweils Polling). Der einzige Interrupt, den ich zum Auslösen bekomme ist der des CAN-Timers, dieser jedoch zuverlässig. Sowohl Sende- als auch Empfangsinterrupt arbeiten nicht.
OK, CANIDM4 = 0;//|= (1<<IDEMSK); und CANGIE = 0xA0; und in der ISR CANCDMOB = (1<<CONMOB1); Dann empfängt er schonmal Nachrichten via Interrupt :)
Habe es ausprobiert, jedoch funktioniert jetzt der Controller überhaupt nicht mehr (SRAM-Error, auch mit meiner ursprünglichen main.c Datei) @flyingwolf: Wie soll es ohne Interrupts funktionieren? Ich habe doch nur 2 Möglichkeiten: entweder SIGNAL(...) oder INTERRUPT(...) -> mit beiden habe ich keine nennenswerten Erfolge erzielt.
Den Fehler kann ich logischerweise nicht nachvollziehen. Ohne Interrupts heißt das Ganze Polling. Du kontrollierst einfach TXOK bzw. RXOK manuell und leitest bei gesetzten Flags die entsprechenden Aktionen ein. Meine Senderoutine demonstriert das ganze eigentlich. Von INTERRUPT würde ich dir generell abraten.
@Alex Dies CANTIML = 0; CANTIMH = 0; CANTTCL = 0; CANTTCH = 0; bringt nichts, da CANTIM, CANTTC und ander CAN-Timer nur Lesezugriff zulassen
@Alexander Das weiß ich, es ist auch in der Endversion (vgl. Codesammlung) nicht mehr drinnen. Stammt noch aus dem Testbetrieb.
@Thomas27 Ganz einfach. Du fragst die Box sporadisch ab. Du musst die Mailbox nach jedem empfang explizit freigeben. Wenn Du Angst hast, dass Du dadurch eine Nachricht verpassen könntest, kannst Du 2 Boxen mit den gleichen Parametern freigeben. Dann kommt die erste Nachricht in der ersten Box an und wenn die zeite Nachricht kommt, bevor die erste Box wieder freigegeben ist, kommt die Nachricht in der zweiten box an. ... Keine Verluste und keine Interrupts.
versuchs mal hiermit, nicht schön, aber selten ...
1 | #include <avr/io.h> |
2 | |
3 | #include <avr/pgmspace.h> |
4 | |
5 | #include <stdlib.h> |
6 | |
7 | |
8 | #include <inttypes.h> |
9 | #include <stdio.h> |
10 | |
11 | #include "can.h" |
12 | |
13 | |
14 | |
15 | #define setbit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
|
16 | #define clearbit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
|
17 | #define checkbit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
|
18 | #define lichtan() setbit(PORTG,PG1)
|
19 | |
20 | |
21 | #define init_mob_rx_0 init_mob_rx(0,8192,536862720); // einkürzen des
|
22 | Befehls, damit Tag und Mask nicht immer mit eingegeben werden müssen. |
23 | #define init_mob_rx_1 init_mob_rx(1,16384,536862720);
|
24 | #define init_mob_rx_2 init_mob_rx(2,24576,536862720);
|
25 | #define init_mob_rx_3 init_mob_rx(3,32768,536862720);
|
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | void Can_bit_timing (void) |
34 | {
|
35 | |
36 | CANBT1= 0x06; |
37 | CANBT2= 0x0C; |
38 | CANBT3= 0x5A; |
39 | |
40 | }
|
41 | |
42 | void can_init (void) |
43 | {
|
44 | Can_bit_timing(); |
45 | Can_clear_all_MOB(); |
46 | setbit(CANGCON,1); //Can_enable |
47 | //test für sleep_Mode
|
48 | //CANTCON=0xFF;
|
49 | |
50 | }
|
51 | |
52 | void Can_clear_all_MOB (void) |
53 | {
|
54 | int num_mob, num_data; |
55 | |
56 | for (num_mob = 0; num_mob < 15; num_mob++) |
57 | {
|
58 | CANPAGE = (num_mob << 4); |
59 | CANSTMOB = 0; |
60 | CANCDMOB = 0; |
61 | CANIDT4 = 0; |
62 | CANIDT3 = 0; |
63 | CANIDT2 = 0; |
64 | CANIDT1 = 0; |
65 | CANIDM4 = 0; |
66 | CANIDM3 = 0; |
67 | CANIDM2 = 0; |
68 | CANIDM1 = 0; |
69 | for (num_data = 0; num_data < 8; num_data++) |
70 | {
|
71 | CANMSG = 0; |
72 | }
|
73 | }
|
74 | }
|
75 | |
76 | void init_mob_rx (char nummob, long idtag, long idmask) |
77 | {
|
78 | CANPAGE = (nummob << 4); // MOB anwählen |
79 | CANIDT4 = (uint8_t)((idtag<<3) & 0xFF); // Tag setzen |
80 | CANIDT3 = (uint8_t)((idtag>>5) & 0xFF); |
81 | CANIDT2 = (uint8_t)((idtag>>13) & 0xFF); |
82 | CANIDT1 = (uint8_t)((idtag>>21) & 0xFF); |
83 | CANIDM4 = (uint8_t)((idmask<<3) & 0xFF); // Maske setzen |
84 | CANIDM3 = (uint8_t)((idmask>>5) & 0xFF); |
85 | CANIDM2 = (uint8_t)((idmask>>13) & 0xFF); |
86 | CANIDM1 = (uint8_t)((idmask>>21) & 0xFF); |
87 | CANSTMOB = 0x00; |
88 | CANCDMOB = 0x98; // MOB in empfangsmodus |
89 | }
|
90 | |
91 | void init_mob_rply(char *sendstring,char nummob, long idtag, long |
92 | idmask) |
93 | {
|
94 | CANPAGE = (nummob << 4); // MOB anwählen |
95 | CANIDT4 = (uint8_t)(((idtag<<3)+4) & 0xFF); // Tag setzen |
96 | CANIDT3 = (uint8_t)((idtag>>5) & 0xFF); |
97 | CANIDT2 = (uint8_t)((idtag>>13) & 0xFF); |
98 | CANIDT1 = (uint8_t)((idtag>>21) & 0xFF); |
99 | CANIDM4 = (uint8_t)(((idmask<<3)+4) & 0xFF); // Maske setzen |
100 | CANIDM3 = (uint8_t)((idmask>>5) & 0xFF); |
101 | CANIDM2 = (uint8_t)((idmask>>13) & 0xFF); |
102 | CANIDM1 = (uint8_t)((idmask>>21) & 0xFF); |
103 | CANSTMOB = 0x00; |
104 | CANCDMOB = 0xb8; // MOB in reply-mode |
105 | for (int counter = 0; counter < strlen(sendstring); counter++) |
106 | {
|
107 | CANMSG = sendstring[counter]; //bitweise das MOB einlesen |
108 | }
|
109 | }
|
110 | |
111 | |
112 | void can_send_mg (char *sendstring, long msid, int m_box,int remote) |
113 | {
|
114 | CANPAGE = (m_box << 4); // die ersten 4 Bit initialisieren die |
115 | Message Box |
116 | //CANPAGE = 0xd0; // nur noch zur Sicherheit drin,
|
117 | quasi als Erinnerung |
118 | if(remote == 1) CANIDT4 = (uint8_t)(((msid<<3)+4) & 0xFF); |
119 | else
|
120 | CANIDT4 = (uint8_t)((msid<<3) & 0xFF); //Die ersten 3 Bit müssen |
121 | überschieben werden!! RTR-TAG muss eins sein |
122 | CANIDT3 = (uint8_t)((msid>>5) & 0xFF); // &0FF kürzt aud ein Byte |
123 | ein
|
124 | CANIDT2 = (uint8_t)((msid>>13) & 0xFF); |
125 | CANIDT1 = (uint8_t)((msid>>21) & 0xFF); |
126 | CANSTMOB = 0x00; |
127 | CANCDMOB = 80 + strlen(sendstring); //0x58; // 80 + |
128 | |
129 | |
130 | for (int counter = 0; counter < strlen(sendstring); counter++) |
131 | {
|
132 | CANMSG = sendstring[counter]; //bitweise das MOB einlesen |
133 | }
|
134 | |
135 | |
136 | }
|
mailbox 0 abfragen und wieder initialisieren
1 | CANPAGE = 0x00; |
2 | if(checkbit(CANSTMOB,RXOK)) |
3 | {
|
4 | for(int counter=0;counter < (CANCDMOB & 0x0F); counter++) |
5 | {displaystring[counter] = CANMSG;} |
6 | init_mob_rx_0; |
mail senden
1 | can_send_mg ("TexSolar", 8192 + Controller_ID,14,0); |
Danke @flyingwolf! Das mit dem Polling klappt eigentlich ganz gut, jedoch scheint mit dem CAN-Takt etwas noch nocht zu stimmen. Meine Einstellungen habe ich aus der Tabelle der AT90CAN128-Anleitung (ca. Seite 261, Oszillatorfrequenz 4MHz). Meine Wunschfrequenz ist 500 kbps -> CANBT1 = 0x00 CANBT2 = 0x04 CANBT3 = 0x13 Mit hilfe eines CANalyzer wollte ich dann eine Nachricht senden, die mein Atmel empfangen und auswerten sollte (Übertragungsgeschw. ebenfalls 500 kbps, sonst gehts ja nicht). Nachdem ich mir jedoch die Nachricht mit dem Oszi angesehen habe, musste ich (mit erschrecken :-) ) feststellen, dass Nachrichten, die ich vom Atmel sende viel länger sind (3ms) als Nachrichten die ich vom CANalyzer sende (ca. 120 us). Gibt es da noch eine Möglichkeit der Konfiguration, um die Länge der Nachricht zu kürzen?
ich takte mit 8MHz Bei den CANBT hatte ich mich an die Vorlagen gehalten, weil ich noch nicht rausbekommen habe wie das mit den Takteinstellungen funktioniert. Die Routine sendet CAN2B Du kannst es ändern indem Du auf 2A umschaltest, dann ist der Identifierer nur 11 Bit lang statt 29
Was kann man eigentlich bei der USART Initialisierung bei diesem Ding falsch machen? void usart0_init (void) { UBRR0H = 0; UBRR0L = 0; UCSR0A = 0; UCSR0C = (3<<1); //8N1 UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0); sei (); } SIGNAL (SIG_UART0_RECV) { //do something } Irgendwie wird der Interrupt nie ausgelöst (baudratenunabhängig).
Ich verwende den Header der beim WinAVR dabei ist (at90can128.h). Der scheint auch mit dem Datenblatt übereinzustimmen. Bin trotzdem ratlos.
OK, aus irgend einem Grund geht das jetzt auf dem USART0, identischer Code auf dem USART1 arbeitet nicht. Irgendwie habe ich manchmal das Gefühl, der Controller will mich veralbern :) Beim ATMega8 bzw. 128 hatte ich sowas nie festgestellt, aber dieser verhält sich irgendwie z.T. unberechenbar. Vielleicht werde ich auch einfach nur senil ...
ich habe einen haufen ungereimtheiten festgestellt, in der Doku und den Libs, die es dazu gab. Ich will nicht soweit gehen zu sagen dass es Fehler sind, weil es ggf auch an mir liegt, aber es empfihlt sich immer 2 mal hinzuschauen und sich zu fragen ob das logisch ist, was in der Doku steht. Ich habe monate damit zugebracht mich über den 90CAN128 zu wundern. Bei den Ints war auch mal was krumm...
Ich weiß nicht wem ich die Schuld zuschieben soll: - mir - dem Controller - dem gcc Finde es halt nur irgendwie kurios, dass bestimmte Codefragmente einmal funktionieren und ein anderes mal wieder nicht.
Zeig doch mal das Beispiel mit den USARTs. Möglicherweise sind das auch nur Flüchtigkeitsfehler...
- LED mit blinkt mir 0,5Hz (Timerinterrupt) - USART schickt jede Sekunde ein 'x' - Main-Loop pollt auf Empfangsflag, gleichzeitig ist auch Empfangsinterrupt aktiviert - wird Flag erkannt bzw. Interrupt ausgelöst, werden Interrupts deaktiviert - die LED sollte also aufhören mit blinken Bei der Hardware bin ich mir eigentlich sicher, dass sie passt (MAX232), habe das identische schon mit einem ATMega128 aufgebaut. Wenn ich längere Strings via Terminal sende erkenne ich am Multimeter einen Spannungsabfall von 4,95V auf 4,6V (RXD1), ich gehe also mal davon aus, dass Zeichen den MAX232 auch wieder verlassen.
Hängst Du vieleicht mit dem ISP-programmer noch an der Schnittstelle dran? Keine Ahnung ob das was ausmacht, ich benutze den max232 nicht.
Der ISP ist an USART0, dort hängt ein FTDI, mit dem es komischerweise keine Probleme gibt.
ah ja, dann hängt bei mir an USART1 die serielle Schnittstelle. OK ich habe keine Interrupts darauf aber die Schnittstelle arbeitet klaglos. Allerdings habe ich keinen max232 dran. Geht es denn ohne interrupt?
Offensichtlich nicht, da das Flag nicht gesetzt wird. Einzig der Sendebetrieb scheint klaglos zu arbeiten. Werde morgen mal ein Oszi dranhalten, im Zweifel liegt der Fehler immer beim Anwender.
Hallo! Nur zur Info: Habe ein paar Fehler beseitigt... Ein Fehler war, dass ein Fuse-Bit gesetzt wer, nämlich ein Vorteiler, der die Grundfrequenz von 4Mhz geteilt runtergeteilt hat. Dieses hat sich dann auch auf die Sendefrequenz des CANS's ausgewirkt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.