R2 Project Log - External Interrupts

I've done some playing, and worked out how to turn on the external interrupts on the atmega128 I am using for R2.

Code:

#define F_CPU 1000000UL
#include avr/io.h>#include util/delay.h>#include avr/interrupt.h>#include "r2.h"

int main(void) {
// Activate all the LEDs, set their pins to output
bit_set(LED_WHITE_L_DDR, LED_WHITE_L_BIT);
bit_set(LED_WHITE_R_DDR, LED_WHITE_R_BIT);
bit_set(LED_RED_L_DDR, LED_RED_L_BIT);
bit_set(LED_RED_R_DDR, LED_RED_R_BIT);
bit_set(LED_YELLOW_FL_DDR, LED_YELLOW_FL_BIT);
bit_set(LED_YELLOW_FR_DDR, LED_YELLOW_FR_BIT);
bit_set(LED_YELLOW_RL_DDR, LED_YELLOW_RL_BIT);
bit_set(LED_YELLOW_RR_DDR, LED_YELLOW_RR_BIT);

// enable internal pullup on PD0
bit_set(PORTD, BIT(0));
// enable external interrupts
EIMSK = BIT(INT0) | BIT(INT1);
// enable global interrupts
sei();

// turn on the white and red LEDs
bit_set(LED_WHITE_L_PORT, LED_WHITE_L_BIT);
bit_set(LED_WHITE_R_PORT, LED_WHITE_R_BIT);
bit_set(LED_RED_L_PORT, LED_RED_L_BIT);
bit_set(LED_RED_R_PORT, LED_RED_R_BIT);

// loop forever
while (1)
{
delayms(500);
}
return 0;
}

// delay for up to 65k milliseconds
void delayms(uint16_t millis)
{
// loop, delaying 1ms each iteration
while ( millis )
{
_delay_ms(1);
millis--;
}
}

// this catches the Interrupt sent from pin INT0
ISR(INT0_vect)
{
//Turn everything off
bit_clear(LED_WHITE_L_PORT, LED_WHITE_L_BIT);
bit_clear(LED_WHITE_R_PORT, LED_WHITE_R_BIT);
bit_clear(LED_RED_L_PORT, LED_RED_L_BIT);
bit_clear(LED_RED_R_PORT, LED_RED_R_BIT);

// loop forever, flashing our indicators.
while(1)
{
bit_flip(LED_YELLOW_FL_PORT, LED_YELLOW_FL_BIT);
bit_flip(LED_YELLOW_FR_PORT, LED_YELLOW_FR_BIT);
bit_flip(LED_YELLOW_RL_PORT, LED_YELLOW_RL_BIT);
bit_flip(LED_YELLOW_RR_PORT, LED_YELLOW_RR_BIT);
delayms(500);
}
}

Changing Trigger Mode:

By default, the interrupt triggers when the pin is brought low. If we want to change this behavior, we need to poke at the External Interrupt Control Registers, EICRA (for INT0 - INT3) and EICRB (for INT4 - INT7).

Each interrupt pin has 2 bits in the EICR Registers, ISCxO and ISCx1. This Gives 4 possible options for triggering:

  • 0 0: Default, Trigger when INTx is held low
  • 0 1: Not Used
  • 1 0: Trigger when INTx changes from 1 to 0
  • 1 1: Trigger when INTx changes from 0 to 1

So, to turn on INT1, and set it to trigger on a rising edge, we,d use the following code:

// enable external interrupt
EIMSK = BIT(INT0);
// set the interrupt to trigger on a rising edge
EICRA |= BIT(ISC00) | BIT(ISC01);

Video:

[youtube=http://www.youtube.com/watch?v=pSuCHiK-Xq4]


0 Responses to R2 Project Log - External Interrupts

  1. There are currently no comments.

Leave a Reply