#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#define LED_RED_PIN PA2 // Pin del LED rojo
#define LED_GREEN_PIN PA1 // Pin del LED verde
#define BUTTON_PIN PA0 // Pin del botón
// Variables para la generación de números aleatorios
static long holdrand = 1L;
volatile unsigned long timer_millis = 0;
// Inicializa la semilla para el generador de números aleatorios
void srand(unsigned int seed) {
holdrand = (long)seed;
}
// Genera un número aleatorio basado en la semilla
int rand(void) {
return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
// Inicializa UART
void uart_init(unsigned int baudrate) {
unsigned int ubrr = F_CPU / 16 / baudrate - 1;
UBRR0H = (unsigned char)(ubrr >> 8);
UBRR0L = (unsigned char)ubrr;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
// Envía un carácter por UART
void uart_send_char(unsigned char data) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
// Envía una cadena por UART
void uart_send_string(const char* str) {
while (*str) {
uart_send_char(*str++);
}
}
// Inicializa Timer0 para contar milisegundos
void timer0_init() {
TCCR0A = (1 << WGM01); // Modo CTC
TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler de 64
OCR0A = 249; // Comparación a 1 ms
TIMSK0 = (1 << OCIE0A); // Habilita la interrupción de comparación
}
// Interrupción del Timer0 cada 1 ms
ISR(TIMER0_COMPA_vect) {
timer_millis++;
}
// Obtiene el tiempo en milisegundos desde que el programa inició
unsigned long millis() {
unsigned long millis_return;
cli(); // Deshabilita interrupciones
millis_return = timer_millis;
sei(); // Habilita interrupciones
return millis_return;
}
void setup() {
DDRA |= (1 << LED_RED_PIN) | (1 << LED_GREEN_PIN); // Configura los pines del LED como salida
DDRA &= ~(1 << BUTTON_PIN); // Configura el pin del botón como entrada
PORTA |= (1 << BUTTON_PIN); // Habilita el pull-up interno para el botón
uart_init(9600); // Inicializa UART a 9600 baudios
timer0_init(); // Inicializa Timer0
sei(); // Habilita interrupciones globales
uart_send_string("Presiona una tecla para iniciar.\r\n");
}
void loop() {
while (!(PINA & (1 << BUTTON_PIN))); // Espera a que se presione el botón
_delay_ms(50); // Pequeña demora para evitar rebotes
uart_send_string("Iniciando...\r\n");
randomDelay(); // Espera un tiempo aleatorio entre 1 y 10 segundos
uart_send_string("Encendiendo LED verde...\r\n");
PORTA |= (1 << LED_GREEN_PIN); // Enciende el LED verde
unsigned long startTime = millis(); // Obtiene el tiempo de inicio
while (!(PINA & (1 << BUTTON_PIN))); // Espera a que se presione el botón
_delay_ms(50); // Pequeña demora para evitar rebotes
unsigned long responseTime = millis() - startTime; // Calcula el tiempo de respuesta
if (responseTime > 1000) { // Si el tiempo de respuesta es mayor a 1 segundo
PORTA &= ~(1 << LED_GREEN_PIN); // Apaga el LED verde
PORTA |= (1 << LED_RED_PIN); // Enciende el LED rojo
_delay_ms(2000); // Mantiene el LED rojo encendido por 2 segundos
PORTA &= ~(1 << LED_RED_PIN); // Apaga el LED rojo
uart_send_string("Respuesta fallida.\r\n");
} else {
displayResponseTime(responseTime); // Muestra el tiempo de respuesta en la terminal
}
PORTA &= ~(1 << LED_GREEN_PIN); // Apaga el LED verde
}
// Realiza un retraso aleatorio entre 1 y 10 segundos
void randomDelay() {
srand(millis()); // Inicializa el generador de números aleatorios
unsigned int delayTime = (rand() % 10 + 1) * 1000; // Genera un número entre 1000 y 10000
while (delayTime--) {
_delay_ms(1);
}
}
// Muestra el tiempo de respuesta en la terminal
void displayResponseTime(unsigned long time) {
char buffer[50];
sprintf(buffer, "Tiempo de respuesta: %lu ms\r\n", time);
uart_send_string(buffer);
}
int main(void) {
setup();
while (1) {
loop();
}
}