/**
* Usamos o conversor ADC para fazer a leitura da tensão analógica no canal ADC1 (porta PF1), em intervalos de 1 s.
* Quando a tensão lida for maior que o valor em PB[2:0], transmitimos pela USART0 a mensagem “Tensão acima do permitido”.
* Deve ser enviada uma única mensagem, cada vez que a tensão lida for maior que PB[2:0].
* Se a tensão não retornar a um valor menor que PB[2:0], depois de 5 s, o LED em PB7 acende.
* Ele é apagado quando a tensão é menor ou igual a PB[2:0]. Use AVCC como tensão de referência.
* Escreva o programa em C.
* Use um potenciômetro na entrada ADC1 para testar o circuito.
*/
#include <avr/io.h> // Biblioteca para manipulação de registradores de I/O do AVR
#include <util/delay.h> // Biblioteca para funções de delay
#include "usart.h" // Inclui a biblioteca USART para comunicação serial
// Função para inicializar o ADC no canal ADC1 e AVCC como referência
void ADC_init(void) {
ADMUX = (1 << REFS0) | (1 << MUX0); // Configura AVCC como referência, canal ADC1 (MUX0 = 1)
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Habilita ADC com prescaler 128
}
// Função para ler o valor do ADC no canal configurado
uint16_t ADC_read(void) {
ADCSRA |= (1 << ADSC); // Inicia a conversão
while (ADCSRA & (1 << ADSC)); // Aguarda até a conversão finalizar
return ADC; // Retorna o valor do ADC (0-1023)
}
int main(void) {
uint16_t adc_value;
uint8_t limit_value;
uint8_t counter = 0; // Contador para verificar tempo em que a tensão está acima do limite
uint8_t message_sent = 0; // Flag para controlar envio único da mensagem
// Configuração de entrada e saída
DDRB &= ~(1 << DDB0) & ~(1 << DDB1) & ~(1 << DDB2); // Configura PB[2:0] como entrada
DDRB |= (1 << DDB7); // Configura PB7 como saída (LED)
ADC_init(); // Inicializa o ADC
USART0_configura(); // Inicializa a USART0 para comunicação serial
while (1) {
adc_value = ADC_read(); // Lê o valor do ADC (0-1023)
// Converte o valor limite de PB[2:0] para uma faixa entre 0 e 1023 (ajuste conforme necessidade)
limit_value = (PINB & 0x07) * 128; // Limite de comparação (0-7) * 128, mapeando de 0 a 896 aproximadamente
// Verifica se a tensão lida é maior que o limite em PB[2:0]
if (adc_value > limit_value) {
if (!message_sent) { // Envia mensagem se ainda não foi enviada
USART0_transmite_string_RAM((uint8_t *)"Tensão acima do permitido\n");
message_sent = 1; // Define flag para evitar envio repetido
}
counter++; // Incrementa contador para verificar tempo acima do limite
} else {
counter = 0; // Reseta contador se tensão estiver abaixo do limite
PORTB &= ~(1 << PB7); // Desliga o LED em PB7
message_sent = 0; // Reseta a flag para novo envio caso a tensão suba novamente
}
// Acende o LED em PB7 se tensão estiver acima do limite por 5 segundos consecutivos
if (counter >= 5) {
PORTB |= (1 << PB7); // Acende o LED em PB7
}
_delay_ms(1000); // Aguarda 1 segundo antes de nova leitura
}
}