|
|
View previous topic :: View next topic |
Author |
Message |
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
delay in RB interrupts |
Posted: Sat May 14, 2011 8:54 am |
|
|
Dear All, I have a problem in delay routine in RB0 interrupt. I am using the below code:
Code: |
#use rtos (timer=0, minor_cycle=100ms)
#use delay(clock = 20000000)
#task(rate=100ms,max=100ms)
void The_first_rtos_task ( )
{
output_high(Pin_D1);
delay_ms(500);
output_low(Pin_D1);
delay_ms(500);
}
#int_RB
void RB_isr(void)
{
disable_interrupts (int_RB);
if (input(PIN_B4))
{
output_HIGH(PIN_D2);
}
else
{
delay_ms(3000);
output_LOW(PIN_D2);
}
if (input(PIN_B5))
{
output_HIGH(PIN_D3);
}
else
{
delay_ms(3000);
output_LOW(PIN_D3);
}
if (input(PIN_B6))
{
output_HIGH(PIN_D4);
}
else
{
delay_ms(3000);
output_LOW(PIN_D4);
}
enable_interrupts (int_RB);
}
void main()
{
set_tris_A(0xFF);
set_tris_B(0xFF);
set_tris_C(0x80);
set_tris_D(0x01);
set_tris_E(0xFF);
port_b_pullups(TRUE);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_ccp1(CCP_OFF);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
ext_int_edge(L_TO_H);
enable_interrupts(INT_RB);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
RTOS_RUN();
} |
The function of this program is very simple. I have a "monitoring led" on pin D0 which is continuously blinking. Now when I press pin B4 "from Low to High", the led lights on and B5 and B6 makes the same. But I need to have a small delay during the release of the button.
I am notice that when I release the B4, 3 seconds will be delay, when I release the B5 there will be a 6 seconds delay and 9 seconds when I release the D6. More than this the compiler is giving me a warning "Interrupts Disabled during call to prevent re-entrancy: (@delay_ms2)
Your help is highly appreciated at this stage and appreciate if you guide me if I am implementing interrupts in the wrong way.
Thanks
Last edited by aaronik19 on Wed Mar 20, 2013 6:36 am; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat May 14, 2011 5:23 pm |
|
|
couple of issues...
do NOT use delays inside the ISRs !!
do NOT enable/disable ISR control from within the ISR...
do NOT enable ANY ISR that you do NOT have a handler( routine) for that ISR..
Don't use 'tris..' statements unless you're 100% sure that YOU'VE set the correct bits of the ports. Instead let the compiler handle it for you automatically. A LOT safer and easier, heck that's two reasons WHY you bought the compiler, right ??!! |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Sun May 15, 2011 1:05 am |
|
|
thanks temtronic for your tips. So how I can modify this program to work correctly? If I want to make a delay before Code: | output_LOW(PIN_D2); | how I should make the code? Once again thanks for your help |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun May 15, 2011 2:17 am |
|
|
For an exact timing, you would want to start a timer in the RB ISR and perform the delayed pin action in the timer ISR. 3 sec delay is however pretty long. If you don't need the delay accurate up to the ms, a continuous tic timer is probably the better way to schedule timed actions. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun May 15, 2011 3:58 am |
|
|
Use the RTOS.
When you see the event you want in the RB interrupt, set a global flag, and exit. Nothing else.
Have an RTOS task running perhaps every half second, which _when it sees the flag go true_, clears the flag, and sets a counter to '6'. If when it is called, the counter is non zero, it decrements the counter. When the counter gets to zero, then change the pins you require.
While you are in the interrupt handler _nothing else_ is running. General rule of thumb, is that the interrupt handler should _only_ do the job associated directly with the interrupt, and get out ASAP. If you want a delay, use a hardware timer - as FVM says, (or as you have the RTOS running, this), to generate the delay.
Best Wishes |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Sun May 15, 2011 4:14 am |
|
|
thanks for your replies, but I got confused. I used RTOS to blink an LED as an indicator that the processor is running. There are no relationship with the interrupt. Can you please help me to initialize timer inside ISR? Please show a piece of code here at least the basic and I will advance the rest. Once again thanks for your help |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun May 15, 2011 3:10 pm |
|
|
The RTOS does things at intervals, using a timer. This is the basis of the RTOS. So you can just add an RTOS task, that at an interval, as already described, checks a global flag, and after a certain number of iterations (for the time required), sets the pin you require.
If you want to do it with a separate timer, you don't have to 'initialise timer inside ISR'. You just have a 'tick' event running at some convenient interval, which again monitors global variables to say when it is to do something.
For example, using your existing RTOS task:
Code: |
//existing processor setup and RTOS setup here
int8 drop_d2=0;
int8 drop_d3=0;
int8 drop_d4=0;
void The_first_rtos_task (void) {
static int1 toggle=true;
static int8 toggle_ctr=0;
if (toggle_ctr) {
--toggle_ctr;
}
//again don't delay in the RTOS task - it is being called every 100mSec
else {
output_bit(Pin_D1,toggle);
toggle^=1;
toggle_ctr=4;
} //this will toggle the pin every five RTOS calls
//These will do nothing, _until_ the counters are non zero.
if (drop_d2) {
--drop_d2;
if (drop_d2==0) output_low(PIN_D2);
}
if (drop_d3) {
--drop_d3; //decrement only if non zero
if (drop_d3==0) output_low(PIN_D3);
}
if (drop_d4) {
--drop_d4;
if (drop_d4==0) output_low(PIN_D4);
}
}
#int_RB
void RB_isr(void) {
//Not needed or wanted disable_interrupts (int_RB);
if (input(PIN_B4)) {
output_HIGH(PIN_D2);
}
else {
drop_d2=30; //Drop in 30 ticks of the RTOS
}
if (input(PIN_B5)) {
output_HIGH(PIN_D3);
}
else {
drop_d3=30;
}
if (input(PIN_B6)){
output_HIGH(PIN_D4);
}
else {
drop_d4=30;
}
}
//existing main here
|
The same applies with the RTOS, as with the interrupt handler, but to a lesser extent. Your RTOS call interval, is 100mSec, so you should ensure that the RTOS functions do _not_ take longer than a small fraction of this time, or RTOS accuracy will vanish.
Best Wishes |
|
|
|
|
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
|