segunda-feira, 13 de fevereiro de 2017

Comunicando com o RTC DS3234 (com PIC16F887 )

        Olá, hoje vou demonstrar como usar o RTC(real time clock) DS3234, a maior
vantagem é possuir internamente no chip o cristal oscilador e um sensor de temperatura,
assim não precisa elementos externo para fazer funcionar o chip RTC. Funcionou tanto na
simulação quanto fisicamente.
   

O código fonte :
/*
 *                                   RTC DS3234 com pic - MPlab XC8
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F887
 * Autor: Aguivone
 * Versão: 1
 * Data :  13/02/2017
 */
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#include <stdlib.h>
#define _XTAL_FREQ 20000000//usado para rotinas de  delays
#include <xc.h>

/////////////////////////////////////////////////////////configuraçôes//////////////////////////////////////////////////

#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#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)
unsigned char gucAlternaPino;
unsigned char gucSPI_lido;
//Defines
#define LED_STATUS                  RD0 
/*#define DS3234_SDO                 TRISCbits.TRISC7
#define DS3234_SDI                 TRISBbits.TRISB0
#define DS3234_SCK                 TRISBbits.TRISB1*/
#define DS3234_SS                  RC2 
//***********************************************************************************************************
// Registradores do chip DS3234 - endereço de leitura,para escrever basta somar 0X80 ao valor hexadecimal
//***********************************************************************************************************
#define DS3234_SEG               0X00 // registrador de segundos
#define DS3234_MIN               0X01 // registrador de minutos
#define DS3234_HORA              0X02 // registrador de horas
#define DS3234_DIA_SEMANA        0X03 // registrador de dia da semana
#define DS3234_DIA               0X04 // registrador de dia
#define DS3234_MES               0X05 // registrador de Mes
#define DS3234_ANO               0X06 // registrador de ano

#define DS3234_ALM1_SEG          0X07 // registrador Alarme 1 de segundos
#define DS3234_ALM1_MIN          0X08 // registrador Alarme 1 de minutos
#define DS3234_ALM1_HORA         0X09 // registrador Alarme 1 de horas
#define DS3234_ALM1_DIA_SEMANA   0X0A // registrador Alarme 1 de dia e dia da semana

#define DS3234_ALM2_MIN          0X0B // registrador Alarme 2 de minutos
#define DS3234_ALM2_HORA         0X0C // registrador Alarme 2 de horas
#define DS3234_ALM2_DIA_SEMANA   0X0D // registrador Alarme 2 de dia e dia da semana

#define DS3234_CONTROL           0X0E // registrador de controle
#define DS3234_STAT_CONTROL      0X0F // registrador de controle e status
#define DS3234_CONF_CRISTAL      0X10 // registrador do cristal interno

#define DS3234_TEMP_H            0X11 // registrador do sensor de temperatura parte alta(msb))
#define DS3234_TEMP_L            0X12 // registrador do sensor de temperatura parte baixa(lsb)

#define DS3234_S_RAM             0X18 // registrador da memoria S_RAM
#define DS3234_S_RAM_DADOS       0X18 // registrador da memoria S_RAM dados

//***********************************************************************************************************
// FUNÇÕES
//***********************************************************************************************************
//===========================================================================================================
// Função:     _configura_SPI
// Parâmetros: nenhum
// Retorno:    nenhum
// Descrição:  configura a parte de hardware que gerencia a SPI.
//===========================================================================================================
void inicializa_spi() //o timer 2 é usado para controlar a spi
{
    //RTC - DS3234
      SSPSTAT = 0B10000000;//modo metre / clock na borda de decida
      SSPCON = 0B00110010;//habilita os pinos da SPI/config clock como nivel altoe freq osc/64.   
}

/////////////////////////////////funçoes usadas pela uart //////////////////////////////////////////////////////
void inicializa_RS232(void)
{//// por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada.
    //modo alta velocidade
    RCSTA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
    TXSTA = 0X24;//modo assincrono,trasmissao 8 bits.
    //somente para cristal de 20Mhz.           
    SPBRG = 129;//9600    
 //   RCIE = 1;//habilita interrupção de recepção
    RCIE = 0;//habilita interrupção de recepção
    TXIE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
}
void escreve(char cValor)
{
     TXIF = 0;//limpa flag que sinaliza envio completo.
     TXREG = cValor;
     __delay_us(1);//1us para evitar problemas de perder caracteres
     while(TXIF == 0);//espera enviar caracter
}
void imprime(const char frase[])
{
     char indice = 0;
     char tamanho = strlen(frase);
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve(frase[indice]);
           indice++;
       }
}
void hex_to_int_char(char quant)
{//converte para inteiro e imprime
     unsigned char ucDez='0', ucUn='0';
    if(quant>=100)
    {//imprime centenas
       while(quant>=100)
       {
          quant -= 100;  
           ucDez++;  
       }
       escreve(ucDez);
       ucDez='0';//zera variavel novamente
    }
    while(quant>=10)
    {
      quant -= 10;  
      ucDez++;  
    }
    while(quant>=1)
    {
       quant -= 1; 
       ucUn++;  
    }
     escreve(ucDez);
     escreve(ucUn);
}
void hex_to_char(char quant)
{//converte para char e imprime
   unsigned char ucDez, ucUn;
    
    ucDez = quant/16;
    ucUn = quant%16;
    if(ucDez >= 10)
        ucDez = (ucDez-10) + 'A';
    else
        ucDez += '0';
    if(ucUn >= 10)
        ucUn = (ucUn-10) + 'A';
    else
        ucUn += '0';
          escreve(ucDez);
          escreve(ucUn);

}

unsigned char DS3234_LER_SPI(unsigned char registrador)
{ 
   unsigned char dado  = SSPBUF;//para limpar buffer 
   DS3234_SS  = 0;  // ativa SS(slave select)
   SSPBUF = registrador;//envia endereço
   while(!SSPSTATbits.BF);//espera completar envio de dados
   dado  = SSPBUF;//para limpar buffer e SSPSTATbits.BF
 //  for(unsigned char Cont=0;Cont<10;Cont++);  // Este tempo é necessário para finalizar  primeira transmissão
   SSPBUF = 0X00;//envia um informação qualquer para que os dados do slave chegue(pois ainda precisa de mais 8 clock)
   while(!SSPSTATbits.BF);//espera completar envio de dados
   dado  = SSPBUF;//para limpar buffer e SSPSTATbits.BF
   DS3234_SS  = 1;//desabilita chip   
  return(dado);//retorna valor
}
void DS3234_ESCREVE_SPI(unsigned char endereco,unsigned char valor)
{
    unsigned char dado  = SSPBUF;//para limpar buffer 
    endereco = endereco|0X80;//pronto pra escrever
    DS3234_SS  = 0;  // ativa SS(slave select)
    SSPBUF = endereco;//opcode que sinaliza que quer deixar um dado
    while(!SSPSTATbits.BF);//espera completar envio de dados
    dado  = SSPBUF;//para limpar buffer e SSPSTATbits.BF
 //   for(unsigned char Cont=0;Cont<10;Cont++);  // Este tempo é necessário para finalizar  primeira transmissão
    SSPBUF = valor;//envia os dados que será colocado no registrador
    while(!SSPSTATbits.BF);//espera completar envio de dados
    dado  = SSPBUF;//para limpar buffer e SSPSTATbits.BF
    DS3234_SS  = 1;//desabilita chip
}

void inicializa_RTC()
{    
    DS3234_ESCREVE_SPI(DS3234_CONTROL,0X80);//80= desliga saida do oscilador , SQ wave @1hz, Alarme desabilitados
    DS3234_ESCREVE_SPI(DS3234_ANO,0X17);//25/08/2017 - 15:05
    DS3234_ESCREVE_SPI(DS3234_MES,0X08);//colocar os valores sempre em hexadecimal
    DS3234_ESCREVE_SPI(DS3234_DIA,0X25);
    DS3234_ESCREVE_SPI(DS3234_HORA,0X15);
    DS3234_ESCREVE_SPI(DS3234_MIN,0X05);
    
}
//////////////////////////////////////////////////////Rotina principal///////////////////////////////////////////////////////////////

void main(void)
{
    TRISA = 0XDF;   //somente pino 5 é saida
    TRISB = 0;   //configura como saida
    TRISC = 0X10;   //somete C4 é entrada(SDI))
    TRISD = 0;   //configura como saida
    TRISE = 0XFF;   //configura como entrada
    PORTA = 0;
    PORTB = 0;  // limpar as portas que estão configuradas como saidas
    PORTC = 0;
    PORTD = 0;
    PORTE = 0;
    inicializa_RS232();
    inicializa_spi();
    GIE = 0; //desliga interrupções 
    ADCON0 = 0X00;//desabilita modulo ADC
    ADCON1 = 0X07;//desliga modulo comparador
    ANSEL = 0x00;   // Disable todas as portas analogicas
    CM1CON0 = 0;
    CM2CON0 = 0;
    long Pisca = 200;//tempo qualquer 
    __delay_ms(50);
    imprime("Usando : RTC_DS3234 \r\n");
    inicializa_RTC();
    for(;;)    
    {        
        if(Pisca == 0)
            {
                 if(gucAlternaPino == '0')
                {
                  LED_STATUS=0;
                  gucAlternaPino = '1';
                  gucSPI_lido = DS3234_LER_SPI(DS3234_HORA);                  
                  hex_to_char( gucSPI_lido);
                  escreve(':');
                  gucSPI_lido = DS3234_LER_SPI(DS3234_MIN);
                  hex_to_char( gucSPI_lido);
                  escreve(':');
                  gucSPI_lido = DS3234_LER_SPI(DS3234_SEG);
                  hex_to_char( gucSPI_lido);
                  escreve('-');
                  escreve('>');
                  gucSPI_lido = DS3234_LER_SPI(DS3234_DIA);
                  hex_to_char( gucSPI_lido);
                  escreve('/');
                  gucSPI_lido = DS3234_LER_SPI(DS3234_MES);
                  hex_to_char( gucSPI_lido);
                  escreve('/');
                  gucSPI_lido = DS3234_LER_SPI(DS3234_ANO);
                  hex_to_char( gucSPI_lido);  
                 imprime("\r\n Temperatura :");//para temperatura negativas é preciso fazer 
                  gucSPI_lido = DS3234_LER_SPI(DS3234_TEMP_H);//alguns tratamentos aqui vamos demontrar apena para uma escala acima de 0
                  hex_to_int_char( gucSPI_lido); 
                  // praticamente não vai fazer diferença
                  // gucSPI_lido = DS3234_LER_SPI(DS3234_TEMP_L);
                  //hex_to_int_char( gucSPI_lido);
                  imprime("\r\n");
                }
                else
                {
                  LED_STATUS=1;
                  gucAlternaPino = '0';
                } 
                 Pisca = 200;
            }
        else
        {
           Pisca--;
           __delay_ms(1);
        }
            
    }//loop infinito

}

A simulação ficou assim:


Nenhum comentário :

Postar um comentário

olá,digite aqui seu comentário!