#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>
#include <stdio.h>
#define RS PB1 // Define o pino PB1 como RS (Register Select) do LCD
#define E PB0 // Define o pino PB0 como E (Enable) do LCD
//-----------------------------------------------------------------//
//BIBLIOTECA LCD DO PROFESSOR
//Funções do LCD (pulso_E, envia_dados, Lcd_cmd, Lcd_out, Lcd_init)
//-----------------------------------------------------------------//
// Função para gerar um pulso no pino E, sinalizando ao LCD para ler os dados
void pulso_E() {
PORTB &= ~(1 << E); // Coloca o pino E em nível baixo
PORTB |= (1 << E); // Coloca o pino E em nível alto
PORTB &= ~(1 << E); // Coloca o pino E em nível baixo novamente
return;
}
// Função para enviar comandos ou dados para o LCD
void envia_dados(unsigned char comando) {
PORTD = ((comando & 0xF0) | (PORTD & 0x0F)); // Envia os 4 bits mais significativos
pulso_E(); // Gera um pulso no E para processar os dados
PORTD = (((comando << 4) & 0xF0) | (PORTD & 0x0F)); // Envia os 4 bits menos significativos
pulso_E(); // Gera um pulso no E para processar os dados
return;
}
// Função para enviar comandos para o LCD
void Lcd_cmd(unsigned char comando) {
_delay_ms(1); // Pequeno delay para garantir a execução do comando
PORTB &= ~(1 << RS); // Coloca o RS em nível baixo para indicar um comando
envia_dados(comando); // Envia o comando para o LCD
return;
}
// Função para posicionar o cursor e enviar texto para o LCD
void Lcd_out(char linha_lcd, char coluna_lcd, char *ponteiro) {
// Verifica se a linha e coluna estão dentro dos limites do LCD
if ((linha_lcd > 0) && (linha_lcd < 3) && (coluna_lcd > 0) && (coluna_lcd < 41)) {
Lcd_cmd(128 + (coluna_lcd - 1) + ((linha_lcd - 1) * 64)); // Calcula a posição do cursor
while (*ponteiro) {
_delay_ms(1); // Delay para processamento de cada caractere
PORTB |= (1 << RS); // Coloca RS em nível alto para indicar dados (caractere)
envia_dados(*ponteiro++); // Envia o caractere para o LCD e incrementa o ponteiro
}
}
return;
}
// Função para inicializar o LCD
void Lcd_init() {
// Configura os pinos do LCD como saída e inicializa o LCD em modo 4 bits
DDRB |= ((1 << E) + (1 << RS));
DDRD |= ((1 << PD4) + (1 << PD5) + (1 << PD6) + (1 << PD7));
PORTB &= ~(1 << RS);
_delay_ms(15);
PORTD = ((0x30 & 0xF0) | (PORTD & 0x0F));
pulso_E();
_delay_ms(5);
pulso_E();
_delay_ms(1);
pulso_E();
_delay_ms(1);
PORTD = ((0x20 & 0xF0) | (PORTD & 0x0F));
pulso_E();
Lcd_cmd(0x28);
Lcd_cmd(0x08);
Lcd_cmd(0x01);
Lcd_cmd(0x06);
Lcd_cmd(0x0C);
}
//----------------------------------------------------------------------------------//
//FIM DA BIBLIOTECA//
//----------------------------------------------------------------------------------//
int BETA = 3950; // Valor do parametro B do NTC
void Inicia_USART(long unsigned int baud_rate)
{
int ubrr;
ubrr = ((F_CPU) / (8 * baud_rate)) - 1;
UBRR0H = (unsigned char)(ubrr >> 8);
UBRR0L = (unsigned char)ubrr;
UCSR0A |= (1 << U2X0);
UCSR0B |= ((1 << RXEN0) | (1 << TXEN0));
UCSR0C &= ~((1 << UMSEL01) | (1 << UMSEL00));
UCSR0C &= ~((1 << UPM01) | (1 << UPM00));
UCSR0C &= ~(1 << USBS0);
UCSR0C &= ~(1 << UCSZ02);
UCSR0C |= ((1 << UCSZ01) | (1 << UCSZ00));
UCSR0B |= (1 << RXCIE0); // Habilita a interrupção da recepção da USART
}
void enviar_dado(unsigned char data)
{
while (!(UCSR0A & (1 << UDRE0))); // Aguarda o buffer esvaziar
UDR0 = data; // Envia o dado
}
void enviar_string(const char *s) {
while (*s) {
enviar_dado(*s++);
}
}
// Configuração e leitura do ADC
void initADC() {
ADMUX |= (0 << REFS1) | (1 << REFS0);; // Configura VCC como referência
ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Liga o ADC e configura prescaler
}
int readADC(int channel) {
ADMUX = (ADMUX & 0xF8) | channel; // Seleciona o canal do ADC (AD0)
ADCSRA |= (1 << ADSC); // Inicia a conversão
while (ADCSRA & (1 << ADSC)); // Espera a conversão completar
return ADC;
}
int main(void) {
initADC();
Inicia_USART(9600);
sei();
Lcd_init();
char buffer[50];
char temp[50];
while (1) {
int AD0 = readADC(0);
int V0_mV = (int)((float)AD0 * 5000.0 / 1024.0); // Tensão em milivolts
// Envia a tensão da porta A0
snprintf(buffer, sizeof(buffer), "Tensao A0: %d.%02d V\n", V0_mV / 1000, V0_mV % 1000);
enviar_string(buffer);
// Calculo da temperatura
float T = 1 / (log(1 / (1023. / AD0 - 1)) / BETA + 1.0 / 298.15) - 273.15;
int T_dec = (int)(T * 100); // Temperatura multiplicada por 100
// Envia a temperatura
snprintf(temp, sizeof(temp), "Temp: %d.%02d oC\n\n", T_dec / 100, T_dec % 100);
enviar_string(temp);
Lcd_out(1, 1, temp);
_delay_ms(3000);
}
return 0;
}