Interface do módulo RTC (DS3231) com o microcontrolador PIC: Relógio digital

Tempo de leitura: 12 minutes

Quase todos os dispositivos incorporados são projetados para interagir com o mundo real. Eles agem como uma ponte para se comunicar entre o mundo digital e o mundo real. Para tornar esse processo mais fácil e eficiente, o mundo digital às vezes precisa acompanhar a hora e a data do mundo real. Dessa forma, o mundo digital saberá a que horas/dia é no mundo real e pode até distinguir entre dia ou noite. Também pode atuar como uma fonte de tempo para executar determinadas tarefas em uma hora ou data especificada. Então aqui estamos nós interface de um módulo RTC com o microcontrolador PIC e exiba a hora e a data no LCD 16×2. Este projeto também pode ser usado como Relógio digital.

Materiais necessários:

  • Fornecimento regulamentado de 5V
  • PIC16F877A
  • Oscilador de cristal 20Mhz
  • Capacitor 33pf – 2Nos
  • Resistor 10K, 5.1K, 1K
  • Módulo DS3231 RTC
  • POT -10k
  • Módulo LCD 16 * 2
  • Conectando fios

Módulo RTC:

A maneira mais comum de um microcontrolador acompanhar a hora ou a data do mundo real é usando um IC RTC. O termo RTC significa Relógio em Tempo Real; esse IC acompanha a hora e a data do mundo real e compartilha essas informações com o microcontrolador sempre que solicitado. O IC RTC que estamos usando aqui é o mais popular e preciso. DS3231. Esse IC é desviado apenas alguns segundos a cada ano e, portanto, é altamente confiável. Para o bem deste tutorial, estamos usando o. Módulo DS3231 RTC que pode ser facilmente adquirido on-line ou na loja de ferragens local. O módulo vem com uma célula de moeda de 3V que alimenta o módulo RTC sempre e, portanto, quando a hora e a data forem definidas, ela será atualizada enquanto a célula de moeda estiver viva.

O módulo DS3231 se comunica com a ajuda do protocolo I2C; portanto, se você não estiver ciente do que é e de como é usado com o PIC, leia o tutorial I2C com PIC antes de prosseguir. Também neste tutorial, criaremos um arquivo de cabeçalho que pode ser usado para se comunicar com nosso módulo RTC e também testamos o mesmo em hardware, exibindo a hora e a data em um monitor LCD, para que também seja importante aprender como visor LCD de interface com microcontrolador PIC O arquivo de cabeçalho criado neste tutorial para DS3231 pode ser usado/modificado posteriormente para atender aos seus aplicativos.

Conectando o DS3231 RTC com o microcontrolador PIC :

Diagrama de circuito para Relógio digital baseado em microcontrolador PIC é dado abaixo. Conforme dito anteriormente, o DS3231 trabalha com a ajuda da comunicação I2C, para que ele tenha um pino de Relógio Serial (SCL) e Dados Seriais (SDA) que deve ser conectado aos pinos I2C em nosso PIC, que é o pino 18 (SCL) e pino 23 (SDA). Um resistor de tração de valor 4.7k é usado para manter o barramento em estado alto quando ocioso.

Um visor LCD também é conectado aos pinos na porta D para exibir a data e a hora atuais. O diagrama de circuito completo foi projetado no proteus e é mostrado abaixo. Usaremos o mesmo para simular ou programar posteriormente neste tutorial.

Siga o diagrama do circuito e faça as conexões de acordo, a caixa I2C mostrada acima é usada para depuração de I2C, portanto, não incluiremos isso em nossas conexões. Além disso, não é demonstrado que o módulo RTC deva ser alimentado com uma fonte de + 5V usando os pinos Vcc e Ground no módulo. Usei minha placa de ensaio para fazer a conexão e, depois de fazer as conexões necessárias, minha configuração parecia algo assim abaixo.

Se você é novo no PIC Microcontroller, comece com Introdução ao microcontrolador PIC.

Programação PIC para o módulo RTC :

programa completo para este relógio digital pode ser baixado do arquivo ZIP aqui. O program includes three header files altogether. They are the lcd.h arquivo para trabalhar com o visor LCD, o PIC16F877a_I2C.h arquivo para trabalhar com a comunicação I2C com o PIC e, finalmente, o PIC16F877a_DS3231.h arquivo para trabalhar com módulos RTC. Todos os três arquivos de cabeçalho são necessários para este programa e estão disponíveis no arquivo ZIP acima. Mais abaixo, explicarei o programa principal que usa todo esse arquivo de cabeçalho para ler a hora e a data do módulo RTC e exibi-lo na tela LCD. Depois disso, explicarei o que realmente está acontecendo dentro do arquivo do cabeçalho do RTC. Como sempre, comece o programa configurando os bits de configuração e definindo a frequência do relógio como 20 MHz, pois é isso que usamos em nosso hardware.

#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define _XTAL_FREQ 20000000

O próximo passo seria defina os pinos de LCD, se você olhar para o hardware, poderá notar que conectamos os pinos do LCD ao PORT D do RD2 ao RD7, portanto definimos o mesmo como mostrado abaixo.

#define RS RD2
#define EN RD3
#defina D4 RD4
#defina D5 RD5
#defina D6 RD6
#defina D7 RD7

Por padrão, quando você comprou o módulo RTC, a hora e a data corretas não serão definidas nele então temos que defini-lo através do nosso programa Portanto, declaramos variável para cada dado e feed no mundo real, hora e data, conforme mostrado abaixo. No momento do upload do programa, minha hora e data eram 10h55 às 6h55 de 2018, então defini as variáveis como abaixo. Você pode definir a hora e a data corretas de acordo com o aplicativo real.

/* Defina o valor atual da data e hora abaixo de */
int sec = 00;
int min = 55;
int hour = 10;
int date = 06;
int month = 05;
int year = 18;
/* Conjunto de hora e data */

Em seguida nós adicione todos os arquivos do cabeçalho sobre o qual discutimos. Se você baixou e abriu o programa a partir do arquivo ZIP, não será um problema. Verifique se todos os arquivos do cabeçalho foram adicionados ao seu arquivo de origem ou ao diretório do projeto.

#include <xc.h>
#include "lcd.h"
#include "PIC16F877a_I2C.h"
#include "PIC16F877a_DS3231.h"

Como usamos o PORT D como pinos de saída para interagir com o LCD, precisamos declará-los como pinos de saída em nosso programa e inicialize o visor LCD como mostrado abaixo

TRISD = 0x00; // Faça os pinos da porta D como saída para interface de LCD
 Lcd_Start(); // Inicializar módulo LCD

O módulo RTC se comunica com a ajuda do protocolo I2C, por isso precisamos habilite a comunicação I2C nosso microcontrolador PIC A maioria dos dispositivos, incluindo nossos módulos DS3231, possui uma frequência operacional I2C de 100KHz, portanto iniciamos a comunicação I2C com uma frequência de 100KHz, conforme mostrado abaixo.

I2C_Initialize(100); // Inicialize o I2C Master com relógio de 100KHz

Assim que estabelecemos uma comunicação I2C com o módulo RTC, a primeira coisa que fazemos é defina a hora e a data atuais em que inserimos em nosso programa. Isso pode ser feito ligando para o. set_Time_Date função como mostrado abaixo. Depois que a hora e a data forem definidas, o módulo será automaticamente rastreado e incrementado como um relógio digital.

Set_Time_Date(); // defina a hora e a data no módulo RTC

Para indicar que o programa foi iniciado, exibiremos uma pequena mensagem de introdução para a qual permanecerá na tela por 2 segundos. Esta mensagem será exibida RTC com PIC – Circuit Digest na tela. O programa para o mesmo é mostrado abaixo

Lcd_Clear();
Lcd_Set_Cursor(1,1) ;
Lcd_Print_String("RTC com PIC");
Lcd_Set_Cursor(2,1) ;
Lcd_Print_String("-CapSistema");
__delay_ms(1500);

Dentro do nosso infinito enquanto loop devemos leia a hora e a data atuais e exiba os valores em nossa tela LCD. Para ler a hora e a data do módulo RTC, o. Update_Current_Time_Date A função pode ser usada como mostrado abaixo. Esta função lerá o valor do módulo RTC e atualizará as variáveis sec, min, hora, data, mês e ano com os valores atuais. Então podemos usá-los para nosso propósito.

Update_Current_Date_Time(); // Leia a data e hora atuais do módulo RTC

As variáveis são do tipo de dados inteiro, precisamos convertê-las em caracteres individuais para que possamos exibi-las na tela LCD. Portanto, usamos o operador de módulo para obter o dígito uma vez e dividir a variável por 10 para obter o dígito de dezenas. O mesmo é feito para todas as variáveis.

//Divida em char para exibir no LCD
 char sec_0 = sec%10;
 char sec_1 = (sec/10);
 char min_0 = min%10;
 char min_1 = min/10;
 char hour_0 = hour%10;
 char hour_1 = hour/10;
 char date_0 = date%10;
 char date_1 = date/10;
 char month_0 = month%10;
 char month_1 = month/10;
 char year_0 = year%10;
 char year_1 = year/10;

Tudo o que resta a fazer é exibindo as informações que adquirimos na tela LCD Isso pode ser feito facilmente com as funções de LCD que discutimos anteriormente em nosso tutorial em LCD. Portanto, o código para exibir a hora é fornecido abaixo, o mesmo método é usado para exibir a data também. Um atraso de 500ms é fornecido após a exibição dos dados, para que ele atue como um intervalo de atualização.

Lcd_Clear();
Lcd_Set_Cursor(1,1) ;
Lcd_Print_String("TIME:");
Lcd_Print_Char(hora_1 + '0');
Lcd_Print_Char(hora_0 + '0');
Lcd_Print_Char(':');
Lcd_Print_Char(min_1 + '0');
Lcd_Print_Char(min_0 + '0');
Lcd_Print_Char(':');
Lcd_Print_Char(sec_1 + '0');
Lcd_Print_Char(sec_0 + '0');

Breve explicação do arquivo do cabeçalho PIC16F877a_DS3231.h :

As coisas explicadas até agora são suficientes para usar o módulo DS3231 com PIC para seus próprios projetos, mas para as mentes curiosas por aí, gostaria de saber o que realmente acontece dentro do arquivo de cabeçalho e os dados são realmente recebidos do módulo RTC pela PIC, apenas leia mais.

A melhor maneira de passar por isso é lendo o folha de dados do DS3231 completamente. Para fornecer um resumo do que é necessário, o módulo atua como escravo do PIC e o endereço de todo o módulo DS3231 é D0. Portanto, escreva dados para o módulo, precisamos passar o endereço D0 e, para ler dados do RTC, precisamos passar o endereço D1. Se passarmos o endereço de gravação o módulo RTC que nos preparamos para obter dados do PIC, para que os dados consequentes escritos pelo PIC sejam recebidos e salvos no módulo RTC. Da mesma forma se enviarmos o endereço para Read então o PIC deve se preparar para ler os valores do RTC, pois o módulo RTC começará a enviar todos os dados que possui. A sequência de bits para D0 e D1 é mostrada abaixo na folha de dados. Observe que o endereço 0b11010000 significa D0 (Write) e 0b11010001 significa D01 (Leia)

Quando o PIC envia o endereço D0 ou D1 para gravar ou ler, os seguintes dados devem ser lidos ou gravados em uma ordem. Esta ordem é mostrada na tabela abaixo. Portanto, os primeiros dados serão sec (00h) seguidos por minutos (01h) seguidos por horas (02h) seguidas por dia (03h) e até MSB de temperatura.

O módulo RTC não entende valores decimais, ele se comunica apenas através de valores BCD. Portanto, antes de escrever quaisquer valores no módulo RTC, ele deve ser convertido em BCD e também os valores recebidos do módulo RTC estarão no formato BCD e devem ser convertidos em Decimal para fazer sentido para nós. Com isso em mente, vamos criar toda a função necessária para o uso do módulo RTC.

Funções BCD_2_DEC e DEC_2_BCD :

As duas primeiras funções seriam usadas para converter o Dados BCD para dados decimais e decimais para BCD, pois o módulo RTC entende apenas BCD As fórmulas para converter BCD para Decimal e BCD para Decimal são.

Decimal = (BCD >> 4) * 10 + (BCD & 0x0F)

BCD = ((Decimal / 10) << 4) + (Decimal % 10)

Nós apenas temos que usar essas duas fórmulas para criar uma função que absorve a unidade oposta como parâmetro e a converte no formato necessário e a retorna, a função para fazer o mesmo é mostrada abaixo

int  BCD_2_DEC(int to_convert)
{
   return (to_convert >> 4) * 10 + (to_convert & 0x0F);
}

int DEC_2_BCD (int to_convert)
{
   return ((to_convert / 10) << 4) + (to_convert % 10);
}

Função Set_Time_Date() :

Esta função irá escreva o valor da hora e da data do módulo PIC para RTC Os valores de hora e data reais devem ser atualizados nas variáveis sec, min, hora, data, mês e ano pelo usuário. Esses valores serão convertidos em BCD e gravados no módulo RTC.

Como discutimos, para escrever um valor no módulo RTC, precisamos passar o endereço D0 e escrever um bull bit 0 para iniciar o processo de gravação. Em seguida, podemos enviar os dados na ordem, conforme mostrado na tabela acima.

void Set_Time_Date()
{
   I2C_Begin();      
   I2C_Write(0xD0);
   I2C_Write(0); 
   I2C_Write(DEC_2_BCD(sec)); //atualiza sec
   I2C_Write(DEC_2_BCD(min)); //atualiza min
   I2C_Write(DEC_2_BCD(hour)); //atualiza hour
   I2C_Write(1); //ignorar dia de atualização
   I2C_Write(DEC_2_BCD(date)); //atualização date
   I2C_Write(DEC_2_BCD(month)); //atualização month
   I2C_Write(DEC_2_BCD(year)); //atualização year
   I2C_End();
}

Função Update_Current_Date_Time() :

A última função na biblioteca é a usada leia a hora e a data do módulo RTC e passe-o para o microcontrolador PIC. Esta função é dividida em três segmentos, um para iniciar o processo de leitura o segundo para ler os valores e salvá-lo nas variáveis globais como sec, min, hora, data, mês e ano. E o terceiro é reconhecer que a leitura foi bem-sucedida.

Observe que, para cada ação, a comunicação I2C deve ser iniciada e finalizada.

Para ler os valores do RTC, precisamos enviar o endereço D0 seguido por um 0. Isso fará com que o módulo RTC envie todos os valores que possui na ordem mostrada na tabela acima. Podemos apenas lê-los convertê-los em Decimal e salvá-los nas variáveis na mesma ordem.

Finalmente, após a leitura, o módulo RTC enviará um bit de reconhecimento que também deve ser lido e reconhecido.

void Update_Current_Date_Time()
{
   //Inicia a Ler
   I2C_Begin();      
   I2C_Write(0xD0);
   I2C_Write(0);   
   I2C_End();
  
  //Ler
   I2C_Begin();
   I2C_Write(0xD1);                              // Inicializar dados lidos
   sec = BCD_2_DEC(I2C_Read(1));   
   min = BCD_2_DEC(I2C_Read(1));  
   hour = BCD_2_DEC(I2C_Read(1)); 
   I2C_Read(1);
   date = BCD_2_DEC(I2C_Read(1)); 
   month = BCD_2_DEC(I2C_Read(1)); 
   year = BCD_2_DEC(I2C_Read(1)); 
   I2C_End();

  //Fim Leitura
    I2C_Begin();
    I2C_Write(0xD1);                              // Initialize data read
    I2C_Read(1);   
    I2C_End();
}

Simulação:

O projeto pode ser simulado usando o software de simulação Proteus. Faça as conexões como mostrado no diagrama de circuitos e carregue o arquivo hexadecimal no controlador PIC. Ao simulá-lo, você encontrará duas caixas pop-up e a data e hora exibidas no LCD, como mostrado abaixo.

O pequeno na parte superior mostra a hora e a data atuais no módulo RTC e o segundo pop-up é o depurador I2C. É uma excelente ferramenta para verificar quais dados estão realmente sendo transmitidos dentro e fora do bug do I2C.

Hora e data da exibição no LCD :

Quando o seu hardware estiver pronto e o código é baixado como arquivo ZIP através do link fornecido, abra o programa usando o MPLABX IDE. Você precisa iniciar o IDE primeiro e usar a opção de projeto aberto e navegar para o conteúdo dentro do arquivo ZIP e abrir a pasta .X.

Basta verificar se o programa está compilando e fazer upload do código no seu hardware usando o PicKit3. Assim que o programa for carregado, você verá a mensagem introdutória e a hora e a data deverão ser exibidas conforme mostrado abaixo.

Se não houver nada no LCD, verifique suas conexões e verifique se o nível de contraste está definido corretamente, variando o potenciômetro. É assim que você pode mostrar a hora e a data de todos os seus projetos de microcontroladores PIC e pode usá-lo como Relógio Digital. Espero que você tenha aprendido algo novo e gostado de aprender este tutorial. Se você tiver algum problema, poste-os nos comentários abaixo.

Código

/*
 * File:   RTC_with_PIC_main.c
 */
#pragma config FOSC = HS        // Bits de seleção do oscilador (oscilador HS)
#pragma config WDTE = OFF       // Bit de habilitação do temporizador de watchdog (WDT desabilitado)
#pragma config PWRTE = ON       // Bit de ativação do temporizador de inicialização (PWRT habilitado)
#pragma config BOREN = ON       // Bit de habilitação de redefinição brown-out (BOR habilitado)
#pragma config LVP = OFF        // Bit de habilitação de programação serial em circuito de baixa tensão (fonte única) (RB3 é E/S digital, HV em MCLR deve ser usado para programação)
#pragma config CPD = OFF        // Bit de proteção de código de memória EEPROM de dados (proteção de código EEPROM de dados desativada)
#pragma config WRT = OFF        // Bits de habilitação de gravação de memória de programa flash (proteção contra gravação desativada; toda a memória de programa pode ser gravada pelo controle EECON)
#pragma config CP = OFF         // Bit de proteção de código de memória de programa flash (proteção de código desativada)

#define _XTAL_FREQ 20000000 //Estamos trabalhando com cristal de 20 MHz

// Defina os pinos do LCD
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7

/*Defina o valor atual de data e hora abaixo*/
int sec = 00;
int min = 55;
int hour = 10;
int date = 06;
int month = 05;
int year = 18;
/*Conjunto de data e hora*/

#include <xc.h>
#include "lcd.h" //Header para usar o módulo LCD
#include "PIC16F877a_I2C.h" // Header para usar o protocolo I2C
#include "PIC16F877a_DS3231.h" // Header para usar o módulo RTC DS3231

int main()
{

    TRISD = 0x00; //Faça os pinos da porta D como saída para interface de LCD
    
    Lcd_Start(); // Inicializar módulo LCD
    
    I2C_Initialize(100); //Inicializar I2C Master com clock de 100 KHz
        
    Set_Time_Date(); //definir hora e data no módulo RTC
    
     //Dê uma mensagem de introdução no LCD
     Lcd_Clear();
     Lcd_Set_Cursor(1,1);
     Lcd_Print_String("  RTC com PIC");
     Lcd_Set_Cursor(2,1);
     Lcd_Print_String(" -CapSistema");
     __delay_ms(1500); //display por 1,5 seg

while(1)
  {
 
    Update_Current_Date_Time(); //Leia a data e hora atuais do módulo RTC
    
    //Divida em char para exibir no LCD
     char sec_0 = sec%10;
     char sec_1 = (sec/10);
     char min_0 = min%10;
     char min_1 = min/10;
     char hour_0 = hour%10;
     char hour_1 = hour/10;
     char date_0 = date%10;
     char date_1 = date/10;
     char month_0 = month%10;
     char month_1 = month/10;
     char year_0 = year%10;
     char year_1 = year/10;
    
       //Exibir a hora na tela LCD
        Lcd_Clear();
        Lcd_Set_Cursor(1,1);
        Lcd_Print_String("TIME: ");
        Lcd_Print_Char(hour_1+'0');
        Lcd_Print_Char(hour_0+'0');
        Lcd_Print_Char(':');
        Lcd_Print_Char(min_1+'0');
        Lcd_Print_Char(min_0+'0');
        Lcd_Print_Char(':');
        Lcd_Print_Char(sec_1+'0');
        Lcd_Print_Char(sec_0+'0');
        
        //Exibir a data na tela LCD
        Lcd_Set_Cursor(2,1);
        Lcd_Print_String("DATE: ");
        Lcd_Print_Char(date_1+'0');
        Lcd_Print_Char(date_0+'0');
        Lcd_Print_Char(':');
        Lcd_Print_Char(month_1+'0');
        Lcd_Print_Char(month_0+'0');
        Lcd_Print_Char(':');
        Lcd_Print_Char(year_1+'0');
        Lcd_Print_Char(year_0+'0');
        __delay_ms(500); //refresh for every 0.5 sec
    
  }

    return 0;
}