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:
Code:
//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:
Code:
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:
Code:
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
Lesezeichen