Contact Switch Interrupt - External Interrupt with Internal Interrupt

Here, in the program, I scroll through the LEDs using a timer interrupt, and if someone presses a switch, he must stop the first interrupt and turn on the second one, which should light up with an LED in accordance with the pressed switch. Here I am a little confused about what interruption causes. I mentioned several books to interrupt the change of contacts and wrote several lines for installing PCMSK2. The output signal am starts: "First, all the LEDs cycle cyclically when the switch is pressed ... the cyclic switching on of the LEDs stops and starts again (this means that the program reads the input simply without causing a second interrupt). Or pause and do not light up the subsequent outputs." Can anyone help please?

#include <avr/io.h> #include <avr/interrupt.h> #define PINK_MASK \ ((1<<PINK0)|(1<<PINK1)|(1<<PINK2)|(1<<PINK3)|(1<<PINK4)|(1<<PINK5)|(1<<PINK6)|(1<<PINK7)) volatile unsigned int intrs, i=1; void enable_ports(void); void delay(void); extern void __vector_23 (void) __attribute__ ((interrupt)); extern void __vector_25 (void) __attribute__ ((signal)); void enable_ports() { DDRB = 0xff; //PORTB as output for leds PORTB = 0xff; DDRK = 0x00; //PORTK as input from switches PORTK |= PINK_MASK; PCMSK2 = PINK_MASK; //ENABLE PCMSK2, Setting interrupts PCICR = 0x04; PCIFR = 0x04; TCCR0B = 0x03; //Setting TIMER TIMSK0 = 0x01; TCNT0 = 0x00; intrs = 0; } void __vector_23 (void) { intrs++; if(intrs > 60) { intrs = 0; PORTB = (0xff<<i); i++ ; if(i == 10 ) { PORTB = 0xff; i = 1 ; } } } void __vector_25 (void) { unsigned char switches; switches = ((~PINK) & (PINK_MASK)); //Reading from switches if(switches & (1<<PINK0)) PORTB = (PORTB<<PINK0); else if (switches & (1<<PINK1)) PORTB = (PORTB<<PINK1); else if (switches & (1<<PINK2)) PORTB = (PORTB<<PINK2); else if (switches & (1<<PINK3)) PORTB = (PORTB<<PINK3); else if (switches & (1<<PINK4)) PORTB = (PORTB<<PINK4); else if (switches & (1<<PINK5)) PORTB = (PORTB<<PINK5); else if (switches & (1<<PINK6)) PORTB = (PORTB<<PINK6); else if (switches & (1<<PINK7)) PORTB = (PORTB<<PINK7); } int main(void) { enable_ports(); sei(); while(1) { } } 

Thanks for your support.

+4
source share
2 answers

External interrupts in the AVR architecture are confusing, but not impossible. I found the best resource for me, this is the AVR libc page on interrupts . I think you made the code too complicated for what you want. Start from scratch:

 #include <avr/io.h> #include <stdint.h> #include <avr/interrupt.h> void main() { sei(); while(1) {}; } 

AVR libc actually makes interrupt handling pretty painless. The page I linked to above has a list of all supported interrupt vectors on each AVR chip. Suppose you are using Mega32, and now you want the LEDs to blink using timer interrupt. Add to the program:

 uint8_t led_state; ISR(TIMER0_COMP_vect) { led_state = ~led_state; PORTB = led_state; } void setup_timer_interrupt() { TCCR0B = 0x03; TIMSK0 = 0x01; TCNT0 = 0x00; } 

This should blink the LEDs on the PORTB every time a timer interrupt occurs. Note that the way it should be configured is to use the ISR(...) macro ISR(...) ; the __vector_... calls you use are outdated and a bit confusing.

Finally, you want to use a set of switches to hold the LED, if I understand your question correctly. In fact, I would not use an external interrupt for this, just read the value of the switches using PINK during ISR(TIMER0_COMP_vect) , but we can use it if you want. We need to add the following code:

 uint8_t switch_state; void setup_switch_interrupt() { // I'm assuming this code to enable external interrupts works. DDRK = 0x00; PORTK = 0xff; PCMSK2 = 0xff; // set to all 1s PCICR = 0x04; PCIFR = 0x04; } ISR(INT0_vect) { switch_state = PINK; } 

What does it do? We will maintain the state of the switches in switch_state every time an external interrupt is interrupted (I assume this set should happen on both transitions 0-> 1 and 1-> 0). It remains only to make the LED output depending on the value of switch_state . We will do this by interrupting the timer as long as we switch the LEDs. The new version looks like this:

 ISR(TIMER0_COMP_vect) { led_state = ~led_state | switch_state; PORTB = led_state; } 

And it must be!

Footnote: I have already said that the use of external interrupt for reading switches is really not required. This is because you can simply read the switch values ​​during the timer interrupt using the PINK . You can get rid of switch_state , setup_switch_interrupt() and ISR(INT0_vect) and just change the timer interrupt like this:

 ISR(TIMER0_COMP_vect) { led_state = ~led_state | PINK; PORTB = led_state; } 

This should make the program a little easier.

+5
source

So, regardless of the fact that every time your __vector_23 is executed, you switch over the LEDs assigned to PORTB , increasing i . If I understand that you are trying to do what you should do, increase i only at __vector_25 when the button is pressed.

0
source

All Articles