/*
Duas chaves ideais são conectadas as entradas PCINT0 e PCINT1. As chaves geram
interrupções. A sub-rotina para tratamento das interrupções geradas deve fazer com que
um LED em PB7 seja acesso nas bordas de descida de PCINT0 e nas bordas de subida de
PCINT1
*/
//Bibliotecas:
#define __ATmega2560__
#define __AVR_ATmega2560__
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>#include <avr/io.h>
#include <avr/interrupt.h>
// Definindo os pinos para o LED e as chaves
#define LED PB7
#define CHAVE1 PB0
#define CHAVE2 PB1
// Função para alternar o estado do LED
void led() {
PORTB |= (1 << LED); // Liga o LED em PB7
}
void desligar_led() {
PORTB &= ~(1 << LED); // Desliga o LED em PB7
}
int estado_atual0, estado_anterior0;
int estado_atual1, estado_anterior1;
int main(void) {
// Configura o pino do LED como saída
DDRB |= (1 << LED);
PORTB &= ~(1 << LED); // Inicialmente, o LED está apagado
// Configura o pino da chave como entrada com pull-up
DDRB &= ~(1 << CHAVE1); // Define PB0 (PCINT0) como entrada
PORTB |= (1 << CHAVE1); // Habilita o pull-up interno para PB0
DDRB &= ~(1 << CHAVE2); // Define PB1 (PCINT1) como entrada
PORTB |= (1 << CHAVE2); // Habilita o pull-up interno para PB1
// Inicializa o estado das chaves
estado_anterior0 = (PINB & (1 << CHAVE1)) ? 1 : 0; // Leitura inicial de CHAVE1 (PB0)
estado_anterior1 = (PINB & (1 << CHAVE2)) ? 1 : 0; // Leitura inicial de CHAVE2 (PB1)
// Habilita interrupções de mudança de pino para PCINT0 e PCINT1
PCICR |= (1 << PCIE0); // Habilita interrupções para pinos PCINT[7:0]
PCMSK0 |= (1 << PCINT0) | (1 << PCINT1); // Habilita a interrupção para PCINT0 (PB0) e PCINT1 (PB1)
// Habilita interrupções globais
sei();
while (1) {
PORTB &= ~ (1 << LED);
}
}
// Sub-rotina de interrupção para PCINT0 (PB0)
ISR(PCINT0_vect) {
// Verifica a borda de descida para CHAVE1 (PCINT0 - PB0)
estado_atual0 = (PINB & (1 << CHAVE1)) ? 1 : 0; // Leitura do estado atual de CHAVE1 (PB0)
if (estado_anterior0 == 1 && estado_atual0 == 0) { // Borda de descida (1 -> 0)
led(); // Liga o LED
}
estado_anterior0 = estado_atual0; // Atualiza o estado anterior
}
// Sub-rotina de interrupção para PCINT1 (PB1)
ISR(PCINT1_vect) {
// Verifica a borda de subida para CHAVE2 (PCINT1 - PB1)
estado_atual1 = (PINB & (1 << CHAVE2)) ? 1 : 0; // Leitura do estado atual de CHAVE2 (PB1)
if (estado_anterior1 == 0 && estado_atual1 == 1) { // Borda de subida (0 -> 1)
led(); // Liga o LED
}
estado_anterior1 = estado_atual1; // Atualiza o estado anterior
}