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

In using multiple external interrupts.

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



Joined: 06 Oct 2013
Posts: 4

View user's profile Send private message

In using multiple external interrupts.
PostPosted: Sun Oct 06, 2013 9:21 pm     Reply with quote

Hi, I am studying about external interrupts with PIC18F4580. When I used only one external interrupt, it worked anyway. And also worked for multiple external interrupts. What is problem is that my device reads both rising and falling edge though I selected only one edge. The following is my code. Ignore the Korean comment.

Code:

#include "set4580.h"
#byte p_d = 0xf83 //defining Port_d, (portD의 레지스터 주소가 0xf83이다.)
#byte p_b = 0xf81
#byte intcon = 0xff2 //defining timer1 16비트,registers which are used to control interrupt operation.
#byte intcon2 =0xff1
#byte intcon3 =0xff0
int8 led;


#int_ext //#int_xxxx는 인터럽트.  timer1 인터럽트 소스 활성화 >Timer 1 overflow
ext_isr() //인터럽트가 발생하면.
{

 led=(led>>1)|(led<<7); //오른쪽으로 비트이동
 p_d=led;
 delay_ms(300);
 ext_int_edge(0,L_TO_H);
 bit_clear(intcon,1); //flag down
}

#int_ext1
ext1_isr()
{

led=(led>>7)|(led<<1); //왼쪽으로 비트이동
p_d=led;
delay_ms(300);
ext_int_edge(1,L_TO_H);
bit_clear(intcon3,0); //flag down
}


void main()
{

setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
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);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);


// TODO: USER CODE!!
set_tris_d(0x00); //output으로 설정
set_tris_b(0x03);

enable_interrupts(int_ext);    //int_ext 인터럽트 활성화 >인터럽트 발생 X
enable_interrupts(int_ext1);
bit_set(intcon2,6);//ext_int_edge(0,L_TO_H); 
bit_clear(intcon2,5);//ext_int_edge(1,H_TO_L);
enable_interrupts(global);     //global 인터럽트 허가>>이 명령 이후부터 인터럽트가 발생
led=0b11110111; //초기값 설정
p_d=led;
while(1){};
}

I used two external interrupts. And this interrupts is triggered by external two switches I can toggle manually. The reason why I inserted 'delay' in service routine is that without the delay, maybe because of chattering of the switch interrupts were triggered several times in one switch toggle.

Anyway, the main point of this post is that 'Why this device's interrupts are triggered both rising and falling edge'.
Ttelmah



Joined: 11 Mar 2010
Posts: 19347

View user's profile Send private message

PostPosted: Mon Oct 07, 2013 9:28 am     Reply with quote

Code:

enable_interrupts(int_ext_L2H);    //int_ext 인터럽트 활성화 >인터럽트 발생 X
enable_interrupts(int_ext1_H2L);
enable_interrupts(global);     //global 인터럽트 허가>>이 명령 이후부터 인터럽트가 발생


I'd suggest you don't change the edge in the interrupt (this can give erratic triggers). Instead start a timer, and retest the bit an interval later using the timer, instead of the delay.

Alternatively, since this is a switch (and not something that really needs the speed of an interrupt response), why not just poll all the pins in a 100Hz timer for example?. If it is set, turn on a flag, and if it is set, and the flag is on, then change your LED's.

Best Wishes
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 2:20 am     Reply with quote

Assuming you are using mechanical switches, it is most likely the contacts are chattering.
In that case, you can get triggering on both opening and closing the contacts.

Have a look with a 'scope to confirm.

Ttelmah has suggested better alternatives, (you need some form of debounce).

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19347

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 3:26 am     Reply with quote

Totally.

This was what I was talking about with the 'flag', but made very unclear.

You set a flag (for each switch) when they are seen, then on the next 'tick', if the flag is set, and the switch is still made, signal 'switch'. If the switch goes off, you clear the flag and start again.
So it has to be made for two successive 'ticks' before it is accepted.

Best Wishes
sonyoungdong



Joined: 06 Oct 2013
Posts: 4

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 3:55 am     Reply with quote

To Ttelmah and Mike
Thanks to your reply.

Still, I wonder something. I set each switch's edge with
Code:

bit_set(intcon2,6);  //same with > ext_int_edge(0,L_TO_H) 
bit_clear(intcon2,5);//same with > ext_int_edge(1,H_TO_L)

And to avoid chattering, I also used
Code:
delay_ms(300);


And to reset the flag, I used
Code:
bit_clear(intcon,1);
bit_clear(intcon3,0);


But Ttelmah refered
Quote:

You set a flag (for each switch) when they are seen, then on the next 'tick', if the flag is set, and the switch is still made, signal 'switch'. If the switch goes off, you clear the flag and start again.
So it has to be made for two successive 'ticks' before it is accepted.

I didn't set a flag with "bit_clear(intcon,1)" but reset it. My device works well. What I want to know is why external interrupts occur every 'TICK'. I set only one edge for each switch. So interrupt must occur every two 'ticks'. But it doesn't Sad

Thanks for your help.
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Oct 08, 2013 10:26 am     Reply with quote

You're not getting it. (Or at least you don't seem to be.)

When you close a switch you may get a waveform like this one:-

Code:
Close switch
-----      -   -
     |    | | | |
      ----   -   ------------------------------------------------------------

And on opening:-

Code:
Open switch
      ----   -   ------------------------------------------------------------
     |    | | | |
-----      -   -

Each operation of the switch produces both +ve & -ve edges.

One way to debounce is to sample the switch state at intervals.
The interval must be longer than the bounce period, and shorter than the quickest switch operation.
When the switch is in the same state for two successive samples, you have a valid switch status change.

Mike

PS

If you are going to persist with edge triggers, and only want operate from say +ve edges you could:-

1) Set both edges active.
2) Respond to +ve edge and disable interrrupts for a fixed period.
3) Respond to -ve edge by disabling interrupts for same fixed period as +ve edge and nothing else.
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