//César André Cifuentes Guzmán
//Carné: 21622
#include <avr/io.h>
#include <avr/interrupt.h>
//Se definene los puertos, pines y las variables a las que representan
#define LED1 (1 << PB0)
#define LED2 (1 << PB1)
#define LED3 (1 << PB2)
#define LED4 (1 << PB3)
//Respectivamente
#define BOTON1 (1 << PD2)
#define BOTON2 (1 << PD3)
#define BOTON3 (1 << PD4)
void setup() {
// Configura los pines del LED como salida
DDRB |= LED1 | LED2 | LED3 | B00001000;
// Configura los pines del botón como entrada
DDRD &= ~(BOTON1 | BOTON2 | BOTON3);
// Habilita las interrupciones para los pines específicos
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19) | (1 << PCINT20);
PCICR |= (1 << PCIE2);
// Activa las resistencias de pull-up internas para los pines del botón
PORTD |= (1 << PD2) | (1 << PD3) | (1 << PD4);
// Habilita las interrupciones globales
sei();
//Se escriben y definen los 3 timmers de 1000Hz
// Arduino Timer Interrupts Calculator
// TIMER 0 for interrupt frequency 1000 Hz:
cli(); // stop interrupts
TCCR0A = 0; // set entire TCCR0A register to 0
TCCR0B = 0; // same for TCCR0B
TCNT0 = 0; // initialize counter value to 0
// set compare match register for 1000 Hz increments
OCR0A = 249; // = 16000000 / (64 * 1000) - 1 (must be <256)
// turn on CTC mode
TCCR0B |= (1 << WGM01);
// Set CS02, CS01 and CS00 bits for 64 prescaler
TCCR0B |= (0 << CS02) | (1 << CS01) | (1 << CS00);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
sei(); // allow interrupts
// TIMER 1 for interrupt frequency 1000 Hz:
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 1000 Hz increments
OCR1A = 15999; // = 16000000 / (1 * 1000) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 1 prescaler
TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
// TIMER 2 for interrupt frequency 1000 Hz:
cli(); // stop interrupts
TCCR2A = 0; // set entire TCCR2A register to 0
TCCR2B = 0; // same for TCCR2B
TCNT2 = 0; // initialize counter value to 0
// set compare match register for 1000 Hz increments
OCR2A = 249; // = 16000000 / (64 * 1000) - 1 (must be <256)
// turn on CTC mode
TCCR2B |= (1 << WGM21);
// Set CS22, CS21 and CS20 bits for 64 prescaler
TCCR2B |= (1 << CS22) | (0 << CS21) | (0 << CS20);
// enable timer compare interrupt
TIMSK2 |= (1 << OCIE2A);
sei(); // allow interrupts
}
void loop() {
//la interrupción maneja el cambio de estado del LED
PORTB |= B00001000; // Establecer el bit 3 del puerto B en 1
delay(1000);
// Apagar el LED
PORTB &= B11110111; // Establecer el bit 3 del puerto B en 0
delay(1000);
}
//Se usa el Volatile para asegurar que su valor se actualice correctamente en las interrupciones.
volatile int count0 = 0;
volatile int count1 = 0;
volatile int count2 = 0;
ISR(TIMER0_COMPA_vect){ // Toma los 100 Hz del timer 0
count0++;
if (count0 == 3000){
count0 = 0;
PORTB &= ~(1 << PB0);
}
}
ISR(TIMER1_COMPA_vect){ // Toma en cuenta los 1000Hz del timer 1
count1++;
if (count1 == 3000){
count1 = 0;
PORTB &= ~(1 << PB1);
}
}
ISR(TIMER2_COMPA_vect){ // Igual que en anterior pero timer 2
count2++;
if (count2 == 500){
count2 = 0;
PORTB &= ~(1 << PB2);
}
}
ISR(PCINT2_vect) {
cli(); // El Cli deshabilita las interrupciones globales
// Verificar si se generó una interrupción en puerto D
if (PCIFR & (1 << PCIF2)) {
;
if (!(PIND & (1 << PIND2))) {
// Código cuando PORTD2 pasa a HIGH
PORTB |= (1 << PB0);
count0 = 0;
}
if (!(PIND & (1 << PIND3))) {
// Código cuando PORTD3 pasa a HIGH
PORTB |= (1 << PB1);
count1 = 0;
}
if (!(PIND & (1 << PIND4))) {
// Código cuando PORTD4 pasa a HIGH
PORTB |= (1 << PB2);
count2 = 0;
}
}
PCIFR |= (1 << PCIF2); // Limpiar bandera de interrupción
//en el puerto D, ya que en el Puerto D se dan las Interrupciones del Timer 0,1 y 2
sei(); // Habilitar interrupciones globales
}