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:

July 27th, 2008 at 10:51 pm
Hazard Warning Lights!
In case you break down?
July 28th, 2008 at 12:15 am
Yeah, dont want to be stuck at the side of the maze without them, i might get clipped by X going past at 70mph