#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/gpio.h"
// Definino pinos e enderecos
#define LCD_ADDR 0x27
#define DS1307_ADDR 0x68
#define I2C_PORT i2c0
#define SDA_PIN 0
#define SCL_PIN 1
// Comandos para o LCD
#define LCD_CLEAR 0x01
#define LCD_CMD 0
#define LCD_DATA 1
#define LCD_ENABLE 0x04
#define LCD_BACKLIGHT 0x08
//
// FUNCOES PARA O LCD
//
void lcd_write(uint8_t val, uint8_t mode)
{
uint8_t data[] = { (val & 0xF0) | mode | LCD_BACKLIGHT, ((val << 4) & 0xF0) | mode | LCD_BACKLIGHT };
for (int i = 0; i < 2; i++)
{
i2c_write_blocking(I2C_PORT, LCD_ADDR, &data[i], 1, false);
data[i] |= LCD_ENABLE;
i2c_write_blocking(I2C_PORT, LCD_ADDR, &data[i], 1, false);
data[i] &= ~LCD_ENABLE;
i2c_write_blocking(I2C_PORT, LCD_ADDR, &data[i], 1, false);
}
}
void lcd_command(uint8_t cmd)
{
lcd_write(cmd, LCD_CMD);
}
void lcd_data(uint8_t data)
{
lcd_write(data, LCD_DATA);
}
void lcd_clear()
{
lcd_command(LCD_CLEAR);
}
void lcd_putstr(const char *str)
{
while (*str)
{
lcd_data(*str++);
}
}
void lcd_set_cursor(uint8_t row, uint8_t col)
{
lcd_command(0x80 | (row * 0x40 + col));
}
uint8_t bcd_to_dec(uint8_t val)
{
return (val >> 4) * 10 + (val & 0xF);
}
uint8_t dec_to_bcd(uint8_t val)
{
return (val / 10 << 4) | (val % 10);
}
//
// FUNCOES PARA O LCD
//
// Funcao para iniciar o i2c
void setup_i2c()
{
// Inicia o i2c nos pinos definidos
i2c_init(I2C_PORT, 120000);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SCL_PIN);
}
// Funcao para iniciar o lcd
void setup_lcd()
{
// Envia comandos para iniciar o lcd
lcd_command(0x03);
lcd_command(0x02);
lcd_command(0x28);
lcd_command(0x0C);
lcd_clear();
lcd_command(0x06);
}
// Funcao para atualizar a hora no display
void ds1307_read_data()
{
// Le a informacao de tempo
uint8_t reg = 0x00, data[7];
i2c_write_blocking(I2C_PORT, DS1307_ADDR, ®, 1, true);
i2c_read_blocking(I2C_PORT, DS1307_ADDR, data, sizeof(data), false);
// Colocando a data no display
char buffer[17];
snprintf(buffer, sizeof(buffer), "Data->%02d/%02d/20%02d", bcd_to_dec(data[4]), bcd_to_dec(data[5]), bcd_to_dec(data[6]));
lcd_clear();
lcd_set_cursor(0, 0);
lcd_putstr(buffer);
// Colocando a hora no display
snprintf(buffer, sizeof(buffer), "Hora->%02d:%02d:%02d", bcd_to_dec(data[2]), bcd_to_dec(data[1]), bcd_to_dec(data[0]));
lcd_set_cursor(1, 0);
lcd_putstr(buffer);
// Colocando a data e hora no console
printf("Data: %02d/%02d/20%02d - Hora: %02d:%02d:%02d\n",
bcd_to_dec(data[4]), bcd_to_dec(data[5]), bcd_to_dec(data[6]),
bcd_to_dec(data[2]), bcd_to_dec(data[1]), bcd_to_dec(data[0]));
}
// Funcao para definir a hora no display
void ds1307_set_data()
{
uint8_t data[] =
{
0x00,
dec_to_bcd(0), // Segundo 0
dec_to_bcd(27), // Minuto 27
dec_to_bcd(13), // Hora 13
dec_to_bcd(2), // Dia da Semana 2
dec_to_bcd(24), // Dia do Mes 24
dec_to_bcd(9), // Mes 9
dec_to_bcd(24) // Ano 2024
};
//Coloca data no RTC
i2c_write_blocking(I2C_PORT, DS1307_ADDR, data, sizeof(data), false);
//Coloca a data no display
ds1307_read_data();
}
// Funcao principal
int main()
{
// Inicia os requisitos
stdio_init_all();
setup_i2c();
setup_lcd();
// Define data para o RTC
ds1307_set_data();
// Loop principal
while (true)
{
//Atualiza a data no display a cada 5 segundos
sleep_ms(5000);
ds1307_read_data();
}
}