#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define DHT_PIN_MASK (1 << PB0)
#define BUTTON_RED_MASK (1 << PD7)
#define BUTTON_YEL_MASK (1 << PD6)
#define BUTTON_BLK_MASK (1 << PB7)
#define LCD_RS_MASK (1 << PB4)
#define LCD_EN_MASK (1 << PB5)
#define LCD_D4_MASK (1 << PD5)
#define LCD_D5_MASK (1 << PD4)
#define LCD_D6_MASK (1 << PD3)
#define LCD_D7_MASK (1 << PD2)
#define LCD_DATA_PORT PORTD
#define LCD_CTRL_PORT PORTB
#define LCD_DATA_DDR DDRD
#define LCD_CTRL_DDR DDRB
#define BUTTON_PORT PORTD
#define BUTTON_PIN PIND
#define BUTTON_DDR DDRD
#define BUTTON_RED 0
#define BUTTON_YEL 1
#define TEMPERATURE_C 0
#define TEMPERATURE_F 1
#define TEMPERATURE_K 2
volatile unsigned char escala = TEMPERATURE_C;
volatile unsigned char tela = 0;
void LCD_pulse_enable(void) {
LCD_CTRL_PORT |= LCD_EN_MASK;
_delay_us(1);
LCD_CTRL_PORT &= ~LCD_EN_MASK;
_delay_us(100);
}
void LCD_send_command(unsigned char command) {
LCD_CTRL_PORT &= ~LCD_RS_MASK; // Set RS to command mode
LCD_DATA_PORT = command & 0xF0; // Send upper nibble
LCD_pulse_enable();
LCD_DATA_PORT = (command << 4) & 0xF0; // Send lower nibble
LCD_pulse_enable();
}
void LCD_send_data(unsigned char data) {
LCD_CTRL_PORT |= LCD_RS_MASK; // Set RS to data mode
LCD_DATA_PORT = data & 0xF0; // Send upper nibble
LCD_pulse_enable();
LCD_DATA_PORT = (data << 4) & 0xF0; // Send lower nibble
LCD_pulse_enable();
}
void LCD_init(void) {
_delay_ms(100); // Wait for LCD to power up
LCD_DATA_DDR |= 0xF0;
LCD_CTRL_DDR |= LCD_RS_MASK | LCD_EN_MASK;
LCD_send_command(0x33);
_delay_ms(5);
LCD_send_command(0x32);
_delay_ms(5);
LCD_send_command(0x28); // 4-bit mode, 2 lines, 5x7 font
_delay_ms(5);
LCD_send_command(0x0C); // Display on, cursor off, blink off
_delay_ms(5);
LCD_send_command(0x01); // Clear display
_delay_ms(5);
LCD_send_command(0x06); // Set entry mode (increment cursor, no display shift)
_delay_ms(5);
}
void show_hello_message(void) {
LCD_send_command(0x01); // Clear display
_delay_ms(5);
LCD_send_data('O');
LCD_send_data('l');
LCD_send_data('a');
LCD_send_data(',');
LCD_send_data(' ');
LCD_send_data('P');
LCD_send_data('&');
LCD_send_data('R');
LCD_send_data(' ');
LCD_send_data('t');
LCD_send_data('e');
LCD_send_data('c');
LCD_send_data('h');
LCD_send_data('\'');
LCD_send_data('s');
_delay_ms(2000);
tela++;
configuracao();
}
void configuracao(void) {
LCD_send_command(0x01); // Clear display
_delay_ms(5);
LCD_send_data('E');
LCD_send_data('s');
LCD_send_data('c');
LCD_send_data('o');
LCD_send_data('l');
LCD_send_data('h');
LCD_send_data('a');
LCD_send_data(' ');
LCD_send_data('o');
LCD_send_data(' ');
LCD_send_data('m');
LCD_send_data('o');
LCD_send_data('d');
LCD_send_data('o');
LCD_send_data(':');
LCD_send_data(' ');
LCD_send_data('1');
LCD_send_data('(');
LCD_send_data('C');
LCD_send_data(')');
LCD_send_data(' ');
LCD_send_data('2');
LCD_send_data('(');
LCD_send_data('K');
LCD_send_data(')');
LCD_send_data(' ');
LCD_send_data('3');
LCD_send_data('(');
LCD_send_data('F');
LCD_send_data(')');
while (1) {
if (!(BUTTON_PIN & BUTTON_RED_MASK)) {
escala = TEMPERATURE_C;
tela++;
show_temperature(escala);
break;
} else if (!(BUTTON_PIN & BUTTON_YEL_MASK)) {
escala = TEMPERATURE_F;
tela++;
show_temperature(escala);
break;
} else if (!(BUTTON_PIN & BUTTON_BLK_MASK)) {
escala = TEMPERATURE_K;
tela++;
show_temperature(escala);
break;
}
}
}
void show_temperature(unsigned char escala) {
float temperatura = 25.0; // DHT_readTemperature(); Simulação de leitura de temperatura
char buffer[16];
LCD_send_command(0x01); // Clear display
_delay_ms(5);
LCD_send_data(' ');
LCD_send_data('T');
LCD_send_data('e');
LCD_send_data('m');
LCD_send_data('p');
LCD_send_data(':');
LCD_send_data(' ');
switch (escala) {
case TEMPERATURE_C:
sprintf(buffer, "%.2fC", temperatura);
break;
case TEMPERATURE_F:
sprintf(buffer, "%.2fF", (temperatura * 9.0 / 5.0) + 32.0);
break;
case TEMPERATURE_K:
sprintf(buffer, "%.2fK", temperatura + 273.15);
break;
}
for (int i = 0; buffer[i] != '\0'; i++) {
LCD_send_data(buffer[i]);
}
}
void setup() {
BUTTON_DDR &= ~(BUTTON_RED_MASK | BUTTON_YEL_MASK | BUTTON_BLK_MASK);
BUTTON_PORT |= BUTTON_RED_MASK | BUTTON_YEL_MASK | BUTTON_BLK_MASK;
LCD_init();
// Configura a interrupção externa INT0 (PD2)
EICRA |= (1 << ISC01) | (1 << ISC00); // Rising edge
EIMSK |= (1 << INT0); // Habilita a interrupção INT0
sei(); // Habilita as interrupções globais
show_hello_message();
}
ISR(INT0_vect) {
tela = 0;
show_hello_message();
}
void loop() {
// Nada a ser feito no loop principal, tudo é tratado por interrupções
}