-
-
Save m1cr0lab/e1b088a9e7bd053cc905668675ce5a72 to your computer and use it in GitHub Desktop.
Optimizing the reaction time of the ATMega328
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* --------------------------------------------------------------------------- | |
* Control of an LED by a push button with an Arduino Nano board | |
* --------------------------------------------------------------------------- | |
* Classical approach with the Arduino API | |
* --------------------------------------------------------------------------- | |
* PIN | | |
* ----+---------------------------------------------------------------------- | |
* D2 | Push button wired up to a pull-down resistor (10 kΩ) | |
* ----+---------------------------------------------------------------------- | |
* D4 | Red LED with a 220 Ω resistor in series | |
* ----+---------------------------------------------------------------------- | |
*/ | |
#include <Arduino.h> | |
#define BTN_PIN 2 | |
#define LED_PIN 4 | |
#define DEBOUNCE_DELAY_MS 1 | |
bool led_level = LOW; | |
uint8_t input; | |
uint8_t last_input; | |
uint8_t output; | |
uint32_t last_debounce; | |
void setup() { | |
pinMode(BTN_PIN, INPUT); | |
pinMode(LED_PIN, OUTPUT); | |
} | |
void loop() { | |
uint32_t now = millis(); | |
input = digitalRead(BTN_PIN); | |
if (input != last_input) last_debounce = now; | |
last_input = input; | |
if (now - last_debounce > DEBOUNCE_DELAY_MS) { | |
if (output != input) { | |
output = input; | |
if (output) { | |
digitalWrite(LED_PIN, led_level = !led_level); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* --------------------------------------------------------------------------- | |
* Control of an LED by a push button with an Arduino Nano board | |
* --------------------------------------------------------------------------- | |
* Dramatically improved reaction time of the ATMega328 | |
* --------------------------------------------------------------------------- | |
* Pinout: | |
* ----+------+ | |
* PIN | PORT | | |
* ----+------+--------------------------------------------------------------- | |
* D2 | PD2 | Push button wired up to a pull-down resistor (10 kΩ) | |
* ----+------+--------------------------------------------------------------- | |
* D4 | PD4 | Red LED with a 220 Ω resistor in series | |
* --------------------------------------------------------------------------- | |
* Instead of using the digitalRead() and digitalWrite() functions of the | |
* Arduino API, we will instead use the internal registers, and the INT0 | |
* interrupt vector (External Interrupt Request 0) of the ATMega328. | |
* --------------------------------------------------------------------------- | |
* As a result, the reaction time of the ATMega328 is 1000 times faster! | |
* --------------------------------------------------------------------------- | |
* Documentation: | |
* | |
* @see https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf | |
* | |
* I/O Ports: | |
* | |
* PORTD - The Port D Data Register | |
* ----+--------+-------+-----------------------------+--------- | |
* PD2 | PORTD2 | Bit 2 | External Interrupt Source | pp.71,73 | |
* PD4 | PORTD4 | Bit 4 | Pin Change Interrupt Source | pp.70,73 | |
* ----+--------+-------+-----------------------------+--------- | |
* | |
* Register Description: | |
* -------+---------------------------------------+-------+----- | |
* SREG | AVR Status Register | | p.11 | |
* SREG_I | Global Interrupt Enable | Bit 7 | p.11 | |
* EICRA | External Interrupt Control Register A | | p.54 | |
* ISC01 | Interrupt Sense Control 0 | Bit 1 | p.54 | |
* ISC00 | Interrupt Sense Control 0 | Bit 0 | p.54 | |
* EIMSK | External Interrupt Mask Register | | p.55 | |
* INT0 | External Interrupt Request 0 Enable | Bit 0 | p.55 | |
* EIFR | External Interrupt Flag Register | | p.55 | |
* INTF0 | External Interrupt Flag 0 | Bit 0 | p.55 | |
* DDRD | Port D Data Direction Register | | p.73 | |
* -------+---------------------------------------+-------+----- | |
* | |
* Interrupt Sense Control 0: | |
* ------+-------+------------------------------------------------------------ | |
* ISC01 | ISC00 | Description | |
* ------+-------+------------------------------------------------------------ | |
* 0 | 0 | The low level of INT0 generates an interrupt request | |
* 0 | 1 | Any logical change on INT0 generates an interrupt request | |
* 1 | 0 | The falling edge of INT0 generates an interrupt request | |
* 1 | 1 | The rising edge of INT0 generates an interrupt request | |
* ------+-------+------------------------------------------------------------ | |
*/ | |
#include <Arduino.h> | |
#define DEBOUNCE_DELAY_MS 1 | |
ISR(INT0_vect) { | |
EIMSK &= ~(1 << INT0); // Override of interrupt vector INT0 | |
PORTD ^= 1 << PD4; // PD4 bit toggle | |
} | |
void setup() { | |
DDRD &= ~(1 << PD2); // Setting the button reading pin | |
DDRD |= 1 << PD4; // Setting the LED control pin | |
EICRA = (1 << ISC01) | (1 << ISC00); // Setting the interrupt vector INT0 (RISING) | |
EIMSK = 1 << INT0; // Arming the interrupt vector INT0 | |
SREG |= 1 << SREG_I; // Activation of interrupts | |
} | |
void loop() { | |
static uint32_t last = 0; | |
uint32_t now = millis(); | |
// If the interrupt vector INT0 has been disarmed, | |
// and the debouncing time has expired... | |
if (!(EIMSK >> INT0) && now - last > DEBOUNCE_DELAY_MS) { | |
last = now; // Reset the stabilization window | |
// Resets the interrupt vector INT0 | |
// as soon as the read pin is at LOW | |
if (!((PIND >> PD2) & 0x1)) { | |
EIFR = 1 << INTF0; // Cancels any previous interruption on interrupt vector INT0 | |
EIMSK = 1 << INT0; // Rearming the interrupt vector INT0 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment