Interrupt-Problem beim C167

Gast #2611244
Lesenswert?

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
void main (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     = (unsigned int)6250;            /* Taktzeit 20 ms */
53
 CAPREL = (unsigned int)6250;            /* Taktzeit als Reload-Wert */
54
 T6CON  = 0x80C4;                        /* binaer : 1 0000 00 011 000 100 */
55
 T6IC   = 0x39;                          // Einstellen des Interruptlevels fuer Takt-Interrupt : enable, Level 14, Gruppenlevel 1 */39
56
 T6IE   = 1;                             /* Interrupt enablen */
57

58
  /*
59
   * Watchdog-Timer hier nochmals bedienen
60
   */
61
  WDTsrv();
62

63
 /* CAN steht zur Verfuegung */
64
 C167.CAN_rdy = TRUE;
65

66
  /*
67
   * Port 3.0 schaltet Flashlights
68
   * (Output, Push/Pull, passiv)
69
   */
70
  _putbit(1,DP3,0);
71
  _putbit(0,ODP3,0);
72
  _putbit(0,P3,0);
73

74
  /*
75
   * Port 3.1 schaltet Starkhorn
76
   * (Output, Push/Pull, passiv)
77
   */
78
  _putbit(1,DP3,1);
79
  _putbit(0,ODP3,1);
80
  _putbit(0,P3,1);
81

82
  /*
83
   * Port 3.2 schaltet LED-Matrix Bild 1
84
   * (Output, Push/Pull, passiv)
85
   */
86
  _putbit(1,DP3,2);
87
  _putbit(0,ODP3,2);
88
  _putbit(0,P3,2);
89

90
  /*
91
   * Port 3.3 schaltet LED-Matrix Bild 2
92
   * (Output, Push/Pull, passiv)
93
   */
94
  _putbit(1,DP3,3);
95
  _putbit(0,ODP3,3);
96
  _putbit(0,P3,3);
97

98
  /* Interrupts zulassen */
99
  IEN = 1;
100

101
 /* Hauptschleife */
102
 while (1)
103
 {
104
 ;
105
 }
106
}
Die Interrupt-Routine, welche ausgeführt werden soll sieht so aus.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <reg167cs.h>
4
#include "can_ext.h"
5
#include "global.h"
6

7
interrupt 0x26
8
void TAKT(void) {
9

10
  unsigned int t6ic_alt = 0;
11
  //static int counter = 1;
12

13
  /* waehrend der Abarbeitung keinen neuen Interrupt zulassen */
14
  t6ic_alt = T6IC;
15
  T6IC = 0;
16

17

18
/*  if (counter < 100)
19
    counter++;
20
  else
21
    counter = 1;
22
*/
23

24
  //if(counter%2==0) { // alle 20 ms; Taktung: 10 ms (Timer 6)
25

26
    vRel = vEigen - vZielUebergabe;  // Relativgeschwindigkeit berechenen
27
    vZiel = vEigen + vRel;      // Tatsächtiche Zielgeschwindigkeit
28

29
    aEigen = (vEigen - vEigenVortakt) * (1000 / taktzeit); //Eigenbeschleunigung
30
    aZiel = (vZiel - vZielVortakt) * (1000 / taktzeit);    // Zielbeschleunigung
31

32
    aRel = aZiel - aEigen;    // Relativbeschleunigung
33
    aRelMax = -800 - aEigen;  // Maximale Relativbeschleunigung
34

35
    dReferenz1 = vEigen * vEigen * 7 / 12500;  // Referenzabstand für die 1. Warnstufe [cm/s]
36
    dReferenz2 = vEigen * vEigen / 2500;      // Referenzabstand für die 2. Warnstufe [cm/s]
37

38
    radikand = vRel * vRel + aRel * abstand * 2;    // Wurzelberechnung
39
    wurzel = isqrt_heron(radikand);            // Wurzelberechnung
40
    tBrems1 = ((vRel * 1000 / - aRelMax) / 2) + 1600 + 2000;  // Bremszeit1; Vergleichszeit Stufe 1
41
    tBrems2 = ((vRel * 1000 / - aRelMax) / 2) + 1600;       // Bremszeit2; Vergleichszeit Stufe 2
42
    ttcBesch = (wurzel - vRel) * 1000 / aRel;
43
    ttcConst = (abstand / vRel) * 1000;
44

45
    switch (sensorAus)  {
46

47
      case 1:  fehlerIDIS(); break;  // IDIS hat sich abgeschaltet
48

49
      default :
50

51
               if (aRelMax >= 0) {    // Das Egofahrzeug führt eine Notbremsung durch
52

53
                  notbremsung();
54

55
               }// else if (vRel < -100 && aRelMax < 0) {}      // Ziel entfernt sich
56

57
                 else if (vRel >= -100 && vRel <= 100 && aRelMax < 0) {  // Ziel folgt
58

59
                 if (abstand <= dReferenz2) stufe2();
60

61
                 if (abstand <= dReferenz1 && abstand > dReferenz2) stufe1();
62

63
                 //if (abstand > dReferenz1) allesOk();
64

65
               } else {    // Ziel fährt auf
66

67
                 if (vRel * vRel >= - aRel * abstand * 2 && aRel != 0 && aRelMax < 0) {    // TTC mit beschleunigten Fahrzeugen
68

69
                   if (ttcBesch <= tBrems2 && ttcBesch > 0) stufe2();
70

71
                   if (ttcBesch > tBrems2 && ttcBesch <= tBrems1) stufe1();
72

73
                   //if (ttcBesch > tBrems1 || ttc < 0) allesOk();
74

75
                 } else if (aRel == 0 && aRelMax < 0) {    // Keine Relativbeschleunigung --> Formel für unbeschleunigte Bewegung
76

77
                   if (ttcConst <= tBrems2) stufe2();
78

79
                   if (ttcConst > tBrems2 && ttcConst <= tBrems1) stufe1();
80

81
                   //if (ttcConst > tBrems1) allesOk();
82

83
                 }
84
    }
85

86
    vEigenUebergabe = vEigen * 36 / 100;  // Umrechnung der Einheiten und Auflösung für IDIS
87

88
    daten[0] = (gierrate&0x00FF);
89
    daten[1] = ((gierrate&0xFF00)>>8);
90
    daten[2] = (vEigenUebergabe&0x00FF);
91
    daten[3] = ((vEigenUebergabe&0xFF00)>>8);
92
    daten[4] = (lenkwinkel&0x00FF);
93
    daten[5] = ((lenkwinkel&0xFF00)>>8);
94
    daten[6] = (bremslicht);
95
    daten[7] = 0;
96

97
    def_mo_16x(0,14, 0, 0x333, 1, 8, 0, 0);
98
    ld_modata_16x(0,14, (unsigned char*)&daten);
99
    send_mo_16x(0,14);
100

101
    }
102
  //counter++;
103
  vZielVortakt = vZiel;
104
  vEigenVortakt = vEigen;
105

106
  //}
107

108
  T6IC = t6ic_alt; // Interrupt wieder zulassen
109

110
}

Grüße,
Andreas
Gast #2611328
Lesenswert?

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.ä.).
#2611432
Lesenswert?

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
Gast #2612091
Lesenswert?

Andreas schrieb:
> T6IC   = 0x39;                          // Einstellen des Interruptlevels fuer 
Takt-Interrupt : enable, Level 14, Gruppenlevel 1 */39
>  T6IE   = 1;                             /* Interrupt enablen */

ersetze die beiden Anweisungen gegen
1
T6IC = 0x79;

ach ja, in der ISR kannst du den Interrupt mit dem T6IE ein- und 
ausplanen.
#2612306
Lesenswert?

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...
#2612344
Lesenswert?

> 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?
#2612472
Lesenswert?

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!
#2613471
Lesenswert?

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.
Gast #2613852
Lesenswert?

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.
#2615357
Lesenswert?

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?
Gast #2615991
Lesenswert?

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:
1
tBrems1 = (((long)vRel * (long)1000 / - aRelMax) / 2) + 1600 + 2000;
wobei ein cast genügen würde.
#3265831
Lesenswert?

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 ?
Gast #3266935
Lesenswert?

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

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