Forum: Mikrocontroller und Digitale Elektronik CAN auslesen AT90CAN128


von Julian M. (julianm94)


Lesenswert?

Hallo Community,
Zwar habe ich folgendes Problem.
Ich wollte für ein Projekt mithilfe des AT90CAN128 CAN Ids auslesen und 
diese über ein Display ausgeben.
Leider bekomme ich es nicht genau hin. Habe auch schon die Forumssuche 
benutzt, aber hier findet man meist nur Beispiele zum senden und 
antworten.
Der Controller soll eigentlich "nur" Ids auslesen können.
Jetzt wollte ich hier Fragen ob jemand hierfür vielleicht einen Beispiel 
Code oder eine Lib oder sonstiges hätte.
Schonmal danke im Vorraus.

Mit freundlichen Grüßen
Julian

von Marc S. (marc_s86)


Lesenswert?

sieh dich mal hier um:
Beitrag "CAN-Bibliothek für den at90CAN128 und das AVRStudio"
wenn du keine filter setzt bekommst du alle nachrichten und kannst dir 
dann deren ids ausgeben.

von Julian M. (julianm94)


Lesenswert?

Vielen Dank. Diesen Beitrag habe ich auch schon komplett durchgepaukt. 
Da fehlt mir aber leider ein Beispiel zum ID empfangen.
Nehmen wir an ich will den Inhalt von dem unsigned int mit der ID 
0x773[2]als Beispiel in eine Variable speichern, sodass ich die auf 
einem Display ausgeben kann.
Der Codeschnipsel welcher dann in der Main stehen würde, den bekomme ich 
einfach nicht hin.
Vielleicht weiß ja noch jemand was.
Schonmal danke im Vorraus.

von Cube_S (Gast)


Lesenswert?

So in etwa mache ich das:
1
ISR(CANIT_vect)
2
{
3
  CANPAGE = CANHPMOB;
4
5
  // Hier CANIDT auswerten
6
7
  ...
8
          
9
  CANSTMOB = 0;
10
  CANCDMOB = (2<<CONMOB0)|8;
11
}
12
13
void main()
14
{
15
  // 125 kHz @ 16MHz
16
  CANBT1 = 0x1e;
17
  CANBT2 = 0x04;
18
  CANBT3 = 0x13;
19
  
20
  // 8 mobs für Empfang
21
  for (uint8_t page=0; page<0x70; page+=0x10)
22
  {
23
    CANPAGE = page;
24
    CANSTMOB = 0;
25
    CANIDT = 0;
26
    CANIDM = 0;
27
    CANCDMOB = (2<<CONMOB0)|8;
28
  }
29
    
30
  CANGCON = (1<<ENASTB);
31
  CANGIE = (1<<ENIT)|(1<<ENRX);
32
33
  CANIE2 = 0xFF; // interrupts für mobs 0-7
34
  
35
  sei();
36
  while(1);
37
}

von Rudolph R. (rudolph)


Lesenswert?

Schau mal hier: Beitrag "ATMEGA16m1 CAN-Interrupt"
bzw. das hier: 
https://www.mikrocontroller.net/attachment/216654/16M1_Test.c

Das ist zwar für einen Mega16M1, im Bezug auf den CAN ist der aber mit 
dem 90CANxx identisch, da sind nur die I/O Ports anders weil der weniger 
Pins hat.

von Julian M. (julianm94)


Lesenswert?

Vielen Dank!
Wenn ich dass richtig sehe, kann ich dann dort meine IDs anpassen. Und 
wenn noch mehr hinzukommen, da in dem Beispiel ja nur zwei sind. Einfach 
eine weitere Canpage hinzufügen und dann kann ich auf die IDs zugreifen.
Jedoch verstehe ich nicht wie sie bei CANMSG auf 0x55 und 0xaa kommen, 
da ihre Empfangs ID ja 0x333 ist.
Entschuldigen Sie für die vielleicht unnötigen Fragen, aber bin sehr neu 
in diesem Gebiet.
Schonmal Danke im Vorraus.

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Wenn ich dass richtig sehe, kann ich dann dort meine IDs anpassen. Und
> wenn noch mehr hinzukommen, da in dem Beispiel ja nur zwei sind. Einfach
> eine weitere Canpage hinzufügen und dann kann ich auf die IDs zugreifen.

Im CANPAGE Register steht drin, auf welche Message-Box sich die aktuelle 
Aktion gerade bezieht.
Das wird im Interrupt gesichert damit man nicht die Hauptschleife 
durcheinander wirft.
Also im Grunde meinst Du wahrscheinlich das richtige, so formuliert 
hätte ich das aber nicht.
Wenn man das mit dem Filter so benutzt das pro Message eine ID verwendet 
wird, dann muss man für eine weitere ID eine neue Message-Box 
konfigurieren.

> Jedoch verstehe ich nicht wie sie bei CANMSG auf 0x55 und 0xaa kommen,
> da ihre Empfangs ID ja 0x333 ist.

0x55 0xaa ist der Botschafts-Inhalt, nur so als Beispiel.

Die bis acht Byte der Botschaft liegen ja nicht in acht Registern, der 
Zugriff erfolgt über das eine CANMSG Register.

Ach ja, die Botschaft wird in dem Beispiel nicht mal gelesen, es wird ja 
nur dessen Empfang festgestellt und ein Flag gesetzt.

Übrigens, die CANEN Zeilen in der Init sind überflüssig - stören aber 
auch nicht.

: Bearbeitet durch User
von Julian M. (julianm94)


Lesenswert?

Vielen Dank, dass du dir dafür so Zeit nimmst.
Habe dann nun auch alles soweit verstanden.
In dem Beispiel Programm wird getestet ob er eine Nachricht erhält und 
wenn diese Erhalten wurde. Schickt er eine Neue Massage los mit dem 
Message Inhalt 0x55 und 0xaa.
Dann muss ich mich jetzt nur noch Informieren wie man die Message dann 
ausließt und in eine Variable speichern kann, welche ich dann auf dem 
Display ausgeben kann.
Ist alles komplizierter als Gedacht, da man im Internet zum reinen 
Auslesen nicht sonderlich viel findet. Sondern eher zum Senden.

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Dann muss ich mich jetzt nur noch Informieren wie man die Message dann
> ausließt und in eine Variable speichern kann, welche ich dann auf dem
> Display ausgeben kann.

Die Daten sind wie geschrieben im CANMSG Register.
Man muss die also nur noch auslesen:
1
if(CANSIT2 & 0x02) // MOB1
2
{
3
  CANPAGE = (1<<4); // select MOB1
4
  CANSTMOB &= ~(1<<RXOK); // clear interrupt flag
5
  CANCDMOB = (1<<CONMOB1) | (1<<DLC3);
6
7
  var1 = CANMSG;
8
  var2 = CANMSG;
9
  var3 = CANMSG;
10
  var4 = CANMSG;
11
  var5 = CANMSG;
12
  var6 = CANMSG;
13
  var7 = CANMSG;
14
  var8 = CANMSG;
15
16
  can_received = 42;
17
}

Oder mit ner Schleife in ein Array schieben, oder was auch immer. :-)

Im CANPAGE Register steht dazu noch ein Index und es gibt ein Auto-Index 
Bit, die werden durch den Zugriff auf CANPAGE auf Null gesetzt und 
fertig.

Und als einfaches Beispiel fängt das Null Fehler ab, zum Beispiel könnte 
eine Botschaft mit weniger Byte eingehen als erwartet werden.

von Julian M. (julianm94)


Lesenswert?

Vielen Dank für Ihre schnellen Antworten.
Die 0x02 oben wird dann die dementsprechende ID sein.
also bei mir z.B. 0x773[2].
dann versuch ich das mal, vielen Dank nochmal.

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Die 0x02 oben wird dann die dementsprechende ID sein.

Nein, im CANSIT2 Register findet man, welche Message-Box den Interrupt 
ausgelöst hat.
Das ist total faul geschrieben. :-)
1
if((CANSIT2 & (1<<SIT1)) != 0) // IRQ von Message-Box 1?

In dem Beispiel ist Message-Box 1 auf den Empfang der ID 0x333 
konfiguriert.

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Vielen Dank für Alles habe nun mal mein Bestes gegeben und den C-Code 
angehängt. Vielleicht könnten sie ja, wenn sie Zeit haben mal drüber 
schauen.
Habe das Beispiel angepasst. Wollte fragen ob dies so stimmt und ich 
dann in der While Schleife auch immer den Aktuellen Wert habe. Habe auch 
noch eine zweite Id zum empfangen eingestellt.
Schonmal danke im Vorraus.

von Rudolph R. (rudolph)


Lesenswert?

Da sind ein paar Schnitzer drin, das funktioniert so nicht.
1
  id = 0x773;   // Empfangs-ID
2
  CANPAGE = (1<<4); // select MOB1
3
  CANIDT1 = (id >> 3); // Put bits 3-11 of message ID into CANIDT1
4
  CANIDT2 = (id << 5); // Put bits 0-2 of message ID into CANIDT2
5
  CANIDM1 = 0xff;
6
  CANIDM2 = 0xe0;
7
  CANIDM4 = (1<<IDEMSK);
8
  CANCDMOB = (1<<CONMOB1) | (1<<DLC3); // set to receive, 8-bytes in message
9
10
  id = 0x775;   // Empfangs-ID
11
  CANPAGE = (2<<4); // select MOB2
12
  CANIDT1 = (id >> 3); // Put bits 3-11 of message ID into CANIDT1
13
  CANIDT2 = (id << 5); // Put bits 0-2 of message ID into CANIDT2
14
  CANIDM1 = 0xff;
15
  CANIDM2 = 0xe0;
16
  CANIDM4 = (1<<IDEMSK);
17
  CANCDMOB = (1<<CONMOB1) | (1<<DLC3); // set to receive, 8-bytes in message
18
19
  CANGIE = (1<<ENIT) | (1<<ENRX); // enable receive interrupt
20
  CANIE1 = 0x00;
21
  CANIE2 = (1<<IEMOB1); // enable MOB1 IRQ
22
  CANIE2 |= (1<<IEMOB2); // enable MOB2 IRQ
23
  CANSIT1 = 0x00;
24
  CANSIT2 = 0x00;
25
}

Den Block unter der Konfiguration für die jeweiligen Message-Boxen 
braucht man nur einmal und wenn man ein Register wie CANIE2 ein zweites 
Mal beschreibt dann besser mit einer Read-Modify-Write Operation. :-)
1
ISR (CAN_INT_vect)
2
{
3
  uint8_t canpage;
4
5
  canpage = CANPAGE; // save canpage
6
7
  if((CANSIT2 & (1<<SIT1)) != 0) // MOB1
8
  {
9
    CANPAGE = (1<<4); // select MOB1
10
    CANSTMOB &= ~(1<<RXOK); // clear interrupt flag
11
    CANCDMOB = (1<<CONMOB1) | (1<<DLC3);
12
13
    int i;
14
    unsigned int messwerte[8];
15
16
    for(i=0; i<8; i++) {
17
      
18
    messwerte[i] = CANMSG;
19
    
20
    }
21
22
    can_received = 42;
23
  }
24
  
25
  if((CANSIT2 & (1<<SIT2)) != 0) // MOB2
26
  {
27
    CANPAGE = (2<<4); // select MOB1
28
    CANSTMOB &= ~(1<<RXOK); // clear interrupt flag
29
    CANCDMOB = (1<<CONMOB1) | (1<<DLC3);
30
31
    int i;
32
    unsigned int temperatur[8];
33
34
    for(i=0; i<8; i++) {
35
      
36
      temperatur[i] = CANMSG;
37
      
38
    }
39
40
    can_received = 42;
41
  }
42
43
  CANPAGE = canpage; // restore canpage
44
}

Ähem, erstmal sind die Variablen lokal für die Funktion, das verlässt 
den Interrupt doch nie.
Und dann ist es "(1<<SIT2)" für MOB2.

Und die 1980er klingeln gerade durch und wollen Ihre Variablen vom Typ 
"int" und "unsigned int" wieder haben. ;-)

1
  DDRB = 0x00;  // alle Pins auf Eingang
2
  PORTB = 0xff; // Pullups an
3
4
  DDRC = (1<<PC2) |(1<<PC7) | (1<<PC6);
5
  PORTC = 0xff; // Pullups an / Ausgang auf High
6
7
  DDRD = 0x00; // alle Pins auf Eingang
8
  PORTD = 0xff; // Pullup-Widerstände an
9
10
  DDRE = 0x00;  // alle Pins auf Eingang
11
  PORTE = 0xff; // Pullups an

Da fehlt noch einiges, der 90CANxx hat noch ein paar Ports mehr
und TXCAN auf PD5.
Das ist einfach nur Copy-Paste von meinem Mega16M1 Beispiel.
1
  while(1)
2
  {
3
    // Hier kann ich dann einfach den Wert der Id ausgeben lassen?
4
    // also in dem ich einfach in den Displaybefehl als ausgabewert messwerte[3] eingebe?
5
    // und auch zum Beispiel temperatur[4]?
6
  }
7
}

Ja, sobald die auch verfügbar sind. :-)

Also am einfachsten Global deklariert mit volatile wie die 
"can_received" Variable und mit Default-Wert.

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Vielen Dank!
Ich hoffe, ich habe nun die Sachen richtig verbessert.
Ich habe die zwei Can Ports des at90Can auf 1 gesetzt und sonst noch die 
Ports auf Ausgang die ich brauche.
Und durch die Globale Deklaration kann ich nun auf die Variablen in der 
Main zugreifen?
Schonmal danke im Vorraus.

von Rudolph R. (rudolph)


Lesenswert?

1
  CANGCON = (1<<SWRES); // off and reset
2
3
  for (i=0; i<6; i++)
4
  {
5
    CANPAGE = (i<<4); // select MOb

Mach aus der "6" mal noch eine 15, der 90CAN hat ein paar Message-Boxen 
mehr. :-)
1
volatile uint16_t messwerte[8]={0};
2
volatile uint16_t temperatur[8]= {0};

Warum eigentlich 16 Bit wenn die Werte doch nur 8 Bit breit sind?
1
  DDRD = (1<<PD5) |(1<<PD6);
2
  DDRA = 0xFF;  // Hier sind LEDs angeschlossen
3
  DDRC = 0xFF;  // Hier sind LEDs angeschlossen

Also kann ja jeder machen wie er will, aber normalerweise initalisiere 
ich erstmal alle Ports komplett durch und schalte bei den unbenutzen 
Pins die Pullup-Widerstände ein.

Und ja, in dem Context würde ein "PORTA = 0x00" nichts bewirken weil das 
Register nach dem Reset sowieso auf Null steht, ich finde es aber 
übersichtlicher explizit hinzuschreiben was man vorhat.

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Vielen Dank, dank ihnen verstehe ich nun einigermaßen was ich mache :)
Habe nun noch meine letzte ID hinzugefügt.
Ist eine Multiplex ID, hoffe ich habe sie richtig realisiert.
Nun habe ich jedoch noch eine Frage, wird der Interrupt dann immer von 
selbst ausgelößt oder muss ich den in der Main() auch irgendwo auslösen?
Dass ich immer die Aktuelle Zahlen habe und nicht nur die, die er beim 
ersten Durchgang rausließt.
Schonmal danke im Vorraus

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Ist eine Multiplex ID, hoffe ich habe sie richtig realisiert.

Sieht gut aus, ist nur nicht ganz optimal.
1
  for(i=0; i<8; i++) { // Ist ein Multiplex mit 3 Row
2
         // Welche Row dran ist wird im Bit 0 übertragen
3
    if (i==0){
4
      row=CANMSG;
5
    }else{
6
    temperatur[i][row] = CANMSG;
7
    }
8
  }


Das "if(i==0)" wird bei jedem Durchlauf mit überprüft.
1
        row = CANMSG;
2
3
  for(i=0; i<7; i++) {
4
    temperatur[i][row] = CANMSG;
5
  }

Als Optimierung etwas witzlos, zugegeben, man sollte Interrupts aber 
auch immer so kurz wie möglich halten.

> Nun habe ich jedoch noch eine Frage, wird der Interrupt dann immer von
> selbst ausgelößt

Ja, es gibt automatisch einen IRQ wenn eine Botschaft mit der passenden 
ID empfangen wurde.

> Dass ich immer die Aktuelle Zahlen habe und nicht nur die, die er beim
> ersten Durchgang rausließt.

Das Flag "can_received" ist in meinem Beispiel dafür da der 
Hauptschleife zu melden, dass was empfangen wurde.
Das könnte man dafür nutzen um ein Display nur bei Änderungen zu 
aktualisieren.
1
if(can_received != 0)
2
{
3
 can_received = 0;
4
 mach_was_mit_den_daten();
5
}

Wobei das auch drei Flags sein könnten, für jede Botschaft einzeln.

can_received_temperatur
can_received_gang
can_received_messwerte

Oder so ähnlich. :-)
Oder ganz weglassen geht auch. :-)

: Bearbeitet durch User
von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Vielen Dank.
Habe nun meinen Code soweit fertig, es kommen auch keine Error 
Meldungen.
Kann ihn leider warscheinlcih erst Dienstag testen.
Jedoch kommen zwei Warnings einmal:
Warning  1  #warning "F_CPU not defined for <util/delay.h>" [-Wcpp]
Obwohl ich
#define F_CPU 16000000ULL
#include <util/delay.h>
geschrieben habe.

Die zweite Warning verstehe ich leider gar nicht und weis auch nicht, 
nach was ich im Internet suchen sollte.

Warning  2  'CAN_INT_vect' appears to be a misspelled signal handler 
[enabled by default]

Schonmal danke im Vorraus. :)

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Warning  1  #warning "F_CPU not defined for <util/delay.h>" [-Wcpp]
> Obwohl ich
> #define F_CPU 16000000ULL
> #include <util/delay.h>
> geschrieben habe.

Hmm, das bekomme ich garnicht.
Ich habe gerade ein neues Projekt aufgemacht mit dem 90CAN128, Deinen 
Text rein kopiert, das GLCD Zeug auskommentiert und durchlaufen lassen.

Auch ein zusätzliches "_delay_ms(12);" führt zu keiner Warnung.

> Die zweite Warning verstehe ich leider gar nicht und weis auch nicht,
> nach was ich im Internet suchen sollte.
>
> Warning  2  'CAN_INT_vect' appears to be a misspelled signal handler
> [enabled by default]

Das kommt davon, wenn man das "trocken" macht. :-)
Das muss "ISR (CANIT_vect)" sein.

Aber ich bekomme noch zwei Warnung für das hier:
1
  sprintf(wassertempstring, "%i", temperatur[2][6]);
2
  sprintf(oiltempstring, "%i", temperatur[2][7]);

Die Variable ist so definiert:
1
volatile uint8_t temperatur[8][3]={{0},{0}};

von Julian M. (julianm94)


Lesenswert?

Vielen Dank :)
Builded nun ohne Errors und ohne Warnings.

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Also habe es heute geflasht, leider hatte ich heute keine möglichkeit 
die Can übertragung zu testen, werde ich morgen machen.
Jetzt aber eine Frage muss ich dass ISR wieder umbennen wenn ein CAN 
angeschlossen ist?
Und ist es normal, dass wenn kein CAN angeschlossen ist, auf dem Display 
an den Postionen der Prints eine Art Verpixeltes Zeichen erscheint? Da 
die Zahlen ja eigentlich mit 0 deklariert sind.
Schonmal danke im Vorraus.

von Julian M. (julianm94)


Lesenswert?

Display funktioniert jetzt, aber er bekommt irgendwie keine can Daten.

von Julian M. (julianm94)


Lesenswert?

Habe es heute auch mal komplett ohne Display getestet. Der Chip bekommt 
keine CAN Daten.

von Rudolph R. (rudolph)


Lesenswert?

Wie sieht überhaupt die Hardware dafür aus?

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Hier ist der Schaltplan.
Also Chip AT90CAN128, dann sind LEDs die angesteuert werden und das 
Display3000.
Die CAN Daten kommen von einer BOSCH MS4 Box.

: Bearbeitet durch User
von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Hier ist der Schaltplan.

Wirf das mal bitte in lesbar über den Zaun. :-)

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

oh sehe es gerade, ich lade ihn als pdf hoch.

von Rudolph R. (rudolph)


Lesenswert?

Spontan fällt mir auf, dass da erheblich zu wenig Kondensatoren an den 
Versorgungs-Anschlüssen der ICs sind.

Und wieder mal die "typischen" 22pF Kondensatoren am Quarz - welcher 
Quarz ist das genau?

Sind die Fuse-Bits im Controller richtig gesetzt so das der auch 
wirklich auf den 16 MHz läuft?

Edit: Was zum Henker soll da drauf ein 3A Schaltregler?

: Bearbeitet durch User
von Julian M. (julianm94)


Lesenswert?

Es ist ein 16 MHz Quartz.
Die Fuse-Bits müssten richtig gesetzt sein. Sie haben mir ja damals ein 
Testprogramm geschickt und dort war ja auch auf 16 Mhz eingestellt und 
sie meinten ja dass im CAN bereicht, sich der Chip nicht unterscheidet 
zum AT90CAN128.

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Es ist ein 16 MHz Quartz.

Ja, schon, aber welcher genau?

> Die Fuse-Bits müssten richtig gesetzt sein.

Müssten oder sind? :-)

> Sie haben mir ja damals ein Testprogramm geschickt und dort war
> ja auch auf 16 Mhz eingestellt

Das Programm ändert aber nichts an den Einstellungen, das Programm geht 
von dieser Konfiguration aus.

> und sie meinten ja dass im CAN bereicht,
> sich der Chip nicht unterscheidet zum AT90CAN128.

Das ist richtig, bis auf die Anzahl der Message-Objekte unterscheiden 
sich die CAN-Einheiten nicht.

von Julian M. (julianm94)


Lesenswert?

Oh wo sehe ich welcher Quartz dies genau ist. Wie schon gesagt ist mein 
erstes Projekt und habe die Platine so bekommen.
Achso wenn das Programm nichts an den Einstellungen ändert wird dies 
wohl der Fehler sein. Habe dann gar keine Einstellungen.

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Oh wo sehe ich welcher Quartz dies genau ist. Wie schon gesagt ist mein
> erstes Projekt und habe die Platine so bekommen.

Dann kann man nur hoffen, dass derjenige der das gebaut hat wusste, was 
er tut, am Schaltplan lässt sich das aber leider erstmal nicht wirklich 
fest machen.
Hast Du auch das Layout? Wie sieht der Quarz denn aus?
Bei 500 kBit wird es aber so oder so hoffentlich nicht daran liegen.

> Achso wenn das Programm nichts an den Einstellungen ändert wird dies
> wohl der Fehler sein. Habe dann gar keine Einstellungen.

Kommt darauf an ob der Controller auf dem Board noch ganz frisch war 
oder ob damit schon jemand rumgespielt hat.
Mach im Programmier-Fenster mal die "Fuse" Einstellungen auf und mach 
Screenshots davon.

von Julian M. (julianm94)


Lesenswert?

habe alles durchsucht, kann leider dieses Fenster nicht finden.
Benutze Atmel Stuidio 6.

von Rudolph R. (rudolph)


Angehängte Dateien:

Lesenswert?

Julian M. schrieb:
> habe alles durchsucht, kann leider dieses Fenster nicht finden.

Das ist der Reiter im Programmier-Dialog.

von Julian M. (julianm94)


Lesenswert?

Extend, High und Low sind alle auf 0xFF.
Angekreuzt ist auch nichts.
Daran wirds dann wohl liegen oder?

von Rudolph R. (rudolph)


Angehängte Dateien:

Lesenswert?

Julian M. schrieb:
> Daran wirds dann wohl liegen oder?

Yup, genau daran liegt es, der Controller läuft dann  nur aus dem 
internen RC-Oszillator mit 1 MHz.

Leider kann ich im Emulator den 90CAN128 nicht auswählen, ich habe aber 
auch keinen Programmer hier.

Auf jeden Fall muss die CKDIV8 Fuse aus sein.
Und mach mal nen Screenshot von den Einstellung für den Takt, aus dem 
Kopf heraus müsste das eine der Optionen ganz unten sein, stelle aber 
besser nichts ein wenn Du nicht sicher bist.

Edit, habe mal nen Bild angehängt.
Das kommt von http://www.engbedded.com/fusecalc/

: Bearbeitet durch User
von Julian M. (julianm94)


Lesenswert?

Sry mein Snipping tool gängt sich gerade immer auf.
Dort steht:
Ext. Crystal Osc. 8.0-   MHz; Start-up time: 16K CK + 65 ms

von Marc H. (marchorby)


Lesenswert?

Poste mal bitte das .sch und .brd-File!

von Julian M. (julianm94)


Lesenswert?

Diese zwei File arten gibt es bei mir nicht.

von Marc H. (marchorby)


Angehängte Dateien:

Lesenswert?

Julian M. schrieb:
> Diese zwei File arten gibt es bei mir nicht.

Erzähl kein Misst! Du verwendest Eagle, das nutzt .sch und .brd

von Julian M. (julianm94)


Angehängte Dateien:

Lesenswert?

Habe die Platine ja nicht selbst gemacht und die Sachen dazu nur 
bekommen.
Also habe somit die zwei Files nur als PDF.

von Marc H. (marchorby)


Lesenswert?

Achso, das ist aber blöd, weil wir nicht wissen wie deine Platine nun 
aussieht und ob dort ein Fehler ist.

von Rudolph R. (rudolph)


Lesenswert?

Das Layout ist auch an mehreren Stellen falsch, viel Erfahrung hatte der 
Benedict damit nicht.
Aber ich gehe mal davon aus, dass das mal irgendwie funktioniert hat 
wenn das in einem Formula-Student Racer verbaut war.

Die 22pF sind übrigens wirklich falsch für den Quarz, in der Bauform 
haben die typisch ein CL von 30pF und bräuchten so je 56pF.
Nur sollte der dennoch anlaufen und der CAN müsste bei 500kBit gerade 
noch so laufen.

Der CAN-Transceiver ist jedenfalls richtig verdrahtet, dem fehlt nur ein 
Kondensator an der Versorgung.

Die Fuses passen jetzt?
Ist der Jumper am CAN gesteckt, oder ein externe 120 Ohm am Bus oder in 
der "BOSCH MS4 Box" 120 Ohm verbaut/aktiviert?

von Julian M. (julianm94)


Lesenswert?

Vielen Dank, habe gerade erfahren, dass es noch nie funktioniert hat. 
Ein Jumper ist nicht gesteckt. Ich glaube in der box sind die 120ohm 
aktiviert, denn wenn man Daten direkt ausließt von der ms4 also mit 
einem converter anschließt und dann empfängt man zum Beispiel mit 
busmaster die Botschaften.
Die Fuses müssten nun passen.
Vielen Dank für alles, ich halte euch auf dem laufenden ob es 
funktioniert.

von Rudolph R. (rudolph)


Lesenswert?

Julian M. schrieb:
> Vielen Dank, habe gerade erfahren, dass es noch nie funktioniert hat.

Na, die Vögel sind ja lustig, Dir so ein Board anzudrehen. :-)

Was passiert denn wenn Du an das lauffähige System aus Bosch-Box und 
USB-CAN-Adapter mit Busmaster die Platine auch noch als dritten 
Teilnehmer anschliesst?

Ach ja, noch einen, hast Du jetzt eigentlich die Port Konfiguration noch 
ergänzt? In Deinem letzten Test-Programm stand da ja quasi noch nichts 
drin.

von Julian M. (julianm94)


Lesenswert?

Habs die Ports für den can auf high gesetzt. Dann die Ports für die LEDs 
als Ausgang gesetzt und dann halt noch das Display initialisiert.
Wenn ich die Platine als dritten Teilnehmer anschließe ist es so, dass 
die eigentlich gar nicht reagiert. Also es verändern sich keine Werte 
auf dem display oder so.

von Rudolph R. (rudolph)


Lesenswert?

Sind wirklich alle Ports durchkofiguriert?

Und was sagt dann Busmaster? Keine Error-Frames? Die Botschaften liegen 
auch wirklich auf dem Bus?

Und Du kannst doch mit einer von den 16 LEDs im CAN-Interrupt wackeln.

von Julian M. (julianm94)


Lesenswert?

Nein keine error frames, also die ms4 sendet aufjedenfall die 
Botschaften richtig. Das Problem ist, dass er nicht in das ISR reingeht 
irgendwie.
Ob die Ports alle richtig sind kann ich leider nicht sagen. Dafür kenne 
ich mich zuwenig aus, ist mein erstes Projekt. Habe halt im Internet 
nach geschaut, welche Ports der at90can128 für die can Übertragung 
braucht und die habe ich auf high gesetzt. Wahrscheinlich habe ich mich 
mit diesem Projekt einfach übernommen. Und die Ports für das display 
usw. Sind richtig gesetzt. Den ich habe das Programm mal so 
umgeschrieben dass anstatt die can Daten. Festgelegte Werte genommen 
werden die sich verändern. Dann funktioniert auch alles wunderbar.

von Rudolph R. (rudolph)


Lesenswert?

Hier:
1
void init_ports(void)
2
{
3
  DDRA = 0xFF;  // Hier sind LEDs angeschlossen
4
  PORTA = 0x00;
5
6
  DDRB = (1<<PB1) | (1<<PB2) | (1<<PB4) | (1<<PB5) | (1<<PB6); // LCD-Ports auf Ausgang setzen
7
  PORTB = (1<<PB0) | (1<<PB7); // Pullups an ungenutzen Pins einschalten
8
9
  DDRC = 0xFF;  // Hier sind LEDs angeschlossen
10
  PORTC = 0x00;
11
12
  DDRD = (1<<PD5);
13
  PORTD = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD7);  // Pullups an ungenutzen Pins einschalten
14
15
  DDRE = (1<<PE1);
16
  PORTE = (1<<PE2) | (1<<PE3) | (1<<PE4) | (1<<PE5) | (1<<PE6) | (1<<PE7);  // Pullups an ungenutzen Pins einschalten
17
18
  DDRF = 0x00; // alle Pins auf Eingang
19
  PORTF = 0xff; // Pullup-Widerstände an
20
21
  DDRG = 0x00; // alle Pins auf Eingang
22
  PORTG = 0xff;  // Pullup-Widerstände an
23
}

Beim PORTB für das LCD bin ich mir nicht sicher, die müssten irgendwo 
anders noch initialisiert werden, dazu fehlt aber jeglicher Aufruf in 
Deinem Programm.

Eine LED kann man wackeln lassen mit dem PIN-Register:

PINC = (1<<PC0); // Zustand von LED1 wechseln

Das geht nicht mit allen AVR, aber beim 90CAN funktioniert das so.
1
ISR (CANIT_vect)
2
{
3
    uint8_t canpage;
4
5
    PINC = (1<<PC0); // Zustand von LED1 wechseln

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.