View previous topic :: View next topic |
Author |
Message |
engineer_1
Joined: 27 Mar 2007 Posts: 6
|
interrupt |
Posted: Thu Jul 12, 2007 2:18 am |
|
|
hi everybody,
i am new to interrupts so i am trying to learn it.i use 16f877.and b port interrupts(b4-b7).i want to connect a button to rb4 as interrupt button.when i press this button i want my led to be low which is connected to c0 pin.
i tried so much but cant work this simple example.i will be pleased if anyone helps
best regards
sefa |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 12, 2007 2:46 am |
|
|
There are quite a lot of 'parts' to this.
The first is that if you just want detection of a single button being pressed, you would be much better to use RB0. The 'reason' is that th 'B changed' interrupt on the high bits will work on all of them (so if one of the other inputs changes, this too will trigger the interrupt), and also that this interrupt triggers on 'change', so will trigger on the key being released, as well as being pressed.
The second thing is that you will need the signal to change from the button press. The easiest way to do this, is to enable the port B 'pullups', which pull the lines towards the Vdd rail, and have the button connected to Vss. Unless you have this sort of woring, nothng much is going to happen...
The third returns to the first. Because this is an interrupt on 'change', the code is relatively more complex than the simple code for the B0 interrupt. There are quite a few things that have to be done to make this work.
Without the headers for your processor, and the other initialisations, you will need something like:
Code: |
int8 old_b; //global variable to hold the last portB value
int1 LEDON=false;
#define LED PIN_C0
#INT_RB
void changed_int(void){
//routine called when any of the high four bits change
int8 tempb;
tempb=input_b(); //you _must_ read portB here otherwise the
//interrupt will continuously trigger.
//Now you need to look for B4 being low, while the 'old' B4 is high
if (bit_test(tempb.4)==0) {
//B4 is low
if (bit_test(old_b.4)==1) {
//old value was high
output_low(LED);
LEDON=TRUE;
}
}
//Update 'old' value
old_b=tempb;
}
void main(void) {
//other initialisation as needed here
port_b_pullups(TRUE); //enable the pullup resistors
delay_us(1); //allow time or the lines to pull high
old_b=input_b(); You _must_ read the port here, or there may be an
//extra interrut at the start.
output_high(LED); //initialise the LED pin
//Now enable the interrupts
clear_interrupts(INT_RB);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
while (TRUE) {
//Loop here, doing whatever else your program needs
//As a 'demo', I reset the LED pin after on second, so you can see
//how it works.
if (LEDON) {
//here the LED has been triggered
delay_ms(1000);
output_high(LED); //turn it off after one second
}
}
}
|
Except that this clears the LED automatically after one second, so you can see what is happening, and lacks the things like delay statements etc., this matches what you have asked for.
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 12, 2007 2:55 am |
|
|
Apologies:
Wiring, not 'woring', and ',', not '.', in the bit_test statements.
Best Wishes |
|
|
kkatesuda
Joined: 09 Sep 2006 Posts: 8
|
|
Posted: Thu Jul 12, 2007 3:51 am |
|
|
Wow Thank you very much. It give good idea for me to user "interrupt on change" |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 12, 2007 4:36 am |
|
|
Another fault. The 'if(LEDON)' code, should reset 'LEDON', or it'll keep being called even if the LED is off....
I needed my caffeine fix at the time.
Best Wishes |
|
|
Guest
|
|
Posted: Thu Jul 12, 2007 7:39 am |
|
|
first of all thank you very much for your explanations.i understood basic working of interrupt by your codes.but i have some questions.
for example in normal program led blinks by 1 seconds(1 second high,1 second low ).then if i press interrupt button, i want my led to be off for 5 seconds and then turn to normal program.may be your program does this but i cant solved.(you say it blinks in every second).
i will be pleased if this my basic question will be answered.
best regards
sefa |
|
|
engineer_1
Joined: 27 Mar 2007 Posts: 6
|
|
Posted: Thu Jul 12, 2007 7:40 am |
|
|
i am so sorry.last message was mine.i have asked it.but forget to be logined before sending message. |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 12, 2007 11:58 am |
|
|
You didn't say anything about flashing the LED originally...
What I'd do, is have a global int16 counter called (say) counter.
Then in the 'while' loop:
Code: |
while (TRUE) {
if (counter) --counter;
else {
if (LEDON) {
output_high(LED);
counter=100;
LEDON=FALSE;
}
else {
output_low(LED);
counter=100;
LEDON=TRUE;
}
}
delay_ms(10);
}
|
This then loops 100*10mSec and then changes the LED, giving the 'one second' behaviour.
Then in the interrupt, have:
counter=500;
output_low(LED);
LEDON=TRUE;
This sets the LED on, and sets the counter so the next change is now in 500*10mSec (5 seconds).
Best Wishes |
|
|
engineer_1
Joined: 27 Mar 2007 Posts: 6
|
|
Posted: Fri Jul 13, 2007 12:45 am |
|
|
thank you very much for your helps.i understood interrupts.you say that external interrupt is easy then rb4-rb7 interrupts.what should i change for rb0 interrupts. |
|
|
|