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 CCS Technical Support

Problem when using both external interrupt with low voltage

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



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

Problem when using both external interrupt with low voltage
PostPosted: Fri Aug 29, 2014 2:25 am     Reply with quote

Hi everybody.
I'm have problems when using both external interrupt with high-low voltage interrupts.
In my project, I used: int_ext0, int_ext1, int_rb and int_lowvolt of PIC18F4680, CCSC complier ver 5.021.
The trouble occurs when the circuit has an interrupt on int_ext1 pin, my program go to int_ext1 and int_lowvolt, the right is only run to int_ext1.
I referenced some topic in site but it not help me to solve this problem.
Because the code is long, so that i cutout some body of my program.

- config fuse and lib:
Code:
#include "18F4680.h"                                                                                                                   
#fuses H4,PUT,PROTECT,NODEBUG,NOLVP,NOWDT,NOPBADEN,MCLR,BROWNOUT,BORV21
#use delay(clock=40000000)                                                                         
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, errors) 


- int_ext0 program:
Code:

#int_ext
void ngat_counter(void)                                       
{                                                                                       
   output_toggle(PIN_E0);
   delay_ms(50);                         
   clear_interrupt(int_ext);                                           
   update_lcd=1;
     
   if(en_count_ac==1)   {  count_ac++;}                                               
   else                                                                                         
   {               
      output_high(PIN_C5);
      leds_on;                                                                                                         
   }

   if(detect_eepr==1)                       
   {                                       
      detect_eepr=0;                   
      save_tag_eepr=1;                                     
   }                                                                                                 
}


- int_ext1 program:
Code:

#int_ext1                               
void ngat_sw(void)                       
{                                             
   while(input(PIN_B1)==0);   
   delay_ms(50);
   count_knife++;
   output_toggle(PIN_E0); 
   update_lcd=1;
}


-int_lowvolt program:
Code:

#int_lowvolt
void ngat_hlvd(void)

   leds_on;
   if(save_tag_eepr==1)
   {
      write_ext_eeprom( 500, make8(count_knife,3) );
      write_ext_eeprom( 501, make8(count_knife,2) );
      write_ext_eeprom( 502, make8(count_knife,1) );
      write_ext_eeprom( 503, make8(count_knife,0) );

      pt_eepr_hi= read_ext_eeprom(0);     
      pt_eepr_lo= read_ext_eeprom(1);
      pt_eepr   = make16(pt_eepr_hi, pt_eepr_lo);   
   
      if(pt_eepr==0) {  pt_eepr=20;}             
     
      pt_eepr++;                                                                                                                                       
      if(chk_offset_pc==1) write_ext_eeprom(pt_eepr, 0X40);   
      else write_ext_eeprom(pt_eepr, 0X00);                           
                                                                       
      pt_eepr++;                                               
      write_ext_eeprom(pt_eepr, make8(count_ac,2));                 
      pt_eepr++;                                                             
      write_ext_eeprom(pt_eepr, make8(count_ac,1));
      pt_eepr++;                                               
      write_ext_eeprom(pt_eepr, make8(count_ac,0));                                                           
                                                                           
      pt_eepr++;                                                                                             
      write_ext_eeprom(pt_eepr, make8(app_code,2));     
      pt_eepr++;                                                   
      write_ext_eeprom(pt_eepr, make8(app_code,1));
      pt_eepr++;
      write_ext_eeprom(pt_eepr, make8(app_code,0));
     
      write_ext_eeprom(0, make8(pt_eepr,1));
      write_ext_eeprom(1, make8(pt_eepr,0));
   }                                     
   save_tag_eepr=0;
}


- int_rb program:
Code:

#int_rb
void ngat_rb()
{
   temp_read =input(PIN_B5);
   clear_interrupt (int_rb);
   delay_ms(100);
   check_so_sa=1;                                             
}


- config interrupt in main program:
Code:


#use delay(clock=40000000)
void main(void)
{                                                                                                                                                           
   set_tris_a (0x3F);  //0x20               
   set_tris_b (0x23);   //0x21                   
   set_tris_c (0x87);                                                                                                       
   set_tris_d (0x00);      // lcd_data   
   set_tris_e (0x00);      // led_disp_stt 
   
   delay_ms (500);   
     
   buzz_off;                                                                                                           
   lcd_bl_off;                                       
                                                                               
   set_timer0(62);                                                               // setup timer0: 5ms 
   setup_timer_0 (RTCC_INTERNAL | RTCC_8_BIT | RTCC_DIV_256);                                                   
   
   set_timer1(62);                                                               // setup timer1: 50ms 
   setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);     
                                                   
   set_timer2(0);                                                                // setup timer2_limit_PIN_TX_485 : 5ms F_cystal=40MHZ
   setup_timer_2 (T2_DIV_BY_16,195,16 );   
   
   temp_read =input(PIN_B5);                                         
   clear_interrupt (int_rb); 
   
   setup_low_volt_detect( LVD_TRIGGER_BELOW | LVD_40 );
   delay_ms(1000);
   clear_interrupt ( int_lowvolt);                                               
   enable_interrupts (int_lowvolt);
   
   
   
   ext_int_edge (0, H_TO_L) ;                                                   
   clear_interrupt (int_ext); 
   
   ext_int_edge (1, H_TO_L) ;                                                   
   clear_interrupt (int_ext1);     
   
   enable_interrupts (int_rb);
   enable_interrupts (int_ext1);                                                                       
   enable_interrupts (int_rda);
   enable_interrupts (global);
                                                                                                             
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   lcd_init();                                                                                                   
   init_ext_eeprom();                                                            // Init Ext EEPROM 24C128
   delay_ms(100);   

   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   pt_eepr_hi= read_ext_eeprom(0);                     
   pt_eepr_lo= read_ext_eeprom(1);                                           
   if(pt_eepr_hi !=0xff && pt_eepr_lo !=0xff)   
   {
      pt_eepr   = make16(pt_eepr_hi, pt_eepr_lo);                                   
   } 
   
   lcd_gotoxy(1,1);                                                                                 
   printf(lcd_putc,"%lu",pt_eepr);
   delay_ms(500);
                                           
   if(pt_eepr >=27 )                                                                                             
   {   
      count_knife3= read_ext_eeprom(500);
      delay_ms(10);   
      count_knife2= read_ext_eeprom(501);
      delay_ms(10);
      count_knife1= read_ext_eeprom(502);
      delay_ms(10);
      count_knife0= read_ext_eeprom(503);
      delay_ms(10);
      count_knife = make32(count_knife3, count_knife2, count_knife1, count_knife0);   
     
      count_ac2 = read_ext_eeprom( pt_eepr -5);                           
      count_ac1 = read_ext_eeprom( pt_eepr -4);                                   
      count_ac0 = read_ext_eeprom( pt_eepr -3);                 
                                               
      app_code2 = read_ext_eeprom( pt_eepr -2);
      app_code1 = read_ext_eeprom( pt_eepr -1);       
      app_code0 = read_ext_eeprom( pt_eepr);         
                                                             
      count_ac_eepr = make32(0, count_ac2, count_ac1, count_ac0);
      app_code_eepr = make32(0, app_code2, app_code1, app_code0);
                                             
      if (count_ac_eepr != 0 && count_ac_eepr <200000 )   {  count_ac = count_ac_eepr;} //   
      if (app_code_eepr != 0 && app_code_eepr <99999 )    {  app_code = app_code_eepr;} //
      detect_eepr=1;                                                             
      status_disp=1;
      en_count_ac=1; 
   }                                                                                                                               
   else                                                                 
   {       
      status_disp=3;
      en_count_ac=0;
      pt_eepr=0;
      count_ac=0;
      app_code=0;
      detect_eepr=0;                                                                                                                     
   }
                                                                             
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   can_init();
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   
   for(i_count=0; i_count<5; i_count++)  {  str_id_4key[i_count] = 0;}     
   for(i_count=0; i_count<11; i_count++)   
   {
      str_id_10key[i_count] = 0;     
      str_rs232[i_count] =0;
   }   
   
   xoa_str_name1();
   xoa_str_name2();                                                                                                         
   read_id();
       
   lcd_bl_on;   
   lcd_gotoxy(1,1);
   printf(lcd_putc,"NODE %03lu",id_addr);   
                                                     
   lcd_gotoxy(1,2);
   printf(lcd_putc,"%lu",app_code_eepr);                   
                                                           
   lcd_gotoxy(9,2);
   printf(lcd_putc,"%lu",count_ac_eepr); 

   lcd_gotoxy(12,1);
   printf(lcd_putc,"%lu", count_knife);     

   delay_ms(1500);                                                                                           
   disp_lcd();                     
   lcd_bl_off;                                                                                                                 
   leds_off;   
   
   enable_interrupts (int_ext);
   for(;;)
   {
   -
   -
   }
   


I think my program have a conflict between int_ext1 vs int_lowvolt, but i still find a errors in my code.
Do you have a way to solve this problem?
Pls help me.
Thanks.
_________________
Begin Begin Begin !!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Aug 29, 2014 3:35 am     Reply with quote

The core reason is the simple one. Using a delay in the ISR. Treat this as if it carries a risk of ebola....

The key point is that ISR handlers should be _quick_. If you want a delay, then set a flag, and use a timer to give the delay.

A search here will find this repeated again and again. In fact if you search for the keyword 'mantra', I know you will find several posts.

You may get an answer then saying 'use high priority interrupts', but this won't work in this case, since INT_EXT, is always high priority if this is done.

Have a nice little 'tick' interrupt at something like 50mSec, and use this to provide your delays.

As it stands, if pin B1 is low, it'll stay in this ISR for ever.
_All_ your interrupts display similar versions of bad programming.

Consider a completely different approach. Have a tick interrupt as already mentioned, and have this check all the pins, and move through a state machine to give all the functions required. Advance the counter for delays, and the state for different pin patterns, and immediately exit.
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Sep 02, 2014 10:07 pm     Reply with quote

Thanks u.
I've modified all interrupt program by remove delay_ms() function and replace by loop delay.
I don't think i make a errors between int_ext1 with int_lowvolt.
I afraid CCS have a errors when compiling?
_________________
Begin Begin Begin !!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Wed Sep 03, 2014 12:40 am     Reply with quote

a 'loop delay', is just as bad if it is inside the interrupt.

The point is you _must_ get out of the interrupt handler ASAP.

As I said, use a single tick interrupt, and sample your pins in this. Whhen you want delays set a counter, and immediately exit. Next time the timer ticks, decrement the counter and exit.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Sep 03, 2014 10:02 am     Reply with quote

If you are convinced it's a CCS problem, write a short, complete, compilable program which proves the point.

I took one look at the length of your code and decided to ignore it.

Mike
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Sep 03, 2014 10:35 am     Reply with quote

also

you CANNOT write to the eeprom inside any ISR !! That too is very.very bad coding.NO delays( and writing to the eeprom is a HUGE delay...) are acceptable inside any ISR.

Simply set a 'flag' and get out ASAP.
within 'main()' do code based on the 'flags' set within the ISRs.


hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Wed Sep 03, 2014 10:43 am     Reply with quote

Disagree just fractionally.

Power failure, is the _one_ interrupt where you can/do write to EEPROM. However you also need to work out how you are going to recover if the power goes back on, and the 'hold up' time of your supply relative to the write time.

The big problem before doing this though, is that it's never going to get to the power fail interrupt, since it is often sitting for ages in other (unnecessary) interrupts.....
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Wed Sep 03, 2014 7:53 pm     Reply with quote

Thanks you so much.
I think I will edit my program as all our's advices, can be as follows:
- write a delay function using "for" loop.
- change delay function of CCSC by my delay function in ISR program.
- move ISR program to main loop program by check flag interrupts.
- repair ISR ext interrupts.
The first, I write a delay function using for loop to create a delay 10ms, but real it's seem longer. I can't calculate exact time delay creat in MPLAB, so I used help in CCSC and saw it take 0.4us with plus operation, with loop 25000 times, it makes 10ms.
Code:

void delay_10_milisec(unsigned int8 ms_delay)
{
   unsigned int16 count_delay=0x61A8;
   unsigned int8 count_loop=0;
   for(count_loop=0; count_loop<ms_delay; count_loop++)
   {
      while (count_delay--);
      count_delay= 0x61A8;
   }
}

Random while editing my program, I detection bug of me in setup low high voltage interrupt:
Code:

   setup_low_volt_detect( LVD_TRIGGER_BELOW | LVD_36 );                         
   IRVST_BIT = 0;
   delay_ms(1000);
   clear_interrupt ( int_lowvolt);                 
   enable_interrupts (int_lowvolt);

In above code, if i setup LVD_40, when ext1 interrupts occur, it also make high-low voltage occur. And, If I set LVD < 4 volt, i work finally. Normal, the power supply for PIC18F4680 is nearly 4.5->4.6V.
I checked again my circuit and not saw bugs in this.
I uploaded this circuit to my post to clearly, I hope ur help me fix it.
Thanks so much.

_________________
Begin Begin Begin !!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Thu Sep 04, 2014 11:40 am     Reply with quote

You are just ignoring the key point:

"The point is you _must_ get out of the interrupt handler ASAP. "

Using your delay, instead of the CCS delay, makes no difference. You are still delaying in the ISR.
This is equivalent to hitting yourself on the head with a sledgehammer. Not likely to lead to working code.

If you want something to happen an time 'after' an edge is seen, program a timer with the required timeout, and leave the interrupt handler immediately. Then when this timer triggers and interrupts, do the other half of your job.

However the whole thing is much simpler if you just have a 'tick' interrupt, and do the jobs needing timing in this. The approach is over complicated, and is causing your problems.
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