CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

RB-Interrupt problem when occuring the second time

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
_olaf_



Joined: 24 Feb 2005
Posts: 32

View user's profile Send private message

RB-Interrupt problem when occuring the second time
PostPosted: Tue Feb 28, 2006 1:11 am     Reply with quote

Hi,

I have a small problem with my program. In this program I want to switch different voltages on. With the RB_Interrupts I want to check if everything is working correct.
When the program starts from a power-on reset everything is ok. The initialisation is working and the outputs are set. If I make an interrupt on the RB-Ports (e.g. RB4) then the controller goes into the RB_ISR(). After that the controller goes to the next sleep operation but does not wake up again when an RB-Interrupt occurs. I can do what I want, but there is no possibility to wake it up. Does somebody have an idea where the problem could be.

MPLAB V7.30
Compiler PCM 3.223

Olaf

Code description


In the
RB_isr(char i) {} -> I get the portnumber of the RB-Interrupt and printout a corresponding errormessage.

Initialisierung() -> makes the initilisation of the PIC

Fehlermeldung(int e) -> print out an errormessage

Power_On_PIC() -> check the voltage of the PIC (Voltage regulator has a errorflag which is set at voltages below 5V, used PIC is 16LF84)

Power_On_Wandler() -> switching on the other voltages

Code:
#include "CCD_SPG1.h"
#int_RB

int EF[6]; // ERRORFLAGS

// declare functions
void Initialisierung(void);
void Fehlermeldung(int e);
void Power_On_PIC(void);
void Wait(unsigned int t);
void RB_isr(char i);

//PORT_B Interrupt Service Routine
RB_isr(char i)
{
unsigned int statusregister;
// statusregister=_STATUS;
DISABLE_Interrupts(INT_RB);
i=0xFF;
i=0x00;
i=INPUT_B();
switch (i) {
Case 0x10: OUTPUT_B(0x00);
Fehlermeldung(2);
break;
Case 0x20: OUTPUT_B(0x01);
Fehlermeldung(5);
break;
Case 0x40: OUTPUT_B(0x01);
Fehlermeldung(4);
break;
Case 0x80: OUTPUT_B(0x01);
Fehlermeldung(5);
break;
}
ENABLE_Interrupts(GLOBAL);
CLEAR_Interrupt(INT_RB);
ENABLE_Interrupts(INT_RB);
}

// initialise Controller
Initialisierung()
{
DISABLE_Interrupts(INT_RB); // PORT-B Interrupts disable
DISABLE_Interrupts(INT_EXT); // Externer Interrupt disable
DISABLE_Interrupts(GLOBAL); // globel Interrupt disable
OUTPUT_A(0x00); // Testsequence switching LED on/off
OUTPUT_A(0b00110); //
delay_ms(500); //
OUTPUT_A(0b00000);
delay_ms(500);
OUTPUT_A(0b00110);
delay_ms(500);
OUTPUT_A(0b00000);
OUTPUT_B(0x00); // End Testsequence
SET_TRIS_A(0x11); // Configure I/O
SET_TRIS_B(0xF0);

EF[0]=0; // preset errorflags
EF[1]=0;
EF[2]=0;
EF[3]=0;
EF[4]=0;
EF[5]=0;
}

// output Errormessages
Fehlermeldung(int e)
{
switch (e) {
Case 1: printf("Something\n");
break;
Case 2: printf("Something\n");
break;
Case 3: printf("Something\n");
break;
Case 4: printf("Something\n");
break;
Case 5: printf("Something\n");
break;
Case 6: printf("Something\n");
break;
}
printf("Something\n");
}

Wait(unsigned int t)
{
Delay_ms(t);
}

// Check Voltage for UB PIC
Power_On_PIC()
{
int i, j, k, l;
DISABLE_INTERRUPTS(INT_RB); // PORT-B Interrupts disable
Check_UB_PIC: // label for testloop
if ( (Input(ERROR_UB_PIC)) && (EF[0]<=5) ) // check UB-PIC
{
Wait(100); // wait 100ms
EF[0]++; // increment ERROR-Flag
if (EF[0]==5)
{
Write_EEPROM(0, EF[0]);// write value to eeprom
Fehlermeldung(1); // test for 5 times. more then 5 times false -> exit
goto Power_Off;
}
goto Check_UB_PIC;
}

else
{
EF[0]==0;
printf("everything o.k.");
}

Power_Off:
ENABLE_Interrupts(GLOBAL);
ENABLE_INTERRUPTS(INT_RB);
}


//Ausgangsspannungen einschalten
Power_On_Wandler()
{
DISABLE_INTERRUPTS(INT_RB);

if (EF[0]==0) //prüfen ob UB_PIC ok
{
Output_Bit(CCD_Power_On, 0); // switch on voltage
Output_Bit(SHTDN_5V_POS, 0); // switch on voltage
}

Check_UB_5V: // label for testloop

if ( (Input(ERROR_5V_Pos)) && (EF[1]<=5) ) // check voltage
{
Wait(100); // Warte 100ms
EF[1]++; // increment ERROR-Flag
if (EF[1]==5) // test for 5 times. more then 5 times false -> exit
{
Write_EEPROM(1, EF[1]); // write value to eeprom
Output_Bit(SHTDN_5V_POS, 1); // switch voltage off
Fehlermeldung(2); // test for 5 times. more then 5 times false -> exit
goto Power_Off;
}
goto Check_UB_5V; // next try
}
else
{
EF[0]==0;
Output_Bit(SHTDN_5V_POS,0);
printf("something");
}
Power_Off:
ENABLE_Interrupts(GLOBAL);
ENABLE_INTERRUPTS(INT_RB);
}



void main() {
int x;
Initialisierung();
ENABLE_Interrupts(GLOBAL);
Power_On_PIC();
Power_On_Wandler();
loop:
sleep();

x=INPUT_B();
if (INT_RB!=1)
{
RB_ISR(x);
}
goto loop;

}

*.h-file:

#include <16LF84A.h>
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT
#define ERROR_UB_PIC 40
#define POS_UB_OK 41
#define NEG_UB_OK 42
#define SHTDN_5V_POS 48
#define SHTDN_15V_POS 49
#define CCD_POWER_ON 50
#define SHTDN_7V_NEG 51
#define ERROR_5V_POS 52
#define ERROR_15V_POS 53
#define UB_15V_NEG_OK 54
#define UB_15V_POS_OK 55
#use rs232(baud=9600,parity=N,xmit=PIN_A3,rcv=PIN_A4)
Ttelmah
Guest







PostPosted: Tue Feb 28, 2006 4:26 am     Reply with quote

Do _not_ enable the global interrupt inside the ISR. This is a 'no no' on the PIC.
You don't need to disable interrupts either.
Basically,when an interrupt occurs, the _hardware_ disables the global interrupt flag. This flag is automatically re-enabled, on the return from the global interrupt handler, _when the instruction completes_.
This prevents interrupts interrupting themselves, and prevents recursive calls to the handler routines (which the chip does not support, having no software stack).
Now if you re-enable the global interrupt flag, inside the interrupt handler, you have killed this protection, and an interrupt can now occur inside the interrupt handler. This will destroy the contents of the registers, and result in values being destroyed.

Best Wishes
_olaf_



Joined: 24 Feb 2005
Posts: 32

View user's profile Send private message

PostPosted: Wed Mar 01, 2006 1:17 am     Reply with quote

Hi,

I tried it with deleting the Code for disabling the interrupts. But it was the same effect. When I debug the program in single step mode, something strange happens.

When I come to

if (INT_RB!=1)
{
RB_ISR(x);
}

in main, the TRISB is changed to 0xFF (all input)

when I continue stepping through the program in the RB_isr at the case command

RB_ISR()
{
...
switch (i) {
Case 0x10: OUTPUT_B(0x00);
Fehlermeldung(2);
break;
Case 0x20: OUTPUT_B(0x01);
Fehlermeldung(5);
break;
....
}

the TRISB is changed to 0x00 (all output)

So it's clear that the controller doesn't react at the second PortB-Change. But what is the reason for this? Another problem is the following. I have an updatet version (Version 3.232) of the Compiler. If I want to compile it with this Version I get the message that the RB_ISR()-description has changed and it generates an error.

Any idea what's the problem with this?

Olaf
_olaf_



Joined: 24 Feb 2005
Posts: 32

View user's profile Send private message

PostPosted: Thu Mar 02, 2006 2:29 am     Reply with quote

I checked the program with the updated compiler verison (3.232) but it is still the same behaviour. When I go into the RB_ISR() the TRISB is changed and so the RB_ISR can not react on a PortB-Change. I searched in the datasheet of the controller and the examples here in the newsgroup, but I didn't find something about this problem. Does anybody have a explanation for this?

Olaf
mpfj



Joined: 09 Sep 2003
Posts: 95
Location: UK

View user's profile Send private message Send e-mail Visit poster's website

Re: RB-Interrupt problem when occuring the second time
PostPosted: Thu Mar 02, 2006 5:17 am     Reply with quote

(1) You should *not* actually call the rb_isr() routine yourself, as you do in main(). The interrupt handler will do this when you use the #int_rb directive.

(2) I would now the #int_rb directive to just before the isr routine.

(3) Remove the interrupt enable / disable code (as stated by Ttelmah).

(4) Add a "default" clause to your switch() statement.

(5) You cannot pass an variables to an isr, because of item (1).

(6) Are you testing for individual bit changes, or only specific bit combinations of PORTB ? For individual bit changes, you will have to use the bit_test() command.

... e.g. ...
Code:

//PORT_B Interrupt Service Routine
#int_RB
void rb_isr(void)
{
   unsigned int i;
   unsigned int statusregister;

   // statusregister=_STATUS;
   i=INPUT_B();
   switch (i) {
   Case 0x10:
      OUTPUT_B(0x00);
      Fehlermeldung(2);
      break;
   Case 0x20:
      OUTPUT_B(0x01);
      Fehlermeldung(5);
      break;
   Case 0x40:
      OUTPUT_B(0x01);
      Fehlermeldung(4);
      break;
   Case 0x80:
      OUTPUT_B(0x01);
      Fehlermeldung(5);
      break;
   default:
      break;
   }
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group