/*
Usamos o conversor ADC para fazer a leitura de duas tensões
analógicas nos canais ADC4 (porta PF4) e ADC1 (porta PF1), em intervalos de 2 s.
Transmitimos pela USART0 a diferença de tensão ADC4 - ADC1. Use a fonte interna
de tensão de 1,1 V. Escreva o programa em C. Faça a simulação com o programa
em https://wokwi.com. Use potenciômetros nas entrada ADC4 e ADC1 para testar
o circuito.
*/
//Bibliotecas:
#define __ATmega2560__
#define __AVR_ATmega2560__
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <stdint.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdbool.h>
#include <stdint.h>
#include <util/delay.h>
#include <stdint.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "usart.h"
#define adc4 PF4
#define adc1 PF1
void configurar_ADC(void) {
// Configura o ADC com:
// - ADEN=1 (ativar o ADC)
// - ADPS[2:0]=111 (prescaler para 128 para uma frequência de 125kHz com F_CPU = 16MHz)
ADCSRA = 0x87;
// Desativa a configuração de gatilho automático
ADCSRB = 0x00;
//
ADMUX = 10000000; // REFS[1:0] = 01
}
/* Função para realizar a leitura do ADC e converter o valor para tensão */
uint16_t ler_ADC(uint8_t canal) {
ADMUX = (ADMUX & 0xF8) | canal; // Limpa os 3 bits (11111000, mantem os 5 primeiro e limpa os ultimos 3) de MUX e define o canal (nos ultrimos 3)
// Inicia a conversão
ADCSRA |= (1 << ADSC);
// Espera a conversão terminar
while (ADCSRA & (1 << ADSC));
// Retorna o valor ADC
return ADC;
}
volatile int cont, valor_ADC1, valor_ADC4;;
int main(void){
configurar_ADC();
configuracao_TC0();
USART0_configura();
while (1) {
}
}
void configuracao_TC0() {
// Configura o timer0 para gerar interrupções a cada 1 ms
TCCR0A = 0x02; // Modo CTC
TCCR0B = 0x04; // CS0[2:0]=100 N=256
TIMSK0 = 0x02; // Ativa OCIE0A (interrupção de comparação A)
OCR0A = 62; // TOP (valor de comparação)
TCNT0 = 0x00; // Zera o contador
sei(); // Ativa as interrupções globais
}
ISR(TIMER0_COMPA_vect) {
int diferenca; // Variável para armazenar a diferença entre os valores lidos
char buffer[6]; // Buffer para armazenar a string da diferença
cont++; // Incrementa o contador para contar as interrupções
// Se o contador atingir 200 (aproximadamente 200 ms), realiza a leitura dos ADCs
if (cont >= 200) {
valor_ADC1 = ler_ADC(1); // Lê o valor do ADC1
valor_ADC4 = ler_ADC(4); // Lê o valor do ADC4
// Calcula a diferença entre as leituras dos ADCs
diferenca = valor_ADC4 - valor_ADC1;
// Converte a diferença para string e envia pela USART
itoa(diferenca, buffer, 10); // Converte o valor inteiro para string decimal
USART0_transmite_string_RAM(buffer); // Transmite a string
USART0_transmite_string_RAM("\r\n"); // Adiciona uma nova linha
cont = 0; // Reseta o contador para recomeçar a contagem
}
}