Forum: Compiler & IDEs AT90CAN128


von Thomas27 (Gast)


Angehängte Dateien:

Lesenswert?

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

von flyingwolf (Gast)


Lesenswert?

hast Du es schon ohne interrupt versucht?

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Alex (Gast)


Lesenswert?

OK,

CANIDM4 = 0;//|= (1<<IDEMSK);

und

CANGIE = 0xA0;

und in der ISR

CANCDMOB = (1<<CONMOB1);

Dann empfängt er schonmal Nachrichten via Interrupt :)

von Alex (Gast)


Lesenswert?


von Thomas27 (Gast)


Lesenswert?

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.

von Alex (Gast)


Lesenswert?

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.

von Alexander Mamajew (Gast)


Lesenswert?

@Alex

Dies

CANTIML = 0;
CANTIMH = 0;
CANTTCL = 0;
CANTTCH = 0;

bringt nichts, da CANTIM, CANTTC und ander CAN-Timer nur Lesezugriff
zulassen

von Alex (Gast)


Lesenswert?

@Alexander

Das weiß ich, es ist auch in der Endversion (vgl. Codesammlung) nicht
mehr drinnen. Stammt noch aus dem Testbetrieb.

von flyingwolf (Gast)


Lesenswert?

@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.

von flyingwolf (Gast)


Lesenswert?

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);

von Thomas27 (Gast)


Lesenswert?

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?

von flyingwolf (Gast)


Lesenswert?

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

von Alex (Gast)


Lesenswert?

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).

von flyingwolf (Gast)


Lesenswert?

hast Du die Interrupttabelle vom 90CAN128 genommen, oder die vom
MEGA128?

von Alex (Gast)


Lesenswert?

Ich verwende den Header der beim WinAVR dabei ist (at90can128.h). Der
scheint auch mit dem Datenblatt übereinzustimmen. Bin trotzdem ratlos.

von Alex (Gast)


Lesenswert?

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 ...

von flyingwolf (Gast)


Lesenswert?

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...

von Alex (Gast)


Lesenswert?

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.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Zeig doch mal das Beispiel mit den USARTs.
Möglicherweise sind das auch nur Flüchtigkeitsfehler...

von flyingwolf (Gast)


Lesenswert?

könnte es an irgend welchen fuses liegen?

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

- 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.

von flyingwolf (Gast)


Lesenswert?

Hängst Du vieleicht mit dem ISP-programmer noch an der Schnittstelle
dran?
Keine Ahnung ob das was ausmacht, ich benutze den max232 nicht.

von Alex (Gast)


Lesenswert?

Der ISP ist an USART0, dort hängt ein FTDI, mit dem es komischerweise
keine Probleme gibt.

von flyingwolf (Gast)


Lesenswert?

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?

von Alex (Gast)


Lesenswert?

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.

von Thomas27 (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.