PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C-Programm auf XC866 'verzählt' sich



Ampfing
09.05.2005, 13:13
Hallo zusammen,

ich habe in etwas komplexeres Problem.
Ich möchte einem Microcontroller vom Typ Infineon XC866 von einem Rechner mit W2k über eine 8-Bit-Verbindung insgesamt 5 Byte übermitteln. Dazu hat der Rechner eine GPIB-Interfacekarte. Vor dem Controller hängt das Gegenstück zu dieser Karte. Sprich, wenn ich im Programm auf dem Rechner sage, ich möchte das 2. Bit im 5.Byte der GPIB-Nachricht setzen wird eine bestimmte Leitung an der Karte vor dem Controller auf high gezogen.
So habe ich also meine 8 Bitleitungen von der Karte an den Controller verdrahtet. Eine 9. Leitung benutze ich, um dem Controller mit einer steigenden Flanke zu singalisieren, dass jetzt 8 Bit anliegen und er diese bitte 'abholen' soll. Auf die steigende Flanke reagiere ich mit einem Interrupt.

Im folgenden also meine Interrupt Service Routine (ISR) für die 9. Leitung:


void TriggerISR() interrupt 8
{
IRCON0 &= 0xfb; //reset IR-Bit of trigger

switch (counter)
{
case 0:
time1 = P3_DATA; //get LSB of time
if (time1 == 0)
{
P0_DATA &= 0xf8;
P0_DATA |= 1;
}
else
{
if (time1 == 1)
{
P0_DATA &= 0xf8;
P0_DATA |= 2;
}
}
break;

case 1:
time2 = P3_DATA; //get 2nd byte of time
if (time2 == 0)
{
P0_DATA &= 0xf8;
P0_DATA |= 0x3;
}
else
{
if (time2 == 1)
{
P0_DATA &= 0xf8;
P0_DATA |= 0x4;
}
}
break;

case 2:
time3 = P3_DATA; //get MSB of time
if (time3 == 0)
{
P0_DATA &= 0xf8;
P0_DATA |= 0x1;
}
else
{
if (time3 == 13)
{
P0_DATA &= 0xf8;
P0_DATA |= 0x7;
}
}
break;

case 3:
phase = P3_DATA; //get phase information
if (phase == 0)
{
P0_DATA &= 0xf8;
P0_DATA |= 0x6;
}
else
{
if (phase == 128)
{
P0_DATA &= 0xf8;
P0_DATA |= 0x1;
}
}
break;

case 4:
switch (P3_DATA)
{
case 0:
usePhase = 0; //-> phase ignored
mainc = 0; //use serial contactors
break;
case 1:
usePhase = 1; //-> phase important
mainc = 0; //use serial contactors
break;
case 2:
usePhase = 0; //-> phase ignored
mainc = 1; //use main contactor
break;
case 3:
usePhase = 1; //-> phase important
mainc = 1; //use main contactor
break;
}
break;
}
counter++;
}


Dabei stellt P3_DATA meine 8 Eingänge dar, an denen die Bytes empfangen werden sollen. An P0.0 bis P0.2 hängen drei high-aktive Dioden, die ich angebracht habe, damit ich mir anzeigen lassen kann, an welcher Stelle im Programm ich bin (debuggen geht leider nicht!).
Und nun mein Problem:
Wenn ich eine Byte-Kombination übergebe, die in den if-else-Blöcken abgefangen wird funktioniert alles wunderbar. Wenn ich dagegen eine Kombination übergebe, die nicht in den ersten if-else-Block reingeht springt er mir anscheinend über den zweiten break drüber (Vermutung!) und macht auch gleich noch den case 2 mit.
Anschaulich heißt das:
1. Byte = 1
2. Byte = 0
3. Byte = 13
4. Byte = 0
5. Byte = 2
--> alles passt!

1. Byte = 2
alle anderen Bytes sind egal, er macht mir, sobald ich das zweite Byte übermittle (z.B. ne 0) zuerst ganz kurz die Dioden für die 3 an, anschließend sofort die Diode für die 1!

1. Byte = 1
2. Byte = 2
3. Byte = 13
4. Byte = 0
5. Byte = 2
--> alles passt!!!

Ich hoffe mal, ihr versteht was ich meine. Wenn nicht fragt bitte nach, dann versuche ich es auf eine andere Art zu erklären.

Was ich schon alles versucht habe:
1. In den verschiedenen cases jeweils den counter auf die nächste Zahl zu setzen (statt counter++ am Ende)
2. In den if-else-Blöcken eine else im if, mit einem return (damit er auch sicher aus der Funktion aussteigt)
3. einen anderen Interrupt zu nehmen
4. den switch durch 5-if-Abfragen zu ersetzen
5. die if-else-Blöcke durch switch mit default-Zweig zu ersetzen
Hat leider alles nichts gebracht!

Wieso reagiert das Programm falsch, wenn der erste Wert nicht im if-else-Block abgefangen wird???

Ich hoffe mal, ihr könnt mir helfen, bin echt schon am verzweifeln!
Danke fürs lesen und viele Grüße

PicNick
09.05.2005, 15:15
Verflixte Sache.
Setz den Interrupt erst am Ende zurück
Mach den Reset auf die Led nur EINMAL und zwar vor dem Switch.
D.h es leuchtet nur was, wenn irgendwas aufgeht.
Wenn du das Strobe-Signal einzeln setzen kannst, laß' mal die ganze "if"-erei weg uns zeig mit den LED nur 1,2,3,4,.,, für den Counter (binär, logo)
Der Strobe u. Counter sollten ja schön der Reihe nach kommen.
Wenn das nicht geht, geht sonst auch nix
Kommen die Strobes zu schnell, dann setzt immer nur bei einer Zahl eine Led (als Trap)
--> Es muß mal sicher sein, daß das Zählen funzt, dann geht's erst weiter.
Es ist zwar reiner Schamanismus, aber schreib in die Switches am Ender jeweils den "default: break;" dazu, nur damit's keine Ausreden gibt.
fürs Erste

Ampfing
10.05.2005, 07:52
Guten Morgen,

danke für die schnelle Antwort! Bin gestern nur nicht mehr dazu gekommen noch weiter zu basteln.
Hier also meine Erkenntnisse von heute:
Ich habe die ganzen if-else-Abfragen auskommentiert, das IR-Bit erst am Ende der ISR rückgesetzt und den Counter an P0 ausgegeben. Und jetzt wirds richtig mysteriös:
Wenn ich eine Kombination übergebe, die VORHER im if-else des 1. Bytes abgefangen wurde geht alles gut, er zählt ganz normal bis 5 hoch und ich bin glücklich.
Wenn ich eine Kombination übergebe, die nicht im if-else des 1. Bytes enthalten war (s. Anfangsthread), dann zählt er 1 - 2 und sofort 3 - 4 - 5 - 6!
Ich habe also ein Oszilloskop drangehängt und mir mal angeschaut, was auf der Interruptleitung passiert. Fazit: Egal, was ich für Werte übergebe, es schaut immer gleich aus (okay, mit gewissen Toleranzen, die von der 'Echtzeitfähigkeit' von Windows kommen)! Sprich, es wird definitiv nur ein Interrupt ausgelöst!!!
Hab auch bei beiden switches einen default: break eingefügt, hat auch nix gebracht.

Hast du vielleicht noch Ideen??? Hast ja geschrieben fürs erste :-)

Im folgenden nochmal mein Code (in der neuen Fassung):

void TriggerISR() interrupt 8
{

P0_DATA &= 0xf8;
switch (counter)
{
case 0:
time1 = P3_DATA; //get LSB of time
break;

case 1:
time2 = P3_DATA; //get 2nd byte of time
break;

case 2:
time3 = P3_DATA; //get MSB of time
if (time3 == 0)
break;

case 3:
phase = P3_DATA; //get phase information
break;

case 4:
switch (P3_DATA)
{
case 0:
usePhase = 0; //-> phase ignored
mainc = 0; //use serial contactors
break;
case 1:
usePhase = 1; //-> phase important
mainc = 0; //use serial contactors
break;
case 2:
usePhase = 0; //-> phase ignored
mainc = 1; //use main contactor
break;
case 3:
usePhase = 1; //-> phase important
mainc = 1; //use main contactor
break;

default:
break;
}
break;

default:
break;
}
counter++;
P0_DATA = counter;
IRCON0 &= 0xfb; //reset IR-Bit of trigger
}

PicNick
10.05.2005, 07:57
Wenn das 1:1 die SOurce ist, dann hast du einen Hund drin.
case 2:
time3 = P3_DATA;
if (time3 == 0)
break;
case 3:

! Break ist nur, wenn time3 == 0 !!

Ampfing
10.05.2005, 08:25
Oh, da habe ich mich vertippt. Hab das Problem, dass ich auf 2 Rechner arbeiten muss, weil der Code-Rechner keinen Netzanschluß hat...
Die if-Abfrage ist im Originalcode nicht drin!
Also einfach
case 2:
time3 = P3_DATA;
break;
case 3:

PicNick
10.05.2005, 09:03
Ich glaub' dir ja gerne, aber genau bei dem Fehler würde er so wie beschrieben reagieren. (break ist kein Formalismus, sondern das Kommando: "jump loop-exit", kann also auch bedingt aufgerufen werden)
Also, der Code ist (wirklich) so (abgespeckt) ?:

void TriggerISR() interrupt 8
{
P0_DATA &= 0xf8;
switch (counter)
{
case 0: time1 = P3_DATA; break;
case 1: time2 = P3_DATA; break;
case 2: time3 = P3_DATA; break;
case 3: phase = P3_DATA; break;
case 4:
switch (P3_DATA)
{
case 0: usePhase = 0; mainc = 0; break;
case 1: usePhase = 1; mainc = 0; break;
case 2: usePhase = 0; mainc = 1; break;
case 3: usePhase = 1; mainc = 1; break;
default: break;
}
break;
default:
break;
}
counter++;
P0_DATA = counter;
IRCON0 &= 0xfb; //reset IR-Bit of trigger
}

Gut. Da aber für das Lämpchenleuchten der ganze Switch irrelevant ist, läuft ja eigentlich nur das:

void TriggerISR() interrupt 8
{
P0_DATA &= 0xf8;
counter++;
P0_DATA = counter;
IRCON0 &= 0xfb;
}

d.h mit switch und break hat das Problem, wenn noch vorhanden, nix zu tun.
Jetzt kontrollieren wir, ob der Interrupt wirklich nur einmal gerufen wird



static (volatile?) char bB = 0;

void TriggerISR() interrupt 8
{
if (bB & 1)
P0_DATA = 0x07; // alle leuchten--> doppel interrupt
else
{
bB |= 1;
P0_DATA &= 0xf8;
counter++;
P0_DATA = counter;
}
IRCON0 &= 0xfb;
bB &= ~1;
}

dadurch ist das p0-data setzen und counter++ abgesichert

FÜr weiteren Support wäre eine disassembler-liste hilfreich.

Wie gesagt, das einzige, was ich ausschließe, ist, daß sich der Controller verzählt. Der Fehler liegt im Interrupt oder doch im Code, auch wenn wir's nicht sehen.
wie sind die Daten definiert ?

Ampfing
10.05.2005, 10:08
Hallo Robert,

ich habe es zwar etwas anders angestellt als du, aber ich bin mir mittlerweile definitiv sicher, dass ein 2. Interrupt ausgelöst wird, wenn ich die 'falschen' Werte übergebe.
Ich habe das ganze herausgefunden, indem ich in der ISR nacheinander in jeden case ein EA = 0 (verbietet global ALLE Interrupts) eingefügt habe. Wenn ich den in case 1 reinschreibe und Werte übergebe geht zunächst die erste LED an (für case 0), dann die 2. und dann is Ruhe. Wenn ich die Zeile in case 2 reinschreibe 'verzählt' er sich wieder. Das heißt doch, dass definitiv ein zweiter Interrupt ausgelöst wird, oder?
Dann ist nur noch die Frage woher...
Ich würde dir ja gerne ein Bild von meinem Oszilloskop schicken, aber leider kann man hier ja keine Anhänge an den Thread hängen und auf ftp-Server darf ich von hier scheinbar nicht. Also muss ich dir halt so versichern, dass es nur insgesamt 5 steigende Flanken am Eingang des Controllers gibt. Und die 3. kommt ganz sicher erst nachdem er bereits den counter auf 3 erhöht hat.
Das mit dem Disassembly wird vermutlich relativ schwierig, weil das wieder nur über Screenshot gehen wird, befürchte ich. Da hab ich aber auch schonmal reingeschaut und finde da ehrlich gesagt keinen Fehler. In einer Simulation (ohne Hardware) funktioniert das Programm auch einwandfrei.

Im Anschluß nochmal ein Originallisting meines aktuellen Programms:
Datei main.c:


//declaration of functions
extern void PortInit(void); //declared in ports.c
extern void InterruptInit(void); //declared in int.c

//declaration of variables
volatile unsigned char counter; //counter variable for number of trigger events
volatile unsigned char time1, time2, time3; //time in ms (LSB to MSB)
volatile unsigned char phase; //phase information
volatile bit usePhase; //0 if phase is not used, 1 if phase is used
volatile bit mainc; //1 if main contactor is used, else 0

void main (void)
{
PortInit(); //initialize the ports
InterruptInit(); //initialize the trigger-interrupts
counter = 0; //set starting value for counter
EA = 1; //enable all interrupts globaly

while(counter < 5); //wait for 5 transmissions from the computer
/*if (mainc == 1)
{
P0_DATA &= 0xf8; //close the serial contactors (shoot is performed with main contactor)
}*/
while(1);
}


Datei ports.c:


void PortInit(void)
{
P0_DIR = 0xb; //P0.0, P0.1 and P0.3 are outputs
P1_DIR = 0x0; //P1.1 is an input
P3_DIR = 0x0; //P3.0 to P3.7 are inputs
//for testing:
P1_DIR |= 0xc0; //P1.6 and P1.7 are outputs
P0_DIR |= 0x4; //P0.2 is an output
}


Datei int.c:


extern volatile unsigned char counter; //declared in main.c
extern volatile unsigned char time1, time2, time3, phase; //declared in main.c
extern volatile bit usePhase; //declared in main.c
extern volatile bit mainc; //declared in main.c

void InterruptInit(void)
{
//set priorities of interrupts (shoot = 2, trigger and phase = 1)
IP1 = 0x8; //reset bit for shoot, set bit for trigger
IPH1 = 0x4; //set bit for shoot, reset bit for trigger
IP |= 0x4; //set bit for phase
IPH = 0x3b; //reset bit for phase

EXICON0 = 0x14; //edge selection for the three signals
IEN0 &= 0xfb; //disable interrupt for phase (individually)
IEN1 |= 0x4; //enable interrupt for the shoot(individually)
IEN1 |= 0x8; //enable interrupt for trigger (individually)
}

void TriggerISR() interrupt 8
{
P0_DATA &= 0xf8;

switch (counter)
{
case 0:
time1 = P3_DATA; //get LSB of time
/*if (time1 == 0)
{
P0_DATA |= 1;
}
else
{
if (time1 == 2)
{
P0_DATA |= 2;
}
}*/
break;

case 1:
time2 = P3_DATA; //get 2nd byte of time
/*if (time2 == 0)
{
P0_DATA |= 0x3;
}
else
{
if (time2 == 1)
{
P0_DATA |= 0x4;
}
}*/
break;

case 2:
time3 = P3_DATA; //get MSB of time
EA = 0; //disable all interrupts
/*if (time3 == 0)
{
P0_DATA |= 0x1;
}
else
{
if (time3 == 13)
{
P0_DATA |= 0x7;
}
}*/
break;

case 3:
phase = P3_DATA; //get phase information
/*if (phase == 0)
{
P0_DATA |= 0x6;
}
else
{
if (phase == 128)
{
P0_DATA |= 0x1;
}
}*/
break;

case 4:
switch (P3_DATA)
{
case 0:
usePhase = 0; //-> phase ignored
mainc = 0; //use serial contactors
break;
case 1:
usePhase = 1; //-> phase important
mainc = 0; //use serial contactors
break;
case 2:
usePhase = 0; //-> phase ignored
mainc = 1; //use main contactor
break;
case 3:
usePhase = 1; //-> phase important
mainc = 1; //use main contactor
break;
default:
break;
}
break;

default:
break;
}
counter++;
P0_DATA = counter;
IRCON0 &= 0xfb; //reset IR-Bit of trigger
}

Wie gesagt, das EA=0 in int.c deaktiviert nur alle Interrupts (war zum Testen).

Vielen Dank für deine Bemühung!!! und viele Grüße

PicNick
10.05.2005, 10:22
Ich schau's mir genau an.
Ein Tip aus alter Zeit:
Wenn du deine PC mit einem Nullmodem-Kabel verbindest, kannst du mit
c:>copy file.xx COM1
bzw.
c:>copy COM1 file.xx
Text-Files transferieren. (MODE com1: baud, etc. nicht vergessen)
Außerdem können viele Terminal-Emu-Programme das und auch binäre daten übertragen

PicNick
10.05.2005, 10:30
Ich kenn den konkreten Controller leider nicht.
Irgendwie kommen wohl deine Interrupts durcheinander, vielleicht weil du nur eine ISR für zwei Prioritäten hast ? (spekulativ)
Da müßte man versuchen, die betreffenden Stellen im Datasheet auswendig zu lernen. Da muß ich wohl passen, tut leid. :oops:

Ampfing
10.05.2005, 10:40
Hallo Robert,

jetzt hatte doch jemand Erbarmen und hat mir verraten, dass er einen USB-Stick hat...
Ich habe mal die relevanten Teile des Disassembly rauskopiert (die 1000 NOPs dazwischen also nicht...).


TriggerISR
C:0x0800 C0E0 PUSH ACC(0xE0)
C:0x0802 C0D0 PUSH PSW(0xD0)
C:0x0804 75D000 MOV PSW(0xD0),#0x00
C:0x0807 C007 PUSH 0x07
C:0x0809 5380F8 ANL P0_DATA(0x80),#IP1(0xF8)
C:0x080C E508 MOV A,counter(0x08)
C:0x080E 14 DEC A
C:0x080F 6012 JZ C:0823
C:0x0811 14 DEC A
C:0x0812 6014 JZ C:0828
C:0x0814 14 DEC A
C:0x0815 6018 JZ C:082F
C:0x0817 14 DEC A
C:0x0818 601A JZ C:0834
C:0x081A 2404 ADD A,#0x04
C:0x081C 703C JNZ C:085A
C:0x081E 85B00A MOV time1(0x0A),P3_DATA(0xB0)
C:0x0821 8037 SJMP C:085A
C:0x0823 85B00B MOV time2(0x0B),P3_DATA(0xB0)
C:0x0826 8032 SJMP C:085A
C:0x0828 85B00C MOV time3(0x0C),P3_DATA(0xB0)
C:0x082B C2AF CLR EA(0xA8.7)
C:0x082D 802B SJMP C:085A
C:0x082F 85B009 MOV phase(0x09),P3_DATA(0xB0)
C:0x0832 8026 SJMP C:085A
C:0x0834 AFB0 MOV R7,P3_DATA(0xB0)
C:0x0836 EF MOV A,R7
C:0x0837 14 DEC A
C:0x0838 6010 JZ C:084A
C:0x083A 14 DEC A
C:0x083B 6013 JZ C:0850
C:0x083D 14 DEC A
C:0x083E 6016 JZ C:0856
C:0x0840 2403 ADD A,#0x03
C:0x0842 7016 JNZ C:085A
C:0x0844 C201 CLR usePhase(0x20.1)
C:0x0846 C200 CLR mainc(0x20.0)
C:0x0848 8010 SJMP C:085A
C:0x084A D201 SETB usePhase(0x20.1)
C:0x084C C200 CLR mainc(0x20.0)
C:0x084E 800A SJMP C:085A
C:0x0850 C201 CLR usePhase(0x20.1)
C:0x0852 D200 SETB mainc(0x20.0)
C:0x0854 8004 SJMP C:085A
C:0x0856 D201 SETB usePhase(0x20.1)
C:0x0858 D200 SETB mainc(0x20.0)
C:0x085A 0508 INC counter(0x08)
C:0x085C 850880 MOV P0_DATA(0x80),counter(0x08)
C:0x085F 53B4FB ANL IRCON0(0xB4),#CCU6_CC60RH(0xFB)
C:0x0862 D007 POP 0x07
C:0x0864 D0D0 POP PSW(0xD0)
C:0x0866 D0E0 POP ACC(0xE0)
C:0x0868 32 RETI

InterruptInit:
C:0x0883 75F808 MOV IP1(0xF8),#counter(0x08)
C:0x0886 75F904 MOV IPH1(0xF9),#0x04
C:0x0889 43B804 ORL IP(0xB8),#0x04
C:0x088C 75B93B MOV IPH(0xB9),#0x3B
C:0x088F 75B714 MOV EXICON0(0xB7),#0x14
C:0x0892 53A8FB ANL IEN0(0xA8),#CCU6_CC60RH(0xFB)
C:0x0895 43E804 ORL IEN1(0xE8),#0x04
C:0x0898 43E808 ORL IEN1(0xE8),#counter(0x08)
C:0x089B 22 RET

main:
C:0x089C 1208B0 LCALL PortInit(C:08B0)
C:0x089F 120883 LCALL InterruptInit(C:0883)
C:0x08A2 E4 CLR A
C:0x08A3 F508 MOV counter(0x08),A
C:0x08A5 D2AF SETB EA(0xA8.7)
C:0x08A7 E508 MOV A,counter(0x08)
C:0x08A9 C3 CLR C
C:0x08AA 9405 SUBB A,#0x05
C:0x08AC 40F9 JC C:08A7
C:0x08AE 80FE SJMP C:08AE

PortInit:
C:0x08B0 75860B MOV P0_DIR(0x86),#time2(0x0B)
C:0x08B3 E4 CLR A
C:0x08B4 F591 MOV P1_DIR(0x91),A
C:0x08B6 F5B1 MOV P3_DIR(0xB1),A
C:0x08B8 4391C0 ORL P1_DIR(0x91),#T2CON(0xC0)
C:0x08BB 438604 ORL P0_DIR(0x86),#0x04
C:0x08BE 22 RET

Die erste Spalte ist jeweils die Adresse.
Auf Adresse 0043 steht ein Jump auf die TriggerISR (sprich, das ist der Interrupt-Vektor für diesen Interrupt).

Wieso habe ich einen Interrupt für 2 Prioritäten? Das mit IP und IPH kommt daher, dass es 4 Prioritätsstufen gibt und die 2 Bit auf die zwei Register verteilt sind.

Nochmal vielen Dank und viele Grüße

PicNick
10.05.2005, 11:22
Ah, danke. sieht ok aus (die switch-Interpretation ist listig, sieht man nicht oft in der Form)
Du setzt "Edge Selection". Schaust du mal, ob das wirklich für "rising / falling" gilt oder womöglich für beides ?
Du brauchst doch entweder "Level" oder definitiv nur eines von rise/fall
(das steht im Datasheet).
Diagnose vom Doktor: Der interrupt-Code ist so oder so o.k.
Entweder hat's was mit der ISR-Definition oder eben doch was elektrisches.
tscha

Ampfing
10.05.2005, 12:34
Hallo Robert,

ich muss ehrlich zugeben, ich habe auch ne Zeit gebraucht, bis ich verstanden habe, wozu der switch umgebaut wurde.
Hab nochmal nachgeschaut, ich habe tatsächlich nur auf positive Flanke getriggert.
Mittlerweile habe ich das Problem auch eingegrenzt und behoben (zumindest von der Software-Seite)!
Es war ehrlich gesagt nicht ganz so, wie ich es am Anfang gepostet hatte. Der 2. Interrupt wird nur ausgelöst, wenn im 1. Byte das höchstwertige Bit gesetzt ist! Dann und nur dann wird bei der Übertragung des 2. Bytes ein 2. Interrupt generiert und er macht Schrott.
Hab das jetzt einfach so abgefangen:


case 1:
time2 = P3_DATA;
if (time1 > 127 && error == 1)
{
error = 0;
counter--;
}
break;

error ist nochmal ein Bit, damit ich weiß, ob ich das erste mal in den case reinlaufe oder nicht.
Das funktioniert zumindest mal - auch wenn ich nach wie vor nicht weiß, warum der 2. Interrupt ausgelöst wird. Das wird wohl das Geheimnis des Controllers bleiben...

Vielen Dank für deine tatkräftige Unterstützung und viele Grüße
Michael

PicNick
10.05.2005, 13:03
Seltsam.
Das einzige, was mir auffällt, aber ich seh auch keinen Grund darin:
du definierst
volatile unsigned char counter;
volatile unsigned char time1, time2, time3;
volatile unsigned char phase;
Er ändert aber die Folge
counter 08
phase 09
time1 0a
time2 0b
time3 0c

Wieso eigentlich ?
alphabetisch isses nicht, reihefolge vorkommen auch nicht

Ampfing
10.05.2005, 13:38
Ich weiß ehrlich gesagt nicht, warum er die Reihenfolge ändert.
Aber das ist doch alphabetisch, oder? (p kommt meines Wissens vor t und nach c)

Ich weiß nur, dass es jetzt endlich funktioniert und dass ich überglücklich bin, weil mein restliches Programm jetzt auch funzt!!!! \:D/

Was ich noch so an Ideen hatte, warum es nicht funktionieren könnte:
Wenn in time1 das msb gesetzt ist und er es in die Variable schiebt könnte ja irgendein Überlauf stattfinden, der durch einen dummen Zufall genau das IR-Bit des Interrupts setzt. Aber das kann eigentlich auch nicht sein, da das Register EXICON0 (mit dem IR-Bit) wo ganz anders liegt - irgendwas mit 0xaX (das X is auch noch ne Zahl...). Außerdem hätte das ja dann weg sein müssen, als ich nen anderen Interruptkanal probiert habe.
Was auch immer es ist, es bleibt wohl oder übel das Geheimnis des Controllers (und vielleicht auch von Infineon).

Nochmal vielen vielen Dank, dass du dir soviel Zeit für mein Problem genommen hast!!! Ich hoffe mal, ich habe dich nicht zu sehr vom Arbeiten abgehalten!?

PicNick
10.05.2005, 14:42
Du hast recht, alphabet sollt man können :oops:
Wenn's geht, ist das schon mal fein.
Is halt blöd, daß man nicht weiß, warums NICHT geht, und jetzt eigentlich nicht weiß, warum es jetzt SCHON geht.
Tu mir aber vielleicht die Liebe und poste das ganze, das ja jetzt funzt, nochmal rein, ich möcht mir das unter den Kopfpolster legen.
Meine Arbeit ist ohnehin genau die gleiche: Fehler in Programmen suchen, die ich vorher selbst reingeschrieben habe. :mrgreen:

Ampfing
10.05.2005, 15:54
Okay, poste ich morgen (hab den anderen Rechner schon aus). Alternativ kann ich dir das Ganze natürlich auch gerne zuschicken, wenn dir das lieber ist!?
Viele Grüße und viel Spaß beim Fehler suchen :-)

PicNick
10.05.2005, 16:12
Hast Recht, den Tag immer bei einem Erfolg sofort beenden, das sicher den Schlaf

Ampfing
11.05.2005, 07:51
Guten Morgen,

im Anschluss also das momentan aktuelle Programm. Ich kann dir aber noch nicht versprechen, dass es 100%ig gleich bleiben wird, aber viel wird sich auf jeden Fall nicht mehr ändern.
Wenn dich 'nur' der problematische Programmteil interessiert schau einfach nur in die Datei int.c (und da in die Funktion TriggerISR), ich poste hier mal mein komplettes Programm (+ Disassembly).
Viele Grüße nach Wien
Michael

Datei main.c:


#include "main.h"
#include "io.h"

//declaration of functions
extern void PortInit(void); //declared in ports.c
extern void TimerInit(void); //declared in timer.c
extern void InterruptInit(void); //declared in int.c
extern void Shoot (void); //declared in int.c
extern void CorrectTimes(void); //declared in timer.c

//declaration of variables
volatile unsigned char counter; //counter variable for number of trigger events
volatile unsigned char time1, time2, time3; //time in ms (LSB to MSB)
volatile unsigned char phase; //phase information
volatile bit usePhase; //0 if phase is not used, 1 if phase is used
volatile bit ready; //0 if shoot paused, 1 if shoot is performed
volatile bit mainc; //1 if main contactor is used, else 0
volatile bit europe; //1 if f=50Hz (European), 0 if f=60Hz (American)

extern volatile bit error; //declared in int.c

/*--------------------------------------------------------------*/
/* function main */
/* initalizes the controller, executes the program */
/* no input, no return value */

void main (void)
{
PortInit(); //initialize the ports
TimerInit(); //initialize the timers
InterruptInit(); //initialize the trigger-interrupts
counter = 0; //set starting value for counter
ready = 0; //shoot must not be performed yet
EA = 1; //enable all interrupts globaly

while(counter < 5); //wait for 5 transmissions from the computer
finished = 0; //reset finished bit
if ((phase & 0x80) == 0)
{
europe = 0;
}
else
{
europe = 1;
}
if (mainc == 1)
{
P0_DATA |= 0x2; //close the serial contactors (shoot is performed with main contactor)
}
else
{
P0_DATA |= 0x1; //close the main contactor (shoot is performed with serial contactors)
}
CorrectTimes(); //corrects time1 to time3

while(ready == 0); //wait for shoot-signal from computer
if (usePhase == 1)
{
IRCON0 &= 0xfd; //reset IR-Bit of null-phase
while ((IRCON0 & 0xfd) == 0); //wait for IR-Bit of null-phase
if (europe == 1)
{
TR0 = 1; //start T0 (for 50Hz)
while (phase > 0); //wait until signal has desired phase
TR0 = 0; //stop T0
}
else
{
TR1 = 1; //start T1 (for 60Hz)
while (phase > 0); //wait until signal has desired phase
TR1 = 0; //stop TR1
}
}
Shoot(); //perform the shoot
while(1);
}
//end of function main()


Datei int.c:


#include "main.h"

//declaration of functions
void ResetShoot(void);
void Shoot(void);

//declaration of variables
volatile bit error; //to correct counter if necessary
extern volatile unsigned char counter; //declared in main.c
extern volatile unsigned char time1, time2, time3, phase; //declared in main.c
extern volatile bit usePhase; //declared in main.c
extern volatile bit mainc, ready; //declared in main.c

/*------------------------------------------------------*/
/* function InterruptInit */
/* initializes the trigger-interrupts */
/* no input, no return value */
/* shoot -> EXINT2 (both edges)
trigger -> EXINT3 (rising edge)
phase -> EXINT1 (rising edge) NOT ACTIVATED!!! */

void InterruptInit(void)
{
//set priorities of interrupts (shoot = 2, trigger and phase = 1)
IP1 = 0x8; //reset bit for shoot, set bit for trigger
IPH1 = 0x4; //set bit for shoot, reset bit for trigger
IP |= 0x4; //set bit for phase
IPH = 0x3b; //reset bit for phase

EXICON0 = 0x64; //edge selection for the three signals
IEN0 &= 0xfb; //disable interrupt for phase (individually)
IEN1 |= 0x4; //enable interrupt for the shoot(individually)
IEN1 |= 0x8; //enable interrupt for trigger (individually)
error = 1;
}
//end of function InterruptInit()

/*------------------------------------------------------*/
/* function TriggerISR */
/* ISR for trigger signal to latch time and phase */
/* no input, no return value */

void TriggerISR() interrupt 9
{
switch (counter)
{
case 0:
time1 = P3_DATA; //get LSB of time
break;

case 1:
time2 = P3_DATA; //get 2nd byte of time
if (time1 > 127 && error == 1)
{
error = 0;
counter--;
}
break;

case 2:
time3 = P3_DATA; //get MSB of time
break;

case 3:
phase = P3_DATA; //get phase information
break;

case 4:
switch (P3_DATA)
{
case 0:
usePhase = 0; //-> phase ignored
mainc = 0; //use serial contactors
break;
case 1:
usePhase = 1; //-> phase important
mainc = 0; //use serial contactors
break;
case 2:
usePhase = 0; //-> phase ignored
mainc = 1; //use main contactor
break;
case 3:
usePhase = 1; //-> phase important
mainc = 1; //use main contactor
break;
default:
break;
}
break;

default:
break;
}
counter++; //increase counter value by 1
IRCON0 &= 0xf7; //reset IR-Bit of trigger
}
//end of function TriggerISR()

/*------------------------------------------------------*/
/* function ShootISR */
/* ISR for pin shoot -> start or pause shoot */
/* no input, no return value */

void ShootISR () interrupt 8
{
if ((P2_DATA & 0x2) == 0) //-> Interrupt on falling edge
{
ResetShoot(); //open the contactor
ready = 0; //reset ready-bit
}
else
{
if (counter > 0) //if first IR on rising edge->maybe use phase information
{
ready = 1; //just set the ready bit (shoot performed by main())
}
else
{
Shoot(); //close the contactors
ready = 1; //set the ready-bit
}
}
IRCON0 &= 0xfb; //reset IR-Bit of shoot
}
//end of function ShootISR()

/*------------------------------------------------------*/
/* function ResetShoot */
/* stops the shoot */
/* no input, no return value */

void ResetShoot()
{
TR2 = 0; //stop T2
if (mainc == 1)
{
P0_DATA &= 0xfe; //open the main contactor
}
else
{
P0_DATA &= 0xfd; //open the serial contactors
}
}
//end of function ResetShoot()

/*------------------------------------------------------*/
/* function Shoot */
/* closes the relais for the shoot and starts T2 */
/* no input, no return value */

void Shoot()
{
if (mainc == 1)
{
P0_DATA |= 0x1; //close the main contactor
}
else
{
P0_DATA |= 0x2; //close the serial contactors
}
TR2 = 1; //start T2
}
//end of function Shoot()

Ampfing
11.05.2005, 07:52
Durfte leider nicht alles auf einmal posten, deshalb hier der zweite Teil.

Datei timer.c:


#include "main.h"
#include "io.h"

//declaration of functions
void CorrectTimes();

extern void ResetShoot();

//declaration of variables
volatile unsigned char idata stepsT0; //counter for steps of T0 for 1ms
volatile unsigned char idata stepsT1; //counter for steps of T1 for 1ms
volatile unsigned char correctTime2; //to save value of correction for time2

extern volatile unsigned char phase; //declared in main.c
extern volatile unsigned char time1, time2, time3; //declared in main.c
extern volatile bit ready; //declared in main.c

/*------------------------------------------------------*/
/* function TimerInit */
/* initializes the timers of controller */
/* no input, no return-value */
/* timer 0 generates 7,94µs for 50Hz,
timer 1 generates 5,78µs for 60Hz */

void TimerInit(void)
{
TMOD = 0x22; //T0 and T1 run in 8bit timer mode with auto reload
TL0 = TH0 = 150; //load T0 and its reload register with value for 7,94µs
TL1 = TH1 = 179; //load T1 and its relaod register with value for 5,78µs

T2MOD = 0; //prescaler is disabled, up-down is disabled, no edge selection (tm)
T2CON = 0; //reload mode, timer is stopped, no external events allowed
T2H = RC2H = 0xf7; //load high bytes of timer 2 and reload with value for 1ms
T2L = RC2L = 0x52; //load low bytes of timer 2 and reload with value for 1ms

IEN0 |= 0x2a; //enable all three timer interrupts (individually)
IP |= 0x2a; //set all three interrupts to priority 1
IPH = 0xd5; //set all three interrupts to priority 1

stepsT0 = 21; //21 overflows of T0 necessary for 166,95µs (3° with f=50Hz)
stepsT1 = 24; //24 overflows of T1 necessary for 138,6µs (3° with f=60Hz)
}
//end of function TimerInit()

/*------------------------------------------------------*/
/* function T2ISR */
/* ISR for timer 2 */
/* no input, no return value */

void T2ISR() interrupt 5
{
TF2 = 0; //clear the IR bit!
if (time1 == 0)
{
if (time2 == 0)
{
if (correctTime2 == 0)
{
if (time3 == 0)
{
P0_DATA &= 0xfc; //open the contactors as test is finished
finished = 1; //signal the computer that test is finished
correctTime2 = 0; //reset the correction time for next shoot
ready = 0; //reset the ready bit -> no shoot must be performed
}
else
{
time3--; //decrease MSB of time
time2 = 0xff; //set time2 to 255
time1 = 0xff; //set LSB of time to 255
}
}
else
{
time2 = correctTime2; //correct time2
time1 = 0xff; //set LSB of time to 255
correctTime2 = 0; //reset time correction
}
}
else
{
time2--; //decrease 2nd byte of time
time1 = 0xff; //set LSB of time to 255
}
}
else
{
time1--; //decrese LSB of time
}
P3_6 =~ P3_6; //toggle diode (for testing only!!)
}
//end of function T2ISR()

/*------------------------------------------------------*/
/* function T0ISR */
/* ISR for timer 0 */
/* no input, no return value */

void T0ISR() interrupt 1
{
stepsT0--; //decrease steps for 3° (50Hz)
if (stepsT0 == 0) //if time for 3° has passed
{
stepsT0 = 21; //reload steps for 3°
phase--; //decrease phase
}
}
//end of function T0ISR()

/*------------------------------------------------------*/
/* function T1ISR */
/* ISR for timer 1 */
/* no input, no return value */

void T1ISR() interrupt 3
{
stepsT1--; //decrease steps for 3° (60Hz)
if (stepsT1 == 0) //if time for 3° has passed
{
stepsT1 = 24; //reload steps for 3°
phase--; //decrease phase
}
}
//end of function T1ISR()

/*------------------------------------------------------*/
/* function CorrectTime */
/* corrects time1 to time3 */
/* no input, no return value */

void CorrectTimes()
{
switch (time3)
{
case 0:
if (time1 != 0 || time2 == 0)
{
time1--;
}
else
{
if (time1 == 0)
{
time2--;
time1 = 0xff;
}
}
break;

default:
correctTime2 = time3;
if (time1 == 0)
{
time2--;
time1 = 0xff;
}
else
{
time1--;
}
break;
}
}
//end of function CorrectTimes()


Datei ports.c:


#include "main.h"
#include "io.h"

//declaration of functions
void PortInit();


/*------------------------------------------------------*/
/* function PortInit */
/* initializes the direction of ports */
/* no input, no return-value */


void PortInit(void)
{
P0_DIR = 0xb; //P0.0, P0.1 and P0.3 are outputs
P1_DIR = 0x0; //P1.1 is an input
P3_DIR = 0x0; //P3.0 to P3.7 are inputs
//for testing:
P1_DIR |= 0xc0; //P1.6 and P1.7 are outputs
P0_DIR |= 0x4; //P0.2 is an output
}
//end of function PortInit()


Disassembly:


main:
C:0x086F 120A25 LCALL PortInit(C:0A25)
C:0x0872 120966 LCALL TimerInit(C:0966)
C:0x0875 1209BC LCALL InterruptInit(C:09BC)
C:0x0878 E4 CLR A
C:0x0879 F508 MOV counter(0x08),A
C:0x087B C202 CLR ready(0x20.2)
C:0x087D D2AF SETB EA(0xA8.7)
C:0x087F E508 MOV A,counter(0x08)
C:0x0881 C3 CLR C
C:0x0882 9405 SUBB A,#0x05
C:0x0884 40F9 JC C:087F
C:0x0886 C283 CLR finished(0x80.3)
C:0x0888 E509 MOV A,phase(0x09)
C:0x088A 20E704 JB 0xE0.7,C:0891
C:0x088D C201 CLR europe(0x20.1)
C:0x088F 8002 SJMP C:0893
C:0x0891 D201 SETB europe(0x20.1)
C:0x0893 300005 JNB mainc(0x20.0),C:089B
C:0x0896 438002 ORL P0_DATA(0x80),#0x02
C:0x0899 8003 SJMP C:089E
C:0x089B 438001 ORL P0_DATA(0x80),#0x01
C:0x089E 120997 LCALL CorrectTimes(C:0997)
C:0x08A1 3002FD JNB ready(0x20.2),C:08A1
C:0x08A4 300324 JNB usePhase(0x20.3),C:08CB
C:0x08A7 53B4FD ANL IRCON0(0xB4),#CCU6_CC61RH(0xFD)
C:0x08AA E5B4 MOV A,IRCON0(0xB4)
C:0x08AC 54FD ANL A,#CCU6_CC61RH(0xFD)
C:0x08AE 60FA JZ C:08AA
C:0x08B0 30010D JNB europe(0x20.1),C:08C0
C:0x08B3 D28C SETB TR0(0x88.4)
C:0x08B5 E509 MOV A,phase(0x09)
C:0x08B7 D3 SETB C
C:0x08B8 9400 SUBB A,#0x00
C:0x08BA 50F9 JNC C:08B5
C:0x08BC C28C CLR TR0(0x88.4)
C:0x08BE 800B SJMP C:08CB
C:0x08C0 D28E SETB TR1(0x88.6)
C:0x08C2 E509 MOV A,phase(0x09)
C:0x08C4 D3 SETB C
C:0x08C5 9400 SUBB A,#0x00
C:0x08C7 50F9 JNC C:08C2
C:0x08C9 C28E CLR TR1(0x88.6)
C:0x08CB 120A34 LCALL Shoot(C:0A34)
C:0x08CE 80FE SJMP C:08CE

ShootISR:
C:0x08D0 C0E0 PUSH ACC(0xE0)
C:0x08D2 C0F0 PUSH B(0xF0)
C:0x08D4 C083 PUSH DPH(0x83)
C:0x08D6 C082 PUSH DPL(0x82)
C:0x08D8 C0D0 PUSH PSW(0xD0)
C:0x08DA 75D000 MOV PSW(0xD0),#0x00
C:0x08DD C000 PUSH 0x00
C:0x08DF C001 PUSH 0x01
C:0x08E1 C002 PUSH 0x02
C:0x08E3 C003 PUSH 0x03
C:0x08E5 C004 PUSH 0x04
C:0x08E7 C005 PUSH 0x05
C:0x08E9 C006 PUSH 0x06
C:0x08EB C007 PUSH 0x07
C:0x08ED E5A0 MOV A,PPAGE_SFR(0xA0)
C:0x08EF 20E107 JB 0xE0.1,C:08F9
C:0x08F2 120A42 LCALL ResetShoot(C:0A42)
C:0x08F5 C202 CLR ready(0x20.2)
C:0x08F7 8010 SJMP C:0909
C:0x08F9 E508 MOV A,counter(0x08)
C:0x08FB D3 SETB C
C:0x08FC 9400 SUBB A,#0x00
C:0x08FE 4004 JC C:0904
C:0x0900 D202 SETB ready(0x20.2)
C:0x0902 8005 SJMP C:0909
C:0x0904 120A34 LCALL Shoot(C:0A34)
C:0x0907 D202 SETB ready(0x20.2)
C:0x0909 53B4FB ANL IRCON0(0xB4),#CCU6_CC60RH(0xFB)
C:0x090C D007 POP 0x07
C:0x090E D006 POP 0x06
C:0x0910 D005 POP 0x05
C:0x0912 D004 POP 0x04
C:0x0914 D003 POP 0x03
C:0x0916 D002 POP 0x02
C:0x0918 D001 POP 0x01
C:0x091A D000 POP 0x00
C:0x091C D0D0 POP PSW(0xD0)
C:0x091E D082 POP DPL(0x82)
C:0x0920 D083 POP DPH(0x83)
C:0x0922 D0F0 POP B(0xF0)
C:0x0924 D0E0 POP ACC(0xE0)
C:0x0926 32 RETI

T2ISR:
C:0x0927 C0E0 PUSH ACC(0xE0)
C:0x0929 C2C7 CLR TF2(0xC0.7)
C:0x092B E50A MOV A,time1(0x0A)
C:0x092D 7030 JNZ C:095F
C:0x092F E50B MOV A,time2(0x0B)
C:0x0931 7025 JNZ C:0958
C:0x0933 E50D MOV A,correctTime2(0x0D)
C:0x0935 7016 JNZ C:094D
C:0x0937 E50C MOV A,time3(0x0C)
C:0x0939 700B JNZ C:0946
C:0x093B 5380FC ANL P0_DATA(0x80),#CCU6_T13L(0xFC)
C:0x093E D283 SETB finished(0x80.3)
C:0x0940 F50D MOV correctTime2(0x0D),A
C:0x0942 C202 CLR ready(0x20.2)
C:0x0944 801B SJMP C:0961
C:0x0946 150C DEC time3(0x0C)
C:0x0948 750BFF MOV time2(0x0B),#CCU6_CC62RH(0xFF)
C:0x094B 800D SJMP C:095A
C:0x094D 850D0B MOV time2(0x0B),correctTime2(0x0D)
C:0x0950 750AFF MOV time1(0x0A),#CCU6_CC62RH(0xFF)
C:0x0953 750D00 MOV correctTime2(0x0D),#0x00
C:0x0956 8009 SJMP C:0961
C:0x0958 150B DEC time2(0x0B)
C:0x095A 750AFF MOV time1(0x0A),#CCU6_CC62RH(0xFF)
C:0x095D 8002 SJMP C:0961
C:0x095F 150A DEC time1(0x0A)
C:0x0961 B2B6 CPL P3_6(0xB0.6)
C:0x0963 D0E0 POP ACC(0xE0)
C:0x0965 32 RETI

TimerInit:
C:0x0966 758922 MOV TMOD(0x89),#0x22
C:0x0969 758C96 MOV TH0(0x8C),#0x96
C:0x096C 758A96 MOV TL0(0x8A),#0x96
C:0x096F 758DB3 MOV TH1(0x8D),#ID(0xB3)
C:0x0972 758BB3 MOV TL1(0x8B),#ID(0xB3)
C:0x0975 E4 CLR A
C:0x0976 F5C1 MOV T2MOD(0xC1),A
C:0x0978 F5C0 MOV T2CON(0xC0),A
C:0x097A 75C3F7 MOV RC2H(0xC3),#HWBPDR(0xF7)
C:0x097D 75C5F7 MOV T2H(0xC5),#HWBPDR(0xF7)
C:0x0980 75C252 MOV RC2L(0xC2),#0x52
C:0x0983 75C452 MOV T2L(0xC4),#0x52
C:0x0986 43A82A ORL IEN0(0xA8),#0x2A
C:0x0989 43B82A ORL IP(0xB8),#0x2A
C:0x098C 75B9D5 MOV IPH(0xB9),#0xD5
C:0x098F 780E MOV R0,#stepsT0(0x0E)
C:0x0991 7615 MOV @R0,#0x15
C:0x0993 08 INC R0
C:0x0994 7618 MOV @R0,#0x18
C:0x0996 22 RET

CorrectTimes:
C:0x0997 E50C MOV A,time3(0x0C)
C:0x0999 7011 JNZ C:09AC
C:0x099B E50A MOV A,time1(0x0A)
C:0x099D 7004 JNZ C:09A3
C:0x099F E50B MOV A,time2(0x0B)
C:0x09A1 7003 JNZ C:09A6
C:0x09A3 150A DEC time1(0x0A)
C:0x09A5 22 RET
C:0x09A6 E50A MOV A,time1(0x0A)
C:0x09A8 7011 JNZ C:09BB
C:0x09AA 8007 SJMP C:09B3
C:0x09AC 850C0D MOV correctTime2(0x0D),time3(0x0C)
C:0x09AF E50A MOV A,time1(0x0A)
C:0x09B1 7006 JNZ C:09B9
C:0x09B3 150B DEC time2(0x0B)
C:0x09B5 750AFF MOV time1(0x0A),#CCU6_CC62RH(0xFF)
C:0x09B8 22 RET
C:0x09B9 150A DEC time1(0x0A)
C:0x09BB 22 RET

InterruptInit:
C:0x09BC 75F808 MOV IP1(0xF8),#counter(0x08)
C:0x09BF 75F904 MOV IPH1(0xF9),#0x04
C:0x09C2 43B804 ORL IP(0xB8),#0x04
C:0x09C5 75B93B MOV IPH(0xB9),#0x3B
C:0x09C8 75B764 MOV EXICON0(0xB7),#0x64
C:0x09CB 53A8FB ANL IEN0(0xA8),#CCU6_CC60RH(0xFB)
C:0x09CE 43E804 ORL IEN1(0xE8),#0x04
C:0x09D1 43E808 ORL IEN1(0xE8),#counter(0x08)
C:0x09D4 D204 SETB error(0x20.4)
C:0x09D6 22 RET

T0ISR:
C:0x09F1 C0E0 PUSH ACC(0xE0)
C:0x09F3 C0D0 PUSH PSW(0xD0)
C:0x09F5 75D000 MOV PSW(0xD0),#0x00
C:0x09F8 C000 PUSH 0x00
C:0x09FA 780E MOV R0,#stepsT0(0x0E)
C:0x09FC 16 DEC @R0
C:0x09FD E6 MOV A,@R0
C:0x09FE 7004 JNZ C:0A04
C:0x0A00 7615 MOV @R0,#0x15
C:0x0A02 1509 DEC phase(0x09)
C:0x0A04 D000 POP 0x00
C:0x0A06 D0D0 POP PSW(0xD0)
C:0x0A08 D0E0 POP ACC(0xE0)
C:0x0A0A 32 RETI

T1ISR:
C:0x0A0B C0E0 PUSH ACC(0xE0)
C:0x0A0D C0D0 PUSH PSW(0xD0)
C:0x0A0F 75D000 MOV PSW(0xD0),#0x00
C:0x0A12 C000 PUSH 0x00
C:0x0A14 780F MOV R0,#stepsT1(0x0F)
C:0x0A16 16 DEC @R0
C:0x0A17 E6 MOV A,@R0
C:0x0A18 7004 JNZ C:0A1E
C:0x0A1A 7618 MOV @R0,#0x18
C:0x0A1C 1509 DEC phase(0x09)
C:0x0A1E D000 POP 0x00
C:0x0A20 D0D0 POP PSW(0xD0)
C:0x0A22 D0E0 POP ACC(0xE0)
C:0x0A24 32 RETI

PortInit:
C:0x0A25 75860B MOV P0_DIR(0x86),#time2(0x0B)
C:0x0A28 E4 CLR A
C:0x0A29 F591 MOV P1_DIR(0x91),A
C:0x0A2B F5B1 MOV P3_DIR(0xB1),A
C:0x0A2D 4391C0 ORL P1_DIR(0x91),#T2CON(0xC0)
C:0x0A30 438604 ORL P0_DIR(0x86),#0x04
C:0x0A33 22 RET

Shoot:
C:0x0A34 300005 JNB mainc(0x20.0),C:0A3C
C:0x0A37 438001 ORL P0_DATA(0x80),#0x01
C:0x0A3A 8003 SJMP C:0A3F
C:0x0A3C 438002 ORL P0_DATA(0x80),#0x02
C:0x0A3F D2C2 SETB TR2(0xC0.2)
C:0x0A41 22 RET

ResetShoot:
C:0x0A42 C2C2 CLR TR2(0xC0.2)
C:0x0A44 300004 JNB mainc(0x20.0),C:0A4B
C:0x0A47 5380FE ANL P0_DATA(0x80),#CCU6_CMPSTATL(0xFE)
C:0x0A4A 22 RET
C:0x0A4B 5380FD ANL P0_DATA(0x80),#CCU6_CC61RH(0xFD)
C:0x0A4E 22 RET

TriggerISR:
C:0x0800 C0E0 PUSH ACC(0xE0)
C:0x0802 C0D0 PUSH PSW(0xD0)
C:0x0804 75D000 MOV PSW(0xD0),#0x00
C:0x0807 C007 PUSH 0x07
C:0x0809 E508 MOV A,counter(0x08)
C:0x080B 14 DEC A
C:0x080C 6012 JZ C:0820
C:0x080E 14 DEC A
C:0x080F 6022 JZ C:0833
C:0x0811 14 DEC A
C:0x0812 6024 JZ C:0838
C:0x0814 14 DEC A
C:0x0815 6026 JZ C:083D
C:0x0817 2404 ADD A,#0x04
C:0x0819 7048 JNZ C:0863
C:0x081B 85B00A MOV time1(0x0A),P3_DATA(0xB0)
C:0x081E 8043 SJMP C:0863
C:0x0820 85B00B MOV time2(0x0B),P3_DATA(0xB0)
C:0x0823 E50A MOV A,time1(0x0A)
C:0x0825 D3 SETB C
C:0x0826 947F SUBB A,#0x7F
C:0x0828 4039 JC C:0863
C:0x082A 300436 JNB error(0x20.4),C:0863
C:0x082D C204 CLR error(0x20.4)
C:0x082F 1508 DEC counter(0x08)
C:0x0831 8030 SJMP C:0863
C:0x0833 85B00C MOV time3(0x0C),P3_DATA(0xB0)
C:0x0836 802B SJMP C:0863
C:0x0838 85B009 MOV phase(0x09),P3_DATA(0xB0)
C:0x083B 8026 SJMP C:0863
C:0x083D AFB0 MOV R7,P3_DATA(0xB0)
C:0x083F EF MOV A,R7
C:0x0840 14 DEC A
C:0x0841 6010 JZ C:0853
C:0x0843 14 DEC A
C:0x0844 6013 JZ C:0859
C:0x0846 14 DEC A
C:0x0847 6016 JZ C:085F
C:0x0849 2403 ADD A,#0x03
C:0x084B 7016 JNZ C:0863
C:0x084D C203 CLR usePhase(0x20.3)
C:0x084F C200 CLR mainc(0x20.0)
C:0x0851 8010 SJMP C:0863
C:0x0853 D203 SETB usePhase(0x20.3)
C:0x0855 C200 CLR mainc(0x20.0)
C:0x0857 800A SJMP C:0863
C:0x0859 C203 CLR usePhase(0x20.3)
C:0x085B D200 SETB mainc(0x20.0)
C:0x085D 8004 SJMP C:0863
C:0x085F D203 SETB usePhase(0x20.3)
C:0x0861 D200 SETB mainc(0x20.0)
C:0x0863 0508 INC counter(0x08)
C:0x0865 53B4F7 ANL IRCON0(0xB4),#HWBPDR(0xF7)
C:0x0868 D007 POP 0x07
C:0x086A D0D0 POP PSW(0xD0)
C:0x086C D0E0 POP ACC(0xE0)
C:0x086E 32 RETI

PicNick
11.05.2005, 08:18
Die Gemeinde dankt recht schön.
Ich hasse geheimnisvolle Dinge. Selbst wenn man irgendwie ein workaround findet, fange die Dinge meist dann wieder zu stinken an, wenn man ein komplexeres Programm drumherum aufgebaut hat. Und dann ist das Finden noch viel schwieriger.
Ist auch reiner Egoismus, ich lern' mehr aus solchen forensischen Recherchen als aus 27 funktionierenden Programmen.
Nur eine Frage noch: ist irgendein gefinkelter Überspruch von der 2^7 Leitung auf den Strobe-Pin möglich ?

Ampfing
11.05.2005, 08:59
Nichts zu danken.
Ehrlich gesagt würde ich schon auch gerne wissen, warum es nicht funktioniert. Hab mich jetzt - voerst! - mal mit dieser Lösung abgefunden, damit ich an meinem restlichen Problem weiter machen kann. Endgültig begraben habe ich das Ganze aber noch nicht.
Also wenn du mit deiner Frage meinst, ob eine Beeinflussung der 2^7-Leitung durch den Strobe stattfinden kann, dann muss ich sagen: elektrisch nicht! Ich habe die Leitungen extra nochmal durchgepiepst und sie sind nicht verbunden. Ist halt ein ganz normales Flachbandkabel. Wäre mir neu, dass sich da die Leitungen gegenseitig beeinflussen. Und vor allem, es passiert ja nur (und ausschließlich!), wenn im 1. Byte das 8. Bit gesetzt ist. Bei allen anderen Bytes ja nicht. Wenn es wirklich ein elektrisches Problem wäre müsste das doch bei allen Bytes auftreten und nicht nur beim Ersten, oder?

Viele Grüße

PicNick
11.05.2005, 09:32
Tscha, erst wenn wir wissen, was es ist , wissen wir, was es NICHT ist, vorher kannst du nur spekulieren.
Es ist ja so, daß beim 2.Isr von dem 2^7 vom 1. ja weit und breit keine Rede mehr ist. Weiters ist durch einen Überspruch eher ein Level-Interrupt gefährdet, und kein Flanken-fuzzy. Immerhin muß die Strobe Leitung ja erstmal runter und dann erst wieder rauf, die Datenleitungen sind während der Flanke aber stabil.
Die einzige Stelle, wo das 128-er Bit überlebt, ist ja time1 und wie soll das beim 2.ISR eine Rolle spielen
Der Inhalt des Datenbytes beim 2.ISR ist ja offensichtlich wurst.
Deswegen bin ich ja überzeugt, daß der Hund im Programm liegt und nicht in der Physik (Dort liegt er meistens).
Na wie auch immer, wir lassen uns das von einem bescheuerten Silzium-plättchen nicht bieten. schaun wir mal.

Ampfing
11.05.2005, 10:30
Genau das ist ja mein Problem. Ich sehe nicht, wie das 1. Byte überhaupt Einfluss auf den Interrupt des zweiten Bytes nehmen könnte!
Der Interrupt geht definitiv auf die Flanke, nicht auf den Zustand (geht bei dem Interrupt-Kanal nämlich gar ned anders). Und auf meinem Oszi-Bild ist definitiv nur eine Flanke beim 2. Byte drauf. Insofern stimme ich dir also zu, dass es nicht von der Physik kommen KANN.
Was mir wie gesagt noch eingefallen ist: Wenn das 2^7-Bit gesetzt ist, dass er sich dann irgendwie das Register IRCON0 (beinhaltet die IR-Bits für meine Interrupts - und zwar alle, nicht nur den Trigger) überschreibt und dadurch das IR-Bit setzt. Das Problem an der Theorie ist halt, dass IRCON0 (0xB4) von der Adresse her nichtmal in der Nähe von time1 (0x0B) liegt. Außerdem würde er mir ja dann jetzt auch noch einen anderen Interrupt (Interrupt 8 mit ISR ShootISR) auslösen. Und das tut er definitiv nicht. Hatte ja auch mal den Trigger-Interrupt auf den Kanal 8 gelegt (zum Testen) und er wurde trotzdem ausgelöst.
Diese Theorie ist also wohl auch nicht haltbar fürchte ich.
Was kann denn noch Ursache für so nen dummen Interrupt sein? Ich dachte immer nur ein IR-Bit oder ein externes Ereignis, aber offensichtlich noch mehr...

PicNick
11.05.2005, 11:39
Ich hab mir die XC866-Doku runtergezogen und versucht, aus der gemappten-Memory-Bank-Extension Philosophie schlau zu werden (diese Bank-Orgie geht mir, ehrlich gesagt, auch bei den PIC... auf den Geist)
Verdacht: Ich seh in der Disassemblerliste keine Stack-Pointer festlegung. (das muß nix heißen) ABER:
Lt. Datasheet ist der SP initial mit 0x07 definiert. Das wäre saumäßig. denn durch die volatile -definition hat der Compiler auch time1----etc. alles da unten addressiert.
Spekulation: 0x80 und größer (kleiner nicht) sind mögliche Flash-Addressen. wenn du also in den Clinch mit dem Stack kommst und ihm eine 0x80.. addresse als return reinschreibst, kommt auch so ein Gefuddel dabei raus (2.ISR)
Ein sinnvoller werte für den SP wäre z.B. 7F (RAMEND)

Es kann aber sein, daß der C in der disassemblerliste nur seine SP-definition unterschlagen hat, dann isses natürlich wieder nix.
Mach dich einmal beim C-Manual /Workbench schlau, wie denn das so ist mit dem SP, in den Infineon Unterlagen steht da natürlich nix.
*seufz*

Ampfing
11.05.2005, 12:59
Hallo Robert,

hm, wenn ich das mal geahnt hätte...
Ich habe - wie von Infineon mit ihrem Easy-Kit empfohlen - eine StartUp-Routine in mein Projekt integriert. Diese wird natürlich zum Code dazugebunden und vor meiner main ausgeführt. Dort habe ich auch einen Eintrag für den SP gefunden.
Weiter unten findest du zum einen den Code der StartUp, zum anderen eine Übersicht über die Adresse, wo der SP hininitialisiert wird (0x20, was direkt in meinen Interrupt-Vektoren liegt!). Wie kommt Keil drauf, den einfach mal so dahin zu legen? Die müssten doch auch wissen, dass in der Gegend die IR-Vektoren liegen, oder??
Ich weiß ja nicht, ob es wirklich daran liegt, aber kann ich den Eintrag einfach so verändern - ohne, dass mein Programm dann gar nicht mehr läuft?
Wobei ich dann immer noch nicht wirklich den Grund erkennen kann, warum es nur beim 1. Byte schiefgeht und warum er nur den einen Interrupt zweimal ausführt (schließlich liegen auf Adressen näher an 0x20 noch 2 andere IR-Vektoren)!?

Startup:


STARTUP1:
C:0x09BD 787F MOV R0,#0x7F
C:0x09BF E4 CLR A
IDATALOOP:
C:0x09C0 F6 MOV @R0,A
C:0x09C1 D8FD DJNZ R0,IDATALOOP(C:09C0)
C:0x09C3 90F000 MOV DPTR,#0xF000
C:0x09C6 7F00 MOV R7,#0x00
C:0x09C8 7E02 MOV R6,#0x02
C:0x09CA E4 CLR A
XDATALOOP:
C:0x09CB F0 MOVX @DPTR,A
C:0x09CC A3 INC DPTR
C:0x09CD DFFC DJNZ R7,XDATALOOP(C:09CB)
C:0x09CF DEFA DJNZ R6,XDATALOOP(C:09CB)
C:0x09D1 758120 MOV SP(0x81),#0x20
C:0x09D4 02086F LJMP main(C:086F)


Memory:


C:0x0020 00 NOP
C:0x0021 00 NOP
C:0x0022 00 NOP
C:0x0023 00 NOP
C:0x0024 00 NOP
C:0x0025 00 NOP
C:0x0026 00 NOP
C:0x0027 00 NOP
C:0x0028 00 NOP
C:0x0029 00 NOP
C:0x002A 00 NOP
C:0x002B 02092A LJMP T2ISR(C:092A)
C:0x002E 00 NOP
C:0x002F 00 NOP
C:0x0030 00 NOP
C:0x0031 00 NOP
C:0x0032 00 NOP
C:0x0033 00 NOP
C:0x0034 00 NOP
C:0x0035 00 NOP
C:0x0036 00 NOP
C:0x0037 00 NOP
C:0x0038 00 NOP
C:0x0039 00 NOP
C:0x003A 00 NOP
C:0x003B 00 NOP
C:0x003C 00 NOP
C:0x003D 00 NOP
C:0x003E 00 NOP
C:0x003F 00 NOP
C:0x0040 00 NOP
C:0x0041 00 NOP
C:0x0042 00 NOP
C:0x0043 0208D3 LJMP ShootISR(C:08D3)
C:0x0046 00 NOP
C:0x0047 00 NOP
C:0x0048 00 NOP
C:0x0049 00 NOP
C:0x004A 00 NOP
C:0x004B 020800 LJMP TriggerISR(C:0800)


Außerdem sind in der Startup folgende Dinge eingestellt:

IDATA memory length 0x0080
XDATA memory start address 0xF000
XDATA memory length 0x0200
PDATA memory start address 0x0000
PDATA memory length 0x00


Und es gäbe einen Eintrag "Reentrant Stack Initialization", bei dem man für das SMALL, LARGE und COMPACT-Modell jeweils "top of stack" einstellen kann.

In den Projekteinstellungen habe ich noch folgende Zeile gefunden:
Code(C:0x0-c:0x2fff, c:0xa000-c:0xafff), XDATA(X:0xf000-X:0xf1ff)

Wenn du jetzt sagst "Mensch, warum schreibt der das denn nicht gleich, dann hätten wir das Problem in 5 Minuten gelöst gehabt!", dann muss ich mich entschuldigen, aber auf solche Zusammenhänge wäre ich wahrscheinlich in 5 Jahren nicht gekommen. Zu meiner Verteidigung sei gesagt, dass das erst der 2. Microcontroller ist, den ich bislang programmiere. Wir hatten das Fach an der Schule und davor habe ich noch nie was von C - oder gar Assembler! - gehört gehabt...

Viele Grüße
Michael

PicNick
11.05.2005, 13:15
Du brauchst dich weder zu entschuldigen noch zu verteidigen, ich programmier jetzt 25 Jahre und bin noch immer jederzeit imstande, absoluten Schwachsinn zu produzieren.
Bei den kleinen Kisten ist ein Stack/Daten Konflikt immer leicht möglich.
Aber jetzt schau'n wir erstmal, ob's wirklich daran liegen kann.
Die Hoffnung stirbt zuletzt.
EDIT Code verändern: Alles sichern und in der Kopie rumzangeln, was du willst. Nie mehr als eine Sache verändern (beim probieren), druch falschen Code kann der Chip nicht abrauchen, also nur der Himmel ist die Grenze.

Ampfing
11.05.2005, 13:46
Du brauchst dich weder zu entschuldigen noch zu verteidigen, ich programmier jetzt 25 Jahre und bin noch immer jederzeit imstande, absoluten Schwachsinn zu produzieren.

Danke. Schwachsinn zu produzieren ist ja auch gar nicht das Problem, sondern eher sinnvolle Programm, oder? :-)

Okay, hab jetzt also in der Startup den SP mit 7F initialisiert. Und siehe da, das Problem besteht weiterhin...
Genau das selbe Phänomen. Hab auch nochmal im Speicher nachgeschaut, in der Gegend von 7F ist weit und breit nix (außer NOPs natürlich) - hab so bis Adresse 0x130 geschaut oder so.
Das wars dann wohl leider auch nicht...

PicNick
11.05.2005, 14:36
Ist auch gut. Jede Fehlerquelle, die man ausschließen kann, wollen wir als Erfolg betrachten.
Ich muß jetzt schauen, ob man als Programm erkennen kann, ob man in einer ISR ist oder nicht. Wär fein, damit wir das vom Tisch haben.
(?Schauen, ob (IRCON0 & 8 ) überhaupt gesetzt ist, und wenn nicht, was dann ?)

Um endgültig die Hardware draußen zu haben:
Schicke >127, schreib's aber nicht nach Time1
Schicke <127, schreib's aber 128 nach Time1
Fehler bei 1 --> HW
Fehler bei 2 --> SW

Einkreisen Time1/Speicheradresse : Füg hinten noch ein Byte an (Zzz1) und verwende es anstatt Time1 (der platz von time1 soll aber belegt bleiben)

Checken Counter: fang mal mit 1 an und zähl von dort rauf.
ev. dasselbe machen wie mit Time1

Ich überleg noch, warum er ausgerechnet diese ISR ganz vorne eingeschlichtet hat, alle andern aber irgendwo (muß nix heißen)

Ampfing
11.05.2005, 15:41
Hallo Robert,

es war natürlich doch die Hardware...

Moment, mir fällt gerade was ein.
Erstmal was ich gerade noch gedacht habe: P3.7 ist gleichzeitig als Alternativbelegung der externe Interrupt 4. Die ext. IR 3-6 teilen sich einen IR-Vektor und damit eine ISR!! Man kann auch nur alle 4 IR freigeben oder sperren, nicht einzeln. Deswegen dachte ich, würde er die gleiche ISR nochmal anspringen.
Dann ist mir aber der Knackpunkt aufgefallen: Ich habe ja auch versucht einen anderen Interrupt zu nehmen. Und das war der ext. IR 2! Der hat aber ein extra Enable bit und teilt sich mit niemandem seine ISR! Und das Phänomen ist trotzdem aufgetreten.
Also kann es das doch fast auch nicht sein, oder?
Außerdem habe ich mal gemacht, was du vorgeschlagen hast. Es wird jedesmal (!) definitiv das IR-Bit des ext. IR 3 gesetzt (hab ich mit IRCON0 & 8 ausprobiert).
Das ist dann wohl der Todesstoß für diese Theroie...

Hab auch das mit <127 und so ausprobiert.
Wenn ich >127 schicke und nicht nach time1 schreibe ruft er trotzdem zweimal die ISR
Schicke ich <127, schreibe aber 128 in time1 ruft er die ISR nur einmal. Heißt also wohl oder übel doch die HW. (insofern stimmt wenigstens der erste Satz noch :-))

Leider muss ich mich jetzt auch schon wieder auf den Heimweg machen (ich würde wirklich gerne weiterbasteln, aber ich hab noch was vor...). Bin aber natürlich weiterhin dankbar für jede Anregung und setze sie gleich morgen früh um (nehm mir für morgen abend mal nichts vor, damit ich für den Fall der Fälle auch länger machen kann!).

Viele Grüße nach Wien und einen schönen Abend noch
Michael

PicNick
11.05.2005, 15:59
So vergeht die Zeit, wenn man Spaß hat.
Die Frage ist ja, wieso wiederholt er den ersten Interrrupt nicht. Wir müssen einkreisen, welcher Interrupt nun was tut. In welchen Zeitabständen kommt denn der Strobe ?

Ampfing
11.05.2005, 16:51
kannst du laut sagen. Wie gesagt, morgen nehme ich mir nix vor. (Schreib jetzt noch kurz von daheim, weil es mich ned loslässt!)

Zu deiner Frage: Wenn es mal fertig läuft kommt der Strobe relativ schnell (so ein paar ms Abstand). Im Moment kommt er dann, wenn ich sage, dass er kommen soll. Also durchaus mit mehreren Sekunden dazwischen.

Mir ist noch was eingefallen, was ich schreiben wollte:
Durch die Standardbelegung von IRCON0 mit lauter 0en wird IR 4 so konfiguriert, dass er auf negative Flanke triggert! Und das Problem kommt auch, wenn er nach dem zweiten Byte eine negative Flanke hat - wie ich jetzt weiß. Ich habe nur nie eine Kombination versucht, die nach dem ersten Byte von high auf low im 8. Bit wechselt... Deshalb waren die anderen Bytes 'beliebig'. Nachher ist man halt immer gescheiter, gell.
Habs jetzt auch mal mit so einer Abfangschleife (in der ISR) versucht:


if (IRCON & 0x10)
{
IRCON &= 0xef;
return;
}
else
{
//der ganze switch auf den counter
}


hat aber leider auch nix gebracht, kommt trotzdem noch zweimal...

Schönen Abend und bis morgen

PicNick
11.05.2005, 17:42
Gut, die Unterlagen hab' ich alle in der Firma, hier bin ich eh hilflos.
bis morgen dann auch

Ampfing
12.05.2005, 08:31
Hallo Robert,

ich kann es selber noch gar nicht fassen, aber es geht!
Es ist tatsächlich so, dass der externe Interrupt 4 bei einer negativen Flanke an P3.7 den Request auslöst.
Und jetzt weiß ich auch, warum meine Abfrage am Anfang der ISR nix gebracht hat (s. gestern abend)...
In dem Testprogramm, das ich wieder verwendet habe, hatte ich testweise den Strobe auf einen anderen Interruptkanal gelegt. Das habe ich aber gestern abend übersehen und die Leitung nicht umgesteckt. Das heißt, er hat einen Request ausgelöst, nur war leider an der Stelle, wo normalerweise der IR-Vektor steht ein NOP. Also ist er das ganze Memory durchgelaufen, bis er auf den nächsten Befehl gelaufen ist - und das war wie es der Zufall so will genau meine TriggerISR...
Jetzt habe ich den Strobe wieder auf den Interrupt-Kanal gelegt, wo er hingehört und meine ISR angepasst - und es geht!!
Ich poste dir jetzt hier nochmal eben meine ISR. Wenn du willst kann ich dir später auch gerne nochmal mein komplettes Programm posten - hat sich doch noch etwas geändert - wenn ich die Änderungen übernommen und getestet habe.

Meine (Test-)ISR:


void TriggerISR() interrupt 9
{
P0_DATA &= 0xf8;
if (IRCON0 != 0x8)
{
IRCON0 &= 0x8;
}
else
{
switch (counter)
{
case 0:
time1 = P3_DATA; //get LSB of time
if (time1 == 0)
{
P0_DATA |= 1;
}
else
{
if (time1 == 2)
{
P0_DATA |= 2;
}
}
break;

case 1:
time2 = P3_DATA; //get 2nd byte of time
/*if (time1 > 127 && error == 1)
{
error = 0;
counter--;
}*/
if (time2 == 0)
{
P0_DATA |= 0x3;
}
else
{
if (time2 == 1)
{
P0_DATA |= 0x4;
}
}
break;

case 2:
time3 = P3_DATA; //get MSB of time
if (time3 == 0)
{
P0_DATA |= 0x1;
}
else
{
if (time3 == 13)
{
P0_DATA |= 0x7;
}
}
break;

case 3:
phase = P3_DATA; //get phase information
if (phase == 0)
{
P0_DATA |= 0x6;
}
else
{
if (phase == 128)
{
P0_DATA |= 0x1;
}
}
break;

case 4:
switch (P3_DATA)
{
case 0:
usePhase = 0; //-> phase ignored
mainc = 0; //use serial contactors
break;
case 1:
usePhase = 1; //-> phase important
mainc = 0; //use serial contactors
break;
case 2:
usePhase = 0; //-> phase ignored
mainc = 1; //use main contactor
break;
case 3:
usePhase = 1; //-> phase important
mainc = 1; //use main contactor
break;
default:
break;
}
break;

default:
break;
}
counter++;
IRCON0 = 0; //reset IR-Bit of trigger
}
}


Puh, das war eine schwere Geburt. Aber sie ist geschafft :-)
Wie sagt man englisch so schön "You're a star!". Soll heißen, nochmal vielen vielen vielen Dank für deine Hilfe, ohne dich wäre ich glaube ich in 2 Wochen immer noch dagesessen und hätte den Fehler gesucht.

Viele Grüße nach Wien und eine schöne Restwoche (is ja eh nimmer lang :-))
Michael

PicNick
12.05.2005, 09:12
Na, das hört man doch gerne. Du hast jetzt wahrscheinlich in den paar Tagen mehr über Controller und Feinheiten gelernt als sonst in einem halben Jahr.
Da sieht man auch eine Tücke in der Zusammenarbeit Compiler/Controller:
Der Compiler läßt unbenutzen Speicher auf Null --> Der Controller versteht Null als "NOP", läuft durch, findet irgendwas oder nicht, läuft über und fängt wieder bei Null an und dann find' er sicher was (meist INIT)
Fachmännisch sagt man da: "the result is undetermined & unpredictable"
Tip: unbenutzte ISR-Vectoren immer mit RETI belegen
Auf eine Gefahr möcht ich dich noch hinweisen: wenn der counter auch nur einmal aus dem Tritt kommt, egal warum, findet er nie wieder nach Hause und keiner merkt es. (Brown out, Peaks etc.)
Ich weiß nicht, wie heikel die Gerätefunktion ist ?

Ampfing
12.05.2005, 09:49
Du hast jetzt wahrscheinlich in den paar Tagen mehr über Controller und Feinheiten gelernt als sonst in einem halben Jahr.
Das kannst du aber laut sagen! Soviel wie ich über den Controller mittlerweile gelernt habe hätte mir wirklich niemand beibringen können - zumindest nicht nicht in 2 Tagen...

Zu den unbenutzten IR-Vektoten: Meinst du tatsächlich, ich soll für jeden möglichen Interrupt eine ISR schreiben, die nichts macht? Könnte man nicht auch 'einfach' an die Stelle der NOPs lauter RET schreiben? RETI bräuchte ich ja nur, wenn ich wirklich in eine ISR verzweige, weil die ja dann noch zusätzlich Info in den Stack legt, oder macht er das schon beim Jump?
Wie bringe ich ihn denn dazu lauter RET(I) an die Stellen im Speicher zu schreiben?

Hm, wie heikel ist die Gerätefunktion. Es handelt sich um ein Steuergerät für Starkstromtests an Telekommunikationsanlagen. Sprich der User stellt an einem Rechner ein führe diesen und jenen Test durch. Daraufhin übermittelt der Rechner dem Steuergerät die erforderlichen Daten (zu benutzenden Widerstand, Spannung etc.) und überwacht anschließend den Test, der von dem Steuergerät gesteuert wird.
Das Problem daran ist, dass er den Test überwacht, indem er selbst die Zeit misst und davon ausgeht, dass der Controller hin ist, wenn mehr als 1s länger die Spannung anliegt als es der Test verlangt. Eine andere Überwachungsmöglichkeit ist mir leider nicht eingefallen.
Was ich theoretisch machen könnte wäre, dass ich in den default-Zweig des switches in der ISR den counter wieder auf 0 setze und dem Rechner einfach nie anzeige, der Test wäre beendet, dann beendet er ihn. Ist wahrscheinlich gar keine schlechte Idee, danke für den Tipp!

Viele Grüße
Michael

PicNick
12.05.2005, 10:26
Hi,
NOP:
Es ist schwer, einen Prozessor zu helfen, der so richtig von Irgendwo ins Nirwana springt. Da bleibst du übrig.
ISR-Dummies:
Manche Compiler machen das selbst, indem sie die Vector-Tabelle prophylaktisch mit RETI füllen. Dadurch verbrauchen sie keinen zusätzlichen Platz.
Du kannst aber eine Sammel-ISR schreiben, die die NOPS vorher zusammensammelt und halt nix als RETI macht. Wichtig wär nur, daß er nicht wie im vorliegenden Fall eine FALSCHE ISR anspringt, das war ja das tödliche.
Überwachung: Timeout ist immer gut.

Also, Michael, keep codin' und wenn wieder was ist, rühr' dich, und wenn ich nix weiß, aufmunternd auf die Schulter klopfen kann ich immer !

Ampfing
12.05.2005, 10:47
Hallo Robert,

werde mich dann mal mit der Sammel-ISR versuchen. Schade eigentlich, dass Keil das nicht automatisch macht. Eigentlich finde ich die Software ziemlich gelungen.

Dann würde ich mal sagen, wir können unbesorgt diesen Thread beschließen :-)
Wird - leider - für ne Zeit lang mein letztes hardwarenahes Programmieren gewesen sein. Werde aber schaun, dass ich in die Richtung weiter machen kann, weil mir das echt total fasziniert und mir auch riesigen Spaß macht.
In diesem Sinne nochmal vielen Dank und hoffentlich bis bald (das würde heißen, dass ich wieder Probleme mit nem Controller habe, deswegen :-))

Viele Grüße

19.09.2005, 20:04
Ich weiß ehrlich gesagt nicht, warum er die Reihenfolge ändert.
Aber das ist doch alphabetisch, oder? (p kommt meines Wissens vor t und nach c)

Ich weiß nur, dass es jetzt endlich funktioniert und dass ich überglücklich bin, weil mein restliches Programm jetzt auch funzt!!!! \:D/

Was ich noch so an Ideen hatte, warum es nicht funktionieren könnte:
Wenn in time1 das msb gesetzt ist und er es in die Variable schiebt könnte ja irgendein Überlauf stattfinden, der durch einen dummen Zufall genau das IR-Bit des Interrupts setzt. Aber das kann eigentlich auch nicht sein, da das Register EXICON0 (mit dem IR-Bit) wo ganz anders liegt - irgendwas mit 0xaX (das X is auch noch ne Zahl...). Außerdem hätte das ja dann weg sein müssen, als ich nen anderen Interruptkanal probiert habe.
Was auch immer es ist, es bleibt wohl oder übel das Geheimnis des Controllers (und vielleicht auch von Infineon).

Nochmal vielen vielen Dank, dass du dir soviel Zeit für mein Problem genommen hast!!! Ich hoffe mal, ich habe dich nicht zu sehr vom Arbeiten abgehalten!?