/*
Já para a comunicação I2C, iremos utilizar o
DS1307, que é um Real Time Clock – RTC
disponível no simulador Wokwi. O endereço I2C
do DS1307 é 0x68. Um RTC é um hardware que
garante a contagem de tempo na unidade de
segundos. Muitos microcontroladores possuem RTC
internos, mas alguns fazem uso de hardware
externos. Para ler os valores, é necessário
inicialmente configurar um valor de data e
hora que deve, por exemplo, ser configurado
manualmente pelo usuário. Nessa questão você
deverá configurar o RTC para 24/09/2024 –
13:27:00 e em seguida, realizar a leitura
do mesmo a cada 5 segundos, e imprimir na
tela do console (Serial USB) o valor lido.
Na tabela a seguir são apresentados os
principais endereços do RTC DS1307.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
// Definições dos pinos do I2C
#define I2C_SDA_PIN 16 // SDA no GPIO 16
#define I2C_SCL_PIN 17 // SCL no GPIO 17
// Intervalo do timer (5 segundos = 5000 ms)
#define INTERVALO_TIMER_MS 5000
// Endereço I2C do DS1307
#define DS1307_ADDRESS 0x68
// Protótipos de funções
int decimal_bcd(int valor); // Converte decimal para BCD
int bcd_decimal(int valor); // Converte BCD para decimal
void set_rtc_time(uint8_t segundo, uint8_t minuto, uint8_t hora, uint8_t dia, uint8_t diaMes, uint8_t mes, uint8_t ano); // Configura o RTC
void get_rtc_time(); // Lê a data e hora do RTC
void init_i2c(); // Inicializa a comunicação I2C
bool repeating_timer_callback(repeating_timer_t *rt); // Callback do timer
int main() {
// Inicializa as funções padrão
stdio_init_all();
// Inicializa o I2C
init_i2c();
printf("Tarefa 2.4 - Unidade 4\n");
// Configura a data e hora inicial no RTC DS1307
printf("Configurando o RTC DS1307 para 24/09/2024 as 13:27:00\n");
set_rtc_time(0, 27, 13, 2, 24, 9, 24); // 24/09/2024 - 13:27:00
printf("RTC será lido a cada 5 segundos\n");
repeating_timer_t timer;
if (add_repeating_timer_ms(INTERVALO_TIMER_MS, repeating_timer_callback, NULL, &timer)) {
printf("Timer inicializado com sucesso\n");
} else {
printf("Falha ao inicializar o timer\n");
return 1; // Encerra o programa em caso de falha
}
// Loop principal: mantém o programa em execução
while (true) {
sleep_ms(1); // Evita uso excessivo da CPU
}
return 0;
}
// Converte decimal para BCD
int decimal_bcd(int valor) {
return ((valor / 10 * 16) + (valor % 10));
}
// Converte BCD para decimal
int bcd_decimal(int valor) {
return ((valor / 16 * 10) + (valor % 16));
}
// Configura a data e hora no DS1307
void set_rtc_time(uint8_t segundo, uint8_t minuto, uint8_t hora, uint8_t dia, uint8_t diaMes, uint8_t mes, uint8_t ano) {
uint8_t tempoCalendario[8] = {
0x00, // Registro inicial
decimal_bcd(segundo) & 0x7F, // Segundos (bit 7 = 0 para habilitar o oscilador)
decimal_bcd(minuto), // Minutos
decimal_bcd(hora), // Horas (formato 24h)
decimal_bcd(dia), // Dia da semana (1 = domingo, 7 = sábado)
decimal_bcd(diaMes), // Dia do mês
decimal_bcd(mes), // Mês
decimal_bcd(ano) // Ano
};
// Configura os registradores internos do DS1307
i2c_write_blocking(i2c0, DS1307_ADDRESS, tempoCalendario, 8, false);
}
// Lê a data e hora do DS1307
void get_rtc_time() {
uint8_t dadosHora[7];
uint8_t registroInicial = 0x00;
// Escreve o valor do registro inicial
i2c_write_blocking(i2c0, DS1307_ADDRESS, ®istroInicial, 1, true);
// Lê as informações de data e hora
i2c_read_blocking(i2c0, DS1307_ADDRESS, dadosHora, 7, false);
// Converte os valores BCD para decimal
int segundos = bcd_decimal(dadosHora[0] & 0x7F); // Ignora o bit 7 (CH)
int minutos = bcd_decimal(dadosHora[1]);
int hora = bcd_decimal(dadosHora[2]);
int dia = bcd_decimal(dadosHora[3]);
int diaMes = bcd_decimal(dadosHora[4]);
int mes = bcd_decimal(dadosHora[5]);
int ano = bcd_decimal(dadosHora[6]);
// Exibe os valores no console
printf("Data: %02d/%02d/20%02d - ", diaMes, mes, ano);
printf("Hora: %02d:%02d:%02d\n", hora, minutos, segundos);
}
// Inicializa a comunicação I2C
void init_i2c() {
i2c_init(i2c0, 100 * 1000); // Velocidade de 100kHz
gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA_PIN); // Habilita pull-up no pino SDA
gpio_pull_up(I2C_SCL_PIN); // Habilita pull-up no pino SCL
}
// Callback do timer: lê e exibe a data/hora a cada 5 segundos
bool repeating_timer_callback(repeating_timer_t *rt) {
get_rtc_time();
return true; // Continua o timer
}