#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile uint8_t work = 0; // Variável global para sinalizar a interrupção
void interrupt_setup() {
// Configura o contador/temporizador TC0 para gerar interrupções a cada 0,6ms
// Configuração para um microcontrolador AVR específico, pode variar para outros modelos
TCCR0A = 0;
TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler de 64
TIMSK0 |= (1 << TOIE0); // Habilita a interrupção por overflow do TC0
TCNT0 = 0; // Reinicia o contador
}
void ADC_init() {
// Configura o ADC para usar a referência de 2,56V e prescaler de 128
ADMUX = (1 << REFS1) | (1 << REFS0); // Seleciona a referência interna de 2,56V
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Habilita o ADC com prescaler de 128
}
uint16_t ADC_read(uint8_t channel) {
ADMUX = (ADMUX & 0xF8) | (channel & 0x07); // Seleciona o canal de entrada
ADCSRA |= (1 << ADSC); // Inicia a conversão
while (ADCSRA & (1 << ADSC)); // Aguarda a conversão ser concluída
return ADC;
}
void configure_pins() {
DDRL |= (1 << DDL3); // Configura o pino PL3 (LED) como saída
DDRL &= ~(1 << DDL5); // Configura o pino PL5 (entrada) como entrada
PORTL |= (1 << PORTL5); // Habilita o pull-up interno para PL5
}
int main(void) {
interrupt_setup(); // Configura as interrupções
ADC_init(); // Inicializa o ADC
configure_pins(); // Configura os pinos
sei(); // Habilita interrupções globais
while (1) {
if (work) {
work = 0; // Reseta a variável work
uint16_t adc_value = ADC_read(3); // Lê o canal ADC3
float voltage = (adc_value * 2.56) / 1024.0; // Calcula a tensão
if (voltage > 2.0 && (PINL & (1 << PINL5))) {
PORTL |= (1 << PORTL3); // Acende o LED em PL3
} else {
PORTL &= ~(1 << PORTL3); // Desliga o LED em PL3
}
}
_delay_ms(60); // Espera 60ms até a próxima leitura do ADC
}
return 0;
}
// Rotina de interrupção do Timer/Counter0 (TC0)
ISR(TIMER0_OVF_vect) {
work = 1; // Sinaliza a interrupção
}