AT90CAN128

Gast #237060
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
Angehängte Dateien:
Gast #237062
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.
Angehängte Dateien:
Gast #237065
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.
Gast #237066
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.
Gast #237069
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.
Gast #237070
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);
Gast #237071
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?
Gast #237072
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
Gast #237073
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).
Gast #237076
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 ...
Gast #237077
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...
Gast #237078
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.
Gast #237081
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.
Angehängte Dateien:
Gast #237084
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?
Gast #237086
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.

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