Forum: Mikrocontroller und Digitale Elektronik CAN-Kommunikation mit AT32UC3C0512C


von Simon (Gast)


Angehängte Dateien:

Lesenswert?

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

von René Z. (dens)


Lesenswert?


von acryl (Gast)


Lesenswert?

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

von Simon (Gast)


Lesenswert?

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.

von cskulkw (Gast)


Lesenswert?

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?

von Simon (Gast)


Lesenswert?

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!

von cskulkw (Gast)


Lesenswert?

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

von Bronco (Gast)


Lesenswert?

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.

von Laura M. (laura21)


Angehängte Dateien:

Lesenswert?

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

von cskulkw (Gast)


Lesenswert?

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.

...

von Laura M. (laura21)


Lesenswert?

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.

von cskulkw (Gast)


Lesenswert?

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.

...

von Laura M. (laura21)


Lesenswert?

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

von cskulkw (Gast)


Lesenswert?

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?

...

von Laura M. (laura21)


Lesenswert?

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

von cskulkw (Gast)


Lesenswert?

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.

...

von Laura M. (laura21)


Angehängte Dateien:

Lesenswert?

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.

von Laura M. (laura21)


Lesenswert?

Aufgabe gelöst

von Mario (Gast)


Lesenswert?

Hallo Laura,
kannst du bitte dein funktionierendes Projekt hochladen.
Brauche auch einen Starthilfe für CAN.
Danke!

von dionysos 3. (dionysos328)


Lesenswert?

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?

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.