Hallo Zusammen,
ich arbeite im Rahmen eines Projektes mit dem AT32UC3C0512C und möchte
damit eine CAN-Kommunikation aufbauen.
Um in die Thematik näher rein zu finden, habe ich das Beispielprogramm
CAN_EXAMPLE21 vom Atmel Software Framework im Atmel Studio 6 in Betrieb
genommen.
Ich habe lediglich die UART-Anzeige herausgenommen und die Baudrate
halbiert.
Leider hängt sich das Programm nach einmaligem Senden sofort auf. Dies
aber nur, wenn ein Teilnehmer am Bus hängt.
Ich konnte den Fehler soweit eingrenzen, dass beim Senden kein Fehler
auftritt wenn ich die Funktion CANIF_mob_enable_interrupt(ch,handle)
herausnehme. Diese ist in CAN_tx() hinterlegt und sorgt für einen
Interruptaufruf des MessageObjects.
Ich habe im Anhang das Projekt angehängt und dazu auch noch zwei
Screenshots der Initialisierung.
In einem anderen Beitrag im Forum habe ich gelesen dass bei dem Bsp.
evtl. die Systemtimerinitialisierung fehlen würde, aber ich konnte
leider nicht verstehen, was dort gemeint ist. Hier der Link dazu:
Beitrag "AT32UC3C0512C - CAN-Probleme"
Über Hilfe oder Anregungen wäre ich sehr dankbar.
Viele Grüße
Simon
>Bildformate...
Ein öffentlicher Pranger in einem Forum/Wiki. Wo gibt's denn so was.
Ist das peinlich. Und da steht er jetzt bin in alle Ewigkeiten drin,
weil die GIFs unscharf sind ?
Ich schäme mich echt für diesen Wikiartikel.
Hallo!
Entschuldigt bitte die Bildformate. Hab gestern Abend den Hinweis
überlesen. Das tut mir Leid.
Wenn ihr wollte lade ich die Bilder nochmal hoch und zwar in einem
besseren Format.
Hallo Simon,
schön das mein Artikel einmal zitiert worden ist.
Ich habe die 2 Beispiele auch schon einmal compiliert und programmiert.
Man braucht dazu den VCP-Treiber für den PC, um sehen zu können, was der
Controler macht.
Die CAN-LIN-Applikation läuft ganz anständig. Da wurde im ASF auch kein
Sleep-Modus verwendet.
Einzig die Art der Datenhaltung ist gewöhnungsbedürftig.
Was willst Du erreichen?
Hallo!
Ist ja cool, dass du dich meldest.
Mein Ziel ist es Daten von verschiedenen CAN-Teilnehmern zusammen zu
sammeln und zu verarbeiten.
Zum Test wollte ich das Senden von Daten zu den Teilnehmern und das
Anfordern separat ausprobieren.
Ich habe den Teil mit der Anzeige über das Hyperterminal rausgemacht.
Könnte es schon reinmachen, aber im Prinzip mach ich das gleiche wie die
Steuerung über den COM, abgesehen davon dass ich alle 2Sekunden zyklisch
etwas senden möchte.
Was hast du damals mit der fehlenden Systemtimerinitialisierung gemeint?
Was hat konkret gefehlt?
Vielen Dank für deine Hilfe!
Moin Simon,
das ist mittlerweile ganz schön her.
Ich habe noch die Projekte und muß einen Diff drüberlaufen lassen. Aber
ich glaube mich noch dunkel daran zu erinnern, dass die einfach den
Funktionsaufruf der sys_clock vergessen hatten. Ich hatte CAN-Beispiel 2
gegen die CAN-LIN-Application-Demo verglichen. Und da ist mir das dann
aufgefallen.
Ja, generell kostet dieser Prozessor mit seinem Framework echt viel Zeit
und erst jetzt, wo ich ein paar hundert Seiten des UG vom UC3C gelesen
habe, fange ich an zu verstehen, was die da in Norwegen programmiert
haben.
Da haben die von Infineon mit ihrem DaVE eine bessere Lösung angeboten,
um schnell einen Start-up für ihre Prozessoren hinzubekommen.
Außerdem habe ich immer noch keine brauchbare Doku gefunden, die mir die
Funktionen der Komponenten und Treiber des ASF beschreibt. Das ist
eigentlich eine Grundvoraussetzung, um den Vorteil der angebotenen
Lösungen zu verstehen und zeitnah nutzen zu können. Ich will ja die
ganzen Parameter und Definitionen nicht im reverse Engineering
herausfinden müssen. Aber das mache ich gerade.
Das Hauptproblem sind die gegenseitigen Abhängigkeiten der einzelen
Komponenten. Das Wort "Peripherie" wird dem Funktionsumfang nicht
gerecht.
Das System - Control - Interface (SCIF) organisiert die vielfältigen
Möglichkeiten der Takterzeugung. Dazu gehören auch die PLLs. Der Power
Manager (PM) wiederum unterstützt die Takterzeugung für die CPU und
verschiedenen Busse. Er wird vom SCIF angetrieben. Nach dem Reset läuft
alles irgendwie - aber nur mit 115 kHz RC-Takt.
Wenn man beim UC3C irgendeine Komponente benutzen möchte, dann muß man
die zielführende taktweiterleitenden Funktion des Power Managers in der
SCIF auswählen. Für das CAN-Interface muß man einerseits die
Takterzeugung für das Peripherie-Modul selbst aktivieren. Damit meine
ich z. B. die Logistik-Logik, die die Ergebnisse in den RAM schreibt
oder liest, etc.
Dann braucht man noch eine Generic Clock. Und zwar die GCLK1. Sie
erzeugt den Takt für die TimeQuanta. Das war beim AT90CAN128 insofern
einfacher, weil der Systemtakt sowohl für die Logik als auch für
Signalerzeugung herangezogen wurde.
Nur so nebenbei. Beide Knoten CAN 1 und CAN 2 laufen dann immer mit der
gleiche Zeitbasis. Also das Erzeugen eines Gateways mit
unterschiedlichen CAN-Taktraten geht mit diesem Prozessor nicht. Gut ich
habe auch noch nicht alles gelesen. Ich will mich da nicht zu weit aus
dem Fenster hängen. Aber die Support- Ings. von Atmel bei einem Seminar
in Hannover haben mir ausweichend geantwortet.
Die GCLK0 bezieht ihren Takt u. a. von den Taktquellen des PMs. D. h.
damit bei CAN-Knoten überhaupt etwas rauskommt, muss in dem SCIF die
GCLK0 aktiviert sein. Wenn das nicht der Fall ist und man bei Senden auf
das "Message ist raus - Bit" in einer While-Schleife wartet, dann hängt
sich der Prozessor auf. Eigentlich wartet er auf etwas, was niemals
eintreten wird. Das ist im ASF unvorteilhaft gelöst. Aber das ist
natürliche eine Philosophiefragen. Ich strebe lieber den schwierigeren
aber nachhaltigeren Weg an.
In den Beispielen haben die Norweger das fast immer berücksichtigt. Nur
in den Quellen ist das bescheiden dokumentiert. Und dann sucht man sich
einen Wolf oder legt das Teil entnervt beiseite.
Im Grunde bin ich ein Atmel - Fan und deshalb wurmt es mich, dass es
nicht läuft. Aus diesem Grund habe ich noch nicht aufgegeben. Aber die
grosse Rechenleistung des UC3C konnte ich noch nicht positionieren.
Mein Ziel ist es einen lowpower CAN-Data-Logger auf SD-Karte zu
programmieren. Außerdem will ich ein Target für den Embedded Coder in
Matlab/Simulink aufsetzen. Für den AT90CAN128 und einige ATmegas läuft
das bereits.
So Simon, vielleicht ist in dem Geschriebenen die Lösung für Dein
Problem enthalten. Mach ein paar Diffs mit Projekten, wo es funktiniert.
Damit kam ich zum Ziel.
Übrigens, was benutzt Du, um Dein gesendetes Signal zu Bestätigen
(Acknowledge)? Falls Du nichts benutzt, könnte auch das das Problem
sein. Bei CAN sollte ein Sender immer einen Zuhörer haben. Sonst gibt es
einen Acknowledge-Fehler. Den kann man ignorieren. Aber das muss man
dann auch einstellen.
Bis dann.
Carsten
Simon schrieb:> Leider hängt sich das Programm nach einmaligem Senden sofort auf.
Was bedeutet "aufhängen"?
> Ich konnte den Fehler soweit eingrenzen, dass beim Senden kein Fehler> auftritt wenn ich die Funktion CANIF_mob_enable_interrupt(ch,handle)> herausnehme. Diese ist in CAN_tx() hinterlegt und sorgt für einen> Interruptaufruf des MessageObjects.
Dann setz doch mal einen Break-Point in die ISR und schau, was dort
passiert.
Wird das Interrupt-Request-Flag zurückgesetzt? Ansonsten wird die CPU
endlos diese ISR anspringen.
Hallo,
ich benutze gerade auch der AT32UC3C0512C, um eine CAN-Kommunikation
aufzubauen. Der CAN-Netzwerke sollte aus zwei CAN-Knoten bestehen, die
Daten untereinander tauschen. Als erste Schritt, habe ich das UC3C CAN
and LIN Loopback Beispiel so geändert, dass ein CAN-Kanal Daten
periodisch senden und empfangen kann. Die beiden CAN-Kanäle senden und
empfangen Nachrichten, aber nach einer gewissen Zeit, hängt das
Programm. Das Programm ist im Anhang angehängt. Ich wäre über Ihre Hilfe
dankbar.
Laura
Laura M. schrieb:> aber nach einer gewissen Zeit, hängt das> Programm.
Hallo Laura,
wie lange ist den die gewisse Zeit?
Wie häufig sendest Du pro Sekunde?
Verläuft die Kommunikation fehlerfrei?
Kannst Du debuggen? -> Fehlerzähler überprüfen.
...
Hallo,
ich habe ein Timer in der Code hinzugefügt und benutzt diesem, um
Botschaften jedes 100 ms zu senden. Die Kommunikation verläuft
fehlerfrei. Das Programm läuft für ungefähr 1 Minute. Ich könnte
debuggen, hatte aber bis jetzt nicht auf der Fehlerzähler geguckt. ich
werde es anschauen. Was noch erstaunlich bei der Debugging, war der
Tatsache, dass nach der Allokation der 15 MOBs, der Debugger das
Debuggen stoppt.
So Laura,
habe mal schnell drüber geschaut.
1. Warum kommentiert Du so gar nichts? Damit machst Du das Programm auch
für Dich nicht wartbar.
Dann habe ich folgendes in der can_task.c gefunden:
// Check return if no mob are available
if (pCANMOB_message0[0].handle==CAN_CMD_REFUSED)
{
while(true);
}
Sollte Deine Programm, warum auch immer in diesen then-Zweig geraten,
dann bleibt das Programm stehen, weil es nie wieder aus der
while-schleife herauskommen. Außer mit einem Reset natürlich.
Was bezweckst Du mit dem Timer?
Ja Du willst etwas schedulen. Aber wieso reicht da nicht die Verzögerung
(Delay)?
Willst Du eine Task-Parallelisierung umsetzen?
Wo hast Du 15 Messageobjekte programmiert?
Der Entscheider in der Interrupt-Routine
switch(msg_to_send)
{
case 0:
can_example_prepare_data_to_send1();
msg_to_send = 1;
break;
case 1:
can_example_prepare_data_to_receive0();
msg_to_send = 0;
break;
case 2:
can_example_prepare_data_to_send0();
msg_to_send = 3;
break;
case 3:
can_example_prepare_data_to_receive1();
msg_to_send = 0;
break;
default:
break;
}
wird nur zw. 0 und 1 hin und herschalten.
Ist das so beabsichtigt?
Laura tue Dir den Gefallen und kommentiere mehr. Mann kann nur ahnen was
Du vor hast.
...
Hallo cskulkw,
vielen Dank für die Tipps,
ich habe folgendes kommentiert
if (pCANMOB_message0[0].handle==CAN_CMD_REFUSED)
{
while(true);
}
die 15Message Object habe ich in der can_task.c datei deklariert(die
Deklaration steht ganz oben nach die Include):
//! Local Mob Declaration
can_msg_t mob_ram_ch0[NB_MOB_CHANNEL];
can_msg_t mob_ram_ch1[NB_MOB_CHANNEL];
eigentlich ich wollte eine CAN-Nachricht jede 100 ms senden oder
empfangen und habe mich einfach für einen Timer entschieden. Der Timer
soll jeder 100 ms, ein Interrupt auflösen.
Ich habe auch inzwischen der ISR so geändert:
switch(msg_to_send)
{
case 0:
send1 = true;
msg_to_send = 1;
break;
case 1:
rcv0 = true;
msg_to_send = 2;
break;
case 2:
send0 = true
msg_to_send = 3;
break;
case 3:
rcv1 = true;
msg_to_send = 0;
break;
default:
break;
}
und der can_task
void can_task(void)
{
if(send1)
{
can_example_prepare_data_to_send1();
send1 = false;
}
if(rcv0)
{
can_example_prepare_data_to_receive0();
rcv0 = false;
}
if(send0)
{
can_example_prepare_data_to_send0();
send0 = false;
}
if(rcv1)
{
can_example_prepare_data_to_receive1();
rcv1 = false;
}
}
Das Programm sollte so verlaufen, dass der CAN-Kanal1 mit der Funktion
can_example_prepare_data_to_send1 eine Botschaft an dem CAN-Kanal0
sendet.Die wird dann mit der Funktion
can_example_prepare_data_to_receive0()empfangen. CAN-Kanal0 nach Empfang
der Nachricht, sendet (can_example_prepare_data_to_send0()) wiederum
eine Nachricht an der Kanal1(can_example_prepare_data_to_receive1)). Das
Programm läuft für ungefähr eine Minute und danach bleibt hängen.
Ich hoffe ich könnte besser erklären, was ich vorhabe
Bis dann
Laura
Moin Laura,
sorry dass ich mich erst jetzt melde.
Ich hatte das so verstanden, dass Du 15 (unterschiedliche) Botschaften
von Kanal 0 nach Kanal 1 senden wolltest.
Aber das machst Du definitiv nicht, weil ich in der Konfiguration nur
zwei Botschafts-ID gefunden habe:
can_msg_t msg_tx_sot =
{
{
{
.id = 0x133, // Identifier
.id_mask = 0x1ff, // Mask
},
},
.data.u64 = 0x0108LL, // Data
};
#endif
can_msg_t msg_tx_3C7 =
{
{
{
.id = 0x3C7, // Identifier
.id_mask = 0x3ff, // Mask
},
},
.data.u64 = 0x1987LL, // Data
};
Das sind einmal die 0x133 und Deine 0x3C7.
Also,
in der ASF-Demo steht folgendes:
can_mob_t pCANMOB_message2[1] = {
...........................^
{CAN_MOB_NOT_ALLOCATED,&msg_rx_listening,0,CAN_DATA_FRAME,CAN_STATUS_NOT
_COMPLETED}
};
Und Du hast das hier geschrieben:
can_mob_t pCANMOB_message2[5] = {
...........................^
{CAN_MOB_NOT_ALLOCATED,&msg_rx_listening,0,CAN_DATA_FRAME,CAN_STATUS_NOT
_COMPLETED}
};
Zweites Problem:
Wenn Deine State-Machine funktioniert, dann würdest Du immer und immer
wieder die can_init aufrufen und versuchen MessageObjekte zu allozieren.
Der UC3C hat nur 32. Irgendwann sind die voll. Und genau hier kann es
passieren, dass er in die Abfrage meines ersten Kommentars geraten kann.
Die Funktion can_out_callback_channelx wird nirgends aufgerufen.
Ich wiederhole gern meine Frage, was willst Du erreichen?
Was Du hier programmiert hast, zeigt, dass Du weder das CAN-Interface
des UC3C noch das ASF mit seiner Implementierung nicht richtig
verstanden hast.
Bitte fasse das jetzt nicht als Arroganz auf. Aber ein CAN-Interface ist
schwierig zu benutzen. Darum verwenden die meisten Hobbyprogrammierer
die Bibliothek vom creativen-chaos.
Hast Du einen CAN-Loger? Damit Du überhaupt sehen kannst, ob da was aus
dem Controler herauskommt? Oder gehst Du davon aus, dass alles richtig
sein muß, wenn Du den Empfänger abfragst?
...
Hallo cskulkw,
ich habe ein CANcaseXL mit einer CANoe Lizenz.
Die Arbeit habe ich in drei Schritte gemacht:
1 Schritt:
Ich habe von CAN-Kanal1 die Nachricht 0x133 an der CANcaseXL gesendet.
Ich könnte mit CANoe überprüfen, dass die Nachricht tatsächlich gesendet
wird. Nach ungefähr 30 Minuten, habe ich dann das Programm abgebrochen.
2 Schritt:
Mit dem CAN-Kanal0 habe ich die Nachricht 0x3C7 an der CANcaseXL
geschickt. Die wurde auch fehlerfrei von der CANcaseXL empfangen(könnte
es mit CANoe bestätigen).
3 Schritt.
Da die Übertragung von CAN-Nachrichten durch die beiden Kanäle
fehlerfrei lief, wollte ich also der Empfang von CAN-Nachrichten
überprüfen.
Aus diesem Grund habe ich dann die funktion
can_example_prepare_data_to_receive1() und
can_example_prepare_data_to_receive0 in der Code hinzugefügt. Ich möchte
einfach überprüfen, dass die beiden Kanäle auch CAN-Nachrichten
fehlerfrei empfangen können. Deswegen versuche ich
CAN-Nachrichten(0x133) von Kanal1 an Kanal 0 zu senden. Ebenso versuche
ich die CAN-Nachricht(0x3C7) von Kanal0 an Kanal1 zu senden. Ich
versuche nicht 15 verschiedene Nachrichten zu senden. Ich versuche nur
zwei Nachrichten zu senden: 0x133 von kanal1 nach Kanal0 und 0x3C7 von
Kanal0 zum Kanal1.
Ich glaube die Tatsache, dass ich can_mob_t pCANMOB_message2[5]
definiere hat hier keinen großen Einfluss auf das Programm, oder??
Moin Laura,
hatte gestern keine Lust mehr auf dem Handy zu antworten.
Szenario Kanal 0 sendet eine Botschaft mit der CAN-ID 0x3C7 an Kanal 1
1. Ein Messageobjekt (und nur EINS !) in Kanal 0 allozieren und ihm die
CAN-ID 0x3C7 zu weisen. Der Modus muss TX für Senden sein.
2 Ein weiteres Messageobjekt (und auch hier nur EINS und keine FÜNF !)
in Kanal 1 allozieren und ihm ebenfalls die CAN-ID 0x3C7 zuweisen.
Ergänzend dazu die IDM ebenfalls auf 0x3C7 einstellen. Dann ist
sichergestellt, dass der FIlter nur CAN-Botschaften mit dieser Adresse
zuläßt.
3. Mit jedem Senden der Botschaft auf Kanal 0 veränderst Du im Anschluß
die CAN-Daten. Sonst siehst Du nur einen Glücktreffer und kannst ihn
nicht unterscheiden.
4. Jetzt muss der veränderte Dateninhalt im Datenspeicher von Mob 1 des
Kanal 1 zu sehen sein.
5. Ich habe noch einmal im Datenblatt nachgeschaut, weil ich wissen
wollte, ob die Messageobjekte innerhalb eines Kanals priorisiert sind.
Das würde bedeuten, wenn man Objekt 0 bis 4 gleichzeit zum Senden
aktvieren würde, dann würde die Hardware mit dem niedrigsten oder
höchsten Objekt anfangen. Alle weiteren würden der Reihe nach dran
kommen. Bei Senden ist das nachvollziehbar.
6. Bei Empfang habe ich nicht herausgefunden, ob die Priorisierung
ebenfalls funktioniert, wenn mehrere Objekte des gleichen Kanals die
gleiche CAN-ID haben. Das macht man ja eigentlich nicht, weil es
Verschwendung wäre, zwei oder mehrer Messageobjekte mit ein und der
selben ID zu belegen. Und deshalb reite ich so auf der 5 beim
Empfangsspeicher herum. Es könnte sein, dass die Hardware einen Klemmer
bekommt, weil 5 MessageObjekte sich gleichzeitig auf den empfangenen
Dateninhalt stürzen. Die FOlge könnte der Dead-Lock sein.
7. Also, wenn Du das jetzt änderst und der Klemmer tritt wieder auf.
Dann gebe ich mich geschlagen. Dann ist es was anderes. Das mußt Du dann
selbst herausfinden.
8. Und da die bei ATMEL einen schlechten Support haben und gern
pfuschen, weil alles billig in der Produktion aber teuer im Verkauf sein
muß, würde es mich nicht wundern, wenn da noch ein Fehler im CHip
vorliegt.
9. Ach und weil Du eine halbe Stunde mit CANoe die Botschaft 0x133
empfangen haben willst, scheint Dein Klemmer ja offensichtlich nicht
mehr vorzuliegen.
Ich wünsche Dir noch viel Erfolg. Genügend Hinweise habe ich Dir
gegeben.
...
Hallo cskulkw,
vielen Dank für die Hinweise. Die Habe ich eingesetzt und könnte schon
etwas zum Laufen bringen(siehe Abbildung 1 und 2). Jetzt habe ich dann
weiter versucht die Kommunikation wie es auf die
Abbildung(Abbildung.GIF) zu sehen programmiert. Aber beim Debuggen, habe
ich festgestellt, das die beiden Kanäle Daten senden, aber nichts wird
empfangen. Ich wäre über Vorschläge sehr dankbar.
ich habe zur Zeit auch das Problem mit dem CANIF des UC3C, dass mit
jedem Kanal nur die Message Objekte 0-15 gesendet werden können.
Danach findet kein weiteres Senden statt.
an welcher Stelle müssen die MOB wieder freigegeben werden, damit sie
erneut verwendet werden können?