|
|
View previous topic :: View next topic |
Author |
Message |
sonyoungdong
Joined: 06 Oct 2013 Posts: 4
|
In using multiple external interrupts. |
Posted: Sun Oct 06, 2013 9:21 pm |
|
|
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: 19515
|
|
Posted: Mon Oct 07, 2013 9:28 am |
|
|
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
|
|
Posted: Tue Oct 08, 2013 2:20 am |
|
|
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: 19515
|
|
Posted: Tue Oct 08, 2013 3:26 am |
|
|
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
|
|
Posted: Tue Oct 08, 2013 3:55 am |
|
|
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
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
Thanks for your help. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Oct 08, 2013 10:26 am |
|
|
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. |
|
|
|
|
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
|