Hallo zusammen!
Ich nutze einen C167CS auf Phytec MiniModul mit dem Tasking Compiler.
Mein Programm soll periodisch (alle 20 ms) Ports (3.0-3.3) in
Abhängigkeit von CAN-Daten schalten. Dazu nutze ich den Timer T6. Der
Code ist erprobt und sollte eigentlich funktionieren. Mein Problem ist,
dass die Interrupt Routine nicht von T6 nicht ausgelöst wird und ich
nicht dahinter komme, warum. Vielleicht sieht jemand einen Fehler. Ich
habe schon mehrere Tage erfolglos danach gesucht. Mein Main-Programm
sieht wie folgt aus:
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<string.h>
4
#include<reg167.h>
5
#include"can_ext.h"
6
#include"global.h"
7
8
voidmain(void)
9
{
10
11
/* Interrupts zulassen */
12
//IEN = 1;
13
14
/* Watchdog-Timer wurde bereits in cstart initialisiert (watchdog time = 419 ms); hier erstmals bedienen */
15
//WDTsrv();
16
17
/* Voreinstellungen */
18
/* ================ */
19
20
/* CAN-Controller */
21
C167.CAN_fehler=FALSE;
22
C167.CAN_rdy=FALSE;
23
24
/* Taktzeitueberschreitung */
25
C167.zeitfehler=FALSE;
26
27
/* Egofahrzeug-Daten */
28
//EgoFzg.v = 0;
29
//Regler.einschalten = FALSE;
30
31
32
/* Initialisierung der Timer, Interupts, etc. */
33
/* ========================================== */
34
35
/* Initialisieren des kurzen Haupttimers : Timer 3 ist ein 16bit-Timer mit einer Zeitaufloesung von 6.4 us */
36
// Gesamtdurchlaufzeit: 419 ms; raufzählend
37
T3=0;/* Timer 3 auf Null setzen */
38
T3CON=0x44;// binaer : 00 00 1 000 100; 0x44
39
40
/* Watchdog-Timer wurde bereits in cstart initialisiert (watchdog time = 419 ms); hier nochmals bedienen */
41
WDTsrv();
42
43
/* Initialisierung CAN1 und CAN2 mit 500 kBit/s */
44
StartCAN(0);
45
//StartCAN(1);
46
47
/* Watchdog-Timer wurde bereits in cstart initialisiert (watchdog time = 419 ms); hier nochmals bedienen */
48
WDTsrv();
49
50
/* Takt-Timer initialisieren : Timer 6 ist ein 16-bit Timer mit einer Zeitaufloesung von 3.2 us */
51
T6CON=0;/* Timer 6 stoppen */
52
T6=(unsignedint)6250;/* Taktzeit 20 ms */
53
CAPREL=(unsignedint)6250;/* Taktzeit als Reload-Wert */
Also. Ich bin mir 99% sicher, dass Du das Interrupt-Flag nicht sichern
und
rücksetzen musst. Das erledigt für dich entweder der µC oder der
Compiler.
Lösungsvorschlag zu Deinem Problem: Hast Du die Interrupts (sinnvoll)
priorisiert (habe die Konfig oben nicht näher untersucht)?
Sind die Timer soweit hardwareseitig aktiviert (schau mal in Deine
Startup-Konfiguration) und rennt Timer6 überhaupt?
Ansonsten baue Dir ein kleines Test-Projekt, in dem Du ohne viel
Beeinflussung den Fehler finden kannst (mit Timer6 z.B. eine LED
im Sekundenrhythmus toggeln, o.ä.).
sdfgq5zg schrieb:> Also. Ich bin mir 99% sicher, dass Du das Interrupt-Flag nicht sichern> und> rücksetzen musst. Das erledigt für dich entweder der µC oder der> Compiler.>> Lösungsvorschlag zu Deinem Problem: Hast Du die Interrupts (sinnvoll)> priorisiert (habe die Konfig oben nicht näher untersucht)?> Sind die Timer soweit hardwareseitig aktiviert (schau mal in Deine> Startup-Konfiguration) und rennt Timer6 überhaupt?>> Ansonsten baue Dir ein kleines Test-Projekt, in dem Du ohne viel> Beeinflussung den Fehler finden kannst (mit Timer6 z.B. eine LED> im Sekundenrhythmus toggeln, o.ä.).
Danke für die schnellen Antworten!
Hab jetzt mit der Prüfung einzelner Segmente angefangen. Kenntnisstand
bis jetzt: Timer laufen, und zwar richtig. Überhaupt, habe ich
hardwareseitig schon alles doppelt und dreifach geprüft. Ich glaub, dass
was übersehe...
Guido schrieb:> In der while-Schleife wird der Watchdog doch nicht bedient.> Macht der die Probleme?
Watchdog ist es nicht. Habe ihn schon mal stillgelegt, ohne Ergebnis.
Außerdem ist er auf 419 ms eingestellt, deshalb denke ich nicht, dass er
hier Probleme macht. Aber danke für den Tipp!
Grüße,
Andreas
Das IC Register zu sichern und nachher wieder zu schreiben macht genau 0
Sinn. Du solltest das IR Flag zurücksetzen in der Interruptroutine,
sonst nichts.
sdfgq5zg schrieb:> Ist das beim Tasking-Compiler wirklich so:
Ja, es ist so. Anders spuckt der Compiler einen Fehler aus.
Steel schrieb:> Das IC Register zu sichern und nachher wieder zu schreiben macht genau 0> Sinn. Du solltest das IR Flag zurücksetzen in der Interruptroutine,> sonst nichts.
Ok, mach ich. Obwohl ich vermute, dass das nicht der Grund für mein
Leiden ist...
Pipeline schrieb:> ersetze die beiden Anweisungen gegenT6IC = 0x79;
Das habe ich der Übersichtlichkeitshalber gemacht. So kann ich den Timer
stilllegen, ohne jedes mal binär in hex umzurechnen.
Pipeline schrieb:> ach ja, in der ISR kannst du den Interrupt mit dem T6IE ein- und> ausplanen.
Wie oben angemerkt, werde ich es gleich mal versuchen...
> Das IC Register zu sichern und nachher wieder zu schreiben macht genau 0> Sinn.
Richtig! Der Interrupt unterbricht sich nicht selbst! Alle Interrupts
mit gleichem oder niedrigerem Level unterbrechen diesen Interrupt nicht.
Das IR Bit wird automatisch vom Prozessor zurückgesetzt.
In Deinem hier gezeigtem Code wird der Watchdog tatsächlich nicht
bedient, allerdings gehört ja noch weiterer Code dazu, in dem der
Watchdog wahrscheinlich bedient wird? Zum Testen würde ich den Watchdog
definitiv erst mal ausschalten.
Wo werden denn die Port 3 Pins geschaltet und wie sieht der Code dazu
aus?
So, anscheinend habe ich (zumindest) eine Stelle lokalisieren können.
Anscheinend geht der Interrupt. Da ich die Bedungungen durch Variablen
festlegen kann, habe ich eine speziellen Fall erzeugt, und zwar: Ziel
folgt mit abstand <= dReferenz2. Bei der Berechnung von dReferenz2
stockt er. Das Problem liegt bei "vEigen * vEigen". Das kriegt er
irgendwie nicht gebacken. Ersetze ich vEigen durch den Wert, z.B. 2400 -
läuft es. Es funktioniert auch, wenn ich eine Zwischenvariable
deklariere und mit der weiter rechne. Also nochmal zusammengefasst:
1
vEigen=2400;
2
dReferenz1=vEigen*vEigen/2500;// geht NICHT!
3
4
dReferenz1=2400*2400/2500;// geht!
5
6
vEigen=2400;
7
bla=vEigen*vEigen;
8
dReferenz1=bla/2500;// geht!
Ich verstehe überhaupt nicht, wie das kommt! In meinen Augen ist das
unlogisch!
B. Jue schrieb:> Als was sind die Variablen deklariert? Integer?> Passt das Ergebnis nicht in ein Integer gibt es Probleme...
Ja, sind alle Integer. Für die Berechnung sollte das ja reichen. Was
mich wundert, ist das es mit einer Zwischenvariablen funktioniert...
B. Jue schrieb:> Als was sind die Variablen deklariert? Integer?> Passt das Ergebnis nicht in ein Integer gibt es Probleme...
War doch die Deklaration! Einige Variablen sind überlaufen. Vielen Dank
für den Hinweis. Ich hoffe, das jetzt Ruhe ist! =)
Andreas H. schrieb:> Ja, sind alle Integer. Für die Berechnung sollte das ja reichen.Andreas H. schrieb:> vEigen = 2400;> dReferenz1 = vEigen*vEigen/2500;
Frage: Wieviel sind 2400*2400?
Antwort: ;-)
Andreas H. schrieb:> Anscheinend geht der Interrupt.
Wie debugst du eigentlich?
Pipeline schrieb:> Frage: Wieviel sind 2400*2400?> Antwort: ;-)
Jaja=), unter Windows/Linux ist int meist ausreichend. Natürlich ist es
bei einem 16-Bit uC anders... Hab ja schon vermutet, dass ich irgendwo
gut auf dem Schlauch gestanden habe.
Pipeline schrieb:> Wie debugst du eigentlich?
Das Debuggen ist recht abenteuerlich. Entweder spreche ich Ports an,
oder schick mir über CAN was. Richtiges Debuggen geht nicht, weil ich
den Tasking nur im Rahmen des Minimodul-Pakets nutzen kann. Das bedeutet
compiliren --> flashen --> gucken.
Wenn ich zwei 16-Bit-Integers multipliziere und in eine
16-Bit-Integervariable ablege, dürfte ich gar keine Probleme mit dem
Überlauf haben. Das Resultat mag nicht das sein, was man erwartet (obere
16Bit abgeschnitten), das wird aber keinen Interrupt verhindern.
Habe gerade festgestellt, dass temporären Variablen auch alle int sind.
Wie Caste ich die denn richtig?
1
tBrems1=((vRel*1000/-aRelMax)/2)+1600+2000;
Hier liegt das Problem in "vRel*1000", wobei vRel auch 1000 gesetzt ist.
Als Antwort bekomme ich da ungefähr 16000 raus. Casten mit
(long)(vRel*1000) funktioniert nicht... Weiß jemand Rat?
Andreas H. schrieb:> Casten mit> (long)(vRel*1000) funktioniert nicht...
kann auch nicht, da du mit 16Bit rechnest und das übergelaufende Ergbnis
auf 32Bit erweiterst. Du möchtest aber mit 32Bit rechnen.
Andreas H. schrieb:> tBrems1 = ((vRel * 1000 / - aRelMax) / 2) + 1600 + 2000;
mal ungeprüft aus der hohlen Hand:
Hallo Andreas,
Ich bin Modellbahner mit einer mittelgroßen µC gesteurten Anlage.
Der µC SAB88C166 ist verreckt und nicht mehr erhältlich.
Als Ersatzoption sehe ich das Phytec Minimodul 167, das ich aus einen
Restposten günstig erwerben kann.
Ich bin Grufti und mit µCs nicht vertraut.
ICh hätte jetzt 2 Fragen
1. Hast Du einen Schltplan vom Minimodul 167, den Du mir als PDF
zumailen kannst? e,falke@web.de
2. Was für Geräte braucht man für das Programmiern des Moduls und seiner
Flash Eproms und würdest Du mir dabei ggffls. helfen ?
Hallo Edgar. Ich bin zur Zeit nicht in DE. Ich schaue in meiner
Dokumentation, wenn ich wieder zurück bin. Meine Erfahrungen mit dem
C167 habe ich im Rahmen meiner Diplomarbeit gemacht. Die liegt aber
schon was zurück. :)
Grüße
Andreas