/**
* @file timer0_pisca_led_polling.c
* @author Giovani Baratto ([email protected])
* @brief Faz um LED no terminal PB7 na frequência de 0,5 Hz. Neste programa, usamos o timer0 para controlar os
* intervalos de tempo. A cada 1000 interrupções,
* trocamos o estado do LED
* @version 0.2
* @date 2024-04-18
*/
#include <stdint.h> /* usamos os tipos uint8_t e uint16_t */
#define _AVR_ATmega2560_ /* programa para */
#ifndef F_CPU // se não foi definida a frequência de relógio
#define F_CPU 16000000UL // a frequência de relógio é 16 MHz
#endif
#include <avr/interrupt.h> /* usamos interrupções */
#include <avr/io.h> /* definições das entradas e saídas */
volatile uint16_t tick; /< incrementada a cada interrupção do timer0. */
/**
* @brief Rotina de interrupção quando ocorre o valor do contador TCNT0 é igual * ao contador OCR0A. A cada 1 ms a
* variável tick é incrementada. A cada 1000 ticks, equivalente ao intervalo de 1 s, o estado do LED é complementado.
*/
ISR(TIMER0_COMPA_vect) {
tick++; // variável tick é incrementada a cada 1 ms
if (tick == 1000) // se transcorreu 1000 ms = 1 s
{
PORTB = PORTB ^ (1 << PORTB7); // inverte o estado do LED em PB7
tick = 0; // começamos um novo intervalo de 1 s
}
}
/**
* @brief Configura o timer0 para gerar interrupções a cada 1 ms e faz o terminal
* PB7 uma saída.
*/
void configura_sistema(void) {
// configura o timer0 para gerar interrupções a cada 1 ms e executar a rotina de interrupção TIMER0_COMPA_vect
TCCR0A = 0x02; // saídas OC0A e OC0B como portas normais. COM0A[1:0]=00 COM0B[1:0]=00 WGM0[2:0]=010
TCCR0B = 0x03; // dividimos a frequência de relógio por 64. FOC0A = 0 FOC0B = 0 WGM0[2:0]=010 CS0[2:0] = 011
TIMSK0 = 0x02; // interrupções ocorrem no overflow do contador. OCIE0B = 0 OCIE0A = 1 TOIE0 = 0
OCR0A = 0xF9; // valor de TOP = 249 = 0xF9
TCNT0 = 0x00; // zeramos o contador
sei(); // habilita as interrupções globalmente
// Configura PB7 como um terminal de saída. Este terminal é ligado a um LED
DDRB = DDRB | (1 << DDB7); // faz o terminal TERMINAL_LED uma saída
PORTB = PORTB & (~(1 << PORTB7)); // envia o valor 0 para o terminal TERMINAL_LED
}
/**
* @brief O procedimento principal. Apenas executa um laço infinito, aguardando as interrupções.
* @return int. O procedimento principal nunca retorna
*/
int main(void) {
configura_sistema(); // configuramos o timer0 e o terminal PB7
while (1) // laço infinito
;
return 0; // o procedimento não retorna
}