🛠 Programmer en registres AVR : timer 16 bits et interruption

Arduino Mega 2560 (Rev3) · avance · Schéma : IMG-mega-2560-avance-1-registres-timer16.svg — schéma fonctionnel du timer 16 bits TCNT1 de l’ATmega2560 en mode CTC avec OCR1A, prédiviseur 1024 et bascule de la broche PB7 pilotée par l’interruption TIMER1_COMPA

Objectives

Step outside the Arduino framework: program the ATmega2560 in bare-metal C (avr-libc) to configure the 16-bit Timer1 in CTC mode (Clear Timer on Compare), enable the TIMER1_COMPA interrupt, and toggle the LED on pin 13 (PB7) at exactly 1 Hz. You will understand TCNT1 (16-bit counter, 0 to 65535, unlike the 8-bit Timer0/Timer2), the prescaler, OCR1A, and the interrupt vector.

Hardware

The original bootloader (stk500boot_v2 image, serial protocol at 115200 bauds) accepts a binary loaded via the "wiring" protocol. Documented note: the current bootloader refuses a complete chip erase via avrdude (problem "stk500v2_command: command failed"), hence the -D option below.

Complete code

/* Blink 1 Hz par Timer1 en CTC — ATmega2560 nu, sans core Arduino */
#define F_CPU 16000000UL          /* quartz de la carte : 16 MHz */
#include <avr/io.h>
#include <avr/interrupt.h>

/* 16 000 000 / 1024 = 15 625 Hz ; OCR1A = 15 624 -> bascule à 1 Hz */
ISR(TIMER1_COMPA_vect) {
    PORTB ^= (1 << PORTB7);       /* toggle PB7 = broche Arduino 13 */
}

int main(void) {
    DDRB  |= (1 << DDB7);         /* PB7 en sortie */
    TCCR1A = 0;                   /* mode normal sur la partie A */
    TCCR1B = (1 << WGM12)         /* CTC : efface TCNT1 à OCR1A */
           |  (1 << CS12) | (1 << CS10);  /* prédiviseur 1024 */
    OCR1A  = 15624;               /* valeur de comparaison 16 bits */
    TIMSK1 |= (1 << OCIE1A);      /* autorise TIMER1_COMPA */
    sei;                        /* active les interruptions */
    for (;;) { /* le CPU dort utilement ici */ }
}
/* Compilation et flash :
   avr-gcc -mmcu=atmega2560 -Os -o timer1.elf timer1.c
   avr-objcopy -O ihex -R .eeprom timer1.elf timer1.hex
   avrdude -p atmega2560 -c wiring -P COMx -b 115200 -D \
           -U flash:w:timer1.hex
*/

Expected verification

The integrated LED toggles exactly once per second (full period of 2 s), without delay or millis: the rate comes from the 16 MHz crystal divided by 1024 then by 15625. By reading TCNT1 with a debugger or changing OCR1A, the frequency adjusts immediately.

Common errors

Other tutorials for this board

Code examples for this board

← Back to the board 🛠 All tutorials