Ir ao conteúdo
  • Cadastre-se

biblioteca ds3231 pic ccs


Posts recomendados

Essa é uma biblioteca que fiz para o DS3231, o bacana desse RTC é que ele possui oscilador interno e faz o ajuste do mesmo automaticamente de acordo com a temperatura (que pode ser lida pelo usuário), o que o torna mais preciso. Além disso ele possui 2 alarmes. Porém ele não possui RAM disponível para uso geral como o DS1307 possui xD.

 

Código para demonstrar o uso da biblioteca:

Spoiler

#include <16F883.h>
#device ADC = 10

#FUSES PUT                      //Power Up Timer
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOCPD                    //No EE protection
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES NOWRT                    //Program memory not write protected

#use delay(internal = 8000000)
#use rs232(baud = 9600, parity = N, uart1, bits = 8)
#use i2c(Master, Slow, i2c1, force_hw)

#define LED PIN_C2
#define DELAY 500

#include "ds3231.c"

void main() {
   int h, min, s, dw, dm, m, y;  
   short communication_status, oscillator_failed, alarm1_match, alarm2_match;
   float temperature;
   
   delay_ms(100);
   
   printf("\33[H\f"); // Send ESC (scape = \33[H) in ANSI so the realterm puts its cursor at home position and clear the terminal (\f)
   
   // THIS FUNCTION MUST BE CALLED VEFORE THE OTHERS
   // read the actual setting from the ds3231
   communication_status = ds3231_read_configuration(); 
   
   // all functions return the communication status so it can be checked to see if the ds3231 has acknowledged all bytes
   if(communication_status) {
      printf("\n\rsomething went wrong while trying to communicate with ds3231.");
      delay_ms(10);
      sleep();
   }
   
   //if this is the first time powering ds3231 up use this function to clear the flag that indicates the the oscilator was stopped
   communication_status = ds3231_clear_oscstop_flag();
   if(communication_status) {
      printf("\n\rsomething went wrong while trying to communicate with ds3231.");
      delay_ms(10);
      sleep();
   }
   
   // configure ds3231 so the SQW is off when the chip is being powered by the battery (_swq_bat_off) other option: _swq_bat_off
   // when the SQW/INT pin is configured to SQW the freqeuncy will be 4KHzz (_sqw_freq_4khz) other options: _sqw_freq_1hz, _sqw_freq_1khz, _sqw_freq_8khz 
   // configure the pin SQW/INT to be driven low, if alarm interrupt is enabled, when alarm 1 or 2 match (_pin_sqwint_as_int) other option: _pin_sqwint_as_sqw
   // enable alarm 1 interrupt (_al1_interrupt_on) other option: _al1_interrupt_off
   // enable alarm 2 interrupt (_al2_interrupt_on) other option: _al2_interrupt_off
   communication_status = ds3231_initialize(_swq_bat_off|_sqw_freq_4khz|_pin_sqwint_as_int|_al2_interrupt_on|_al1_interrupt_on);
   
   // You can also configure using these functions:
   // 
   // --> ALARM:
   //    ds3231_enable_alarm1_interrupt();
   //    ds3231_disable_alarm1_interrupt();
   //    ds3231_enable_alarm2_interrupt();
   //    ds3231_disable_alarm2_interrupt();
   //
   // --> PIN INT/SQW:
   //    ds3231_intsqw_function(_interrupt)
   //    ds3231_intsqw_function(_sqw) 
   //
   // --> SQW FREQUENCY
   //    ds3231_set_sqw_frequency(_sqw_freq_1hz);
   //    ds3231_set_sqw_frequency(_sqw_freq_1khz);
   //    ds3231_set_sqw_frequency(_sqw_freq_4khz);
   //    ds3231_set_sqw_frequency(_sqw_freq_8khz);
   //
   // --> SQW BATTERY
   //    ds3231_sqw_battery(_sqw_bat_on);
   //    ds3231_sqw_battery(_sqw_bat_off);
   
   // disable 32KHz squared wave the pin goes to a high impedance state.
   // to enable it use the function s3231_enable_32khz();
   ds3231_disable_32khz();
   
   // read the oscillator stop flag to see if it has failed at some point in the past
   ds3231_read_oscstop_flag(oscillator_failed);  
   if(oscillator_failed) {          // if it has failed
      // take some action
      ds3231_clear_oscstop_flag();  // and clear it
   }
   
   // Set time to 23:50:45
   ds3231_set_time(23, 50, 50);
   
   // set date. day of the month: 26, month: 1, year: 2017, day of the week: 5
   ds3231_set_date(5, 26, 1, 17);
   
   // set alarm 1 to 23:50:06 day of the month: 26, other options:
   //_Alarm1_once_per_second
   //_Alarm1_when_seconds_match 
   //_Alarm1_when_minutes_seconds_match
   //_Alarm1_when_hours_minutes_seconds_match
   //_Alarm1_when_date_hours_minutes_seconds_match
   //_Alarm1_when_day_hours_minutes_seconds_match
   ds3231_set_alarm1(_alarm1_when_date_hours_minutes_seconds_match, 23, 51, 6, 26);
   
   // set alarm 2 to 23:52 day of the week: 5, other opitins:
   //_Alarm2_once_per_minute
   //_Alarm2_when_minutes_match
   //_Alarm2_when_hours_minutes_match
   //_Alarm2_when_date_hours_minutes_match
   //_Alarm2_when_day_hours_minutes_match
   ds3231_set_alarm2(_alarm2_when_day_hours_minutes_match, 23, 52, 5);
      
   while(true) {
      // Reading ds3231 temperature
      ds3218_read_temperature(temperature);
      printf("\n\n\rtemp: %.2f", temperature);
      
      // Get time
      ds3231_read_time(h, min, s);
      printf("\n\r%02u:%02u:%02u", h, min, s);
      
      // Get date
      ds3231_read_date(dw, dm, m, y);
      printf("\n\r%02u/%02u/%02u Day week: %u", dm, m, y, dw);
      
      // check alarm 1
      ds3218_check_alarm1(alarm1_match);
      if(alarm1_match) {
         printf("\n\r>> ALARM 1 HAS MATCHED. CLEARING IT...");
         
         // clear alarm 1 flag
         ds3231_clear_alarm1();
      }
      
      // check alarm 2
      ds3218_check_alarm2(alarm2_match);
      if(alarm2_match) {
         printf("\n\r>> ALARM 2 HAS MATCHED. CLEARING IT...");
         
         // clear alarm 2 flag
         ds3231_clear_alarm2();
      }      
      
      output_toggle(LED);
      delay_ms(DELAY);
      
      output_toggle(LED);
      delay_ms(DELAY);
   }
}

 

 

Biblioteca (ds3231.c):

Spoiler

#define bus_free_time         0x05
#define _ack                  0x01
#define _nack                 0x00

#define _ds3231_wadd          0xD0
#define _ds3231_radd          0xD1

#define _ds3231_seconds_reg   0x00
#define _ds3231_minutes_reg   0x01
#define _ds3231_hours_reg     0x02

#define _ds3231_day_reg       0x03  // day of the week
#define _ds3231_date_reg      0x04  // day of the month
#define _ds3231_month_reg     0x05
#define _ds3231_year_reg      0x06

#define _ds3231_al1sec_reg    0x07
#define _ds3231_al1min_reg    0x08
#define _ds3231_al1hour_reg   0x09
#define _ds3231_al1day_reg    0x0A

#define _ds3231_al2min_reg    0x0B
#define _ds3231_al2hour_reg   0x0C
#define _ds3231_al2day_reg    0x0D

#define _ds3231_control_reg   0x0E
#define _ds3231_status_reg    0x0F

#define _ds3231_msb_temp_reg  0x11
#define _ds3231_lsb_temp_reg  0x12

#define _osc_off              0x80
#define _osc_on               0x00  // This is the state when ds3231 is powered POR

#define _swq_bat_on           0x40
#define _swq_bat_off          0x00  // This is the state when ds3231 is powered POR

#define _sqw_freq_1hz         0x00 
#define _sqw_freq_1khz        0x08
#define _sqw_freq_4khz        0x10
#define _sqw_freq_8khz        0x18  // This is the state when ds3231 is powered POR

#define _pin_sqwint_as_int    0x04  // This is the state when ds3231 is powered POR
#define _pin_sqwint_as_sqw    0x00
#define _interrupt            0x04  // This is the state when ds3231 is powered POR
#define _sqw                  0x00

#define _al2_interrupt_on     0x02
#define _al2_interrupt_off    0x00  // This is the state when ds3231 is powered POR

#define _al1_interrupt_on     0x01
#define _al1_interrupt_off    0x00  // This is the state when ds3231 is powered POR

#define _default_por          0x20

#define _32khz_en             0x08  // This is the state when ds3231 is powered POR        
#define _32khz_disa           0x00

#define _alarm1_once_per_second                       0x0F
#define _alarm1_when_seconds_match                    0x0E
#define _alarm1_when_minutes_seconds_match            0x0C
#define _alarm1_when_hours_minutes_seconds_match      0x08
#define _alarm1_when_date_hours_minutes_seconds_match 0x00
#define _alarm1_when_day_hours_minutes_seconds_match  0x10
 
#define _alarm2_once_per_minute                       0x07
#define _alarm2_when_minutes_match                    0x06
#define _alarm2_when_hours_minutes_match              0x04
#define _alarm2_when_date_hours_minutes_match         0x00
#define _alarm2_when_day_hours_minutes_match          0x08


int _ds3231_shadow_ctrlreg;  // Variable that holds the actual state of the control register
int _en32khz_shadow;

int ds3231_initialize(int _configuration_word) {
   int _status, _current_hour;
   
   _ds3231_shadow_ctrlreg = _configuration_word;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);   //configure the control reg
   
   i2c_start();                                    //Repeated start to configure the hour format to 24h
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_hours_reg);
   i2c_start();  
   _status = i2c_write(_ds3231_radd);
   _current_hour = i2c_read(_nack);               //Read the current hour to not configure it with a wrong time
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_hours_reg);
   _current_hour &= 0xBF;                          // Clear bit 6 (24 hour mode)
   _status |= i2c_write(_current_hour);
   i2c_stop();
   
   return(_status);
}

int ds3231_read_configuration() {
   int _status;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _ds3231_shadow_ctrlreg = i2c_read(_ack);
   _en32khz_shadow = i2c_read(_nack);
   i2c_stop();
   
   _en32khz_shadow &= 0x08;
   _ds3231_shadow_ctrlreg &= 0xDF; // leave thee CONV bis as zero wich is its normal state 
   
   return(_status);
}

int ds3231_intsqw_function(int _function) {
   int _status;
   
   if(bit_test(_function, 2)) 
      _ds3231_shadow_ctrlreg |= 0x04;
      
      else
         _ds3231_shadow_ctrlreg &= 0xFB;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop();
   
   return(_status);
}

int ds3231_set_sqw_frequency(int _frequency) {
   int _status;
   
   _ds3231_shadow_ctrlreg &= 0xE7;
   _ds3231_shadow_ctrlreg |= _frequency;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop();  
   
   return(_status);
}

int ds3231_enable_alarm1_interrupt() {
   int _status;
   
   _ds3231_shadow_ctrlreg |= 0x01;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status);
}

int ds3231_disable_alarm1_interrupt() {
   int _status;
   
   _ds3231_shadow_ctrlreg &= 0xFE;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status);
}

int ds3231_enable_alarm2_interrupt() {
   int _status;
   
   _ds3231_shadow_ctrlreg |= 0x02;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status);
}

int ds3231_disable_alarm2_interrupt() {
   int _status;
   
   _ds3231_shadow_ctrlreg &= 0xFD;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status);
}

int ds3231_sqw_battery(int _swq_bat_on_or_swq_bat_off) {
   int _status;
   
   _ds3231_shadow_ctrlreg &= 0xBF;
   _ds3231_shadow_ctrlreg |= _swq_bat_on_or_swq_bat_off;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status);   
}

int ds3231_enable_oscillator() {
   int _status;
   
   _ds3231_shadow_ctrlreg &= 0x7F; // 0 = oscillator enabled
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status); 
}

int ds3231_disable_oscillator() {
   int _status;
   
   _ds3231_shadow_ctrlreg |= 0x80;  // 1 = oscillator disabled
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   return(_status); 
}

int ds3231_start_temp_conversion() {
   int _status;
   
   _ds3231_shadow_ctrlreg |= 0x20;  // set the conv bit in the control Reg.
                                    // this bit will return to zero when conversion finishes
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_control_reg);
   _status |= i2c_write(_ds3231_shadow_ctrlreg);
   i2c_stop(); 
   
   _ds3231_shadow_ctrlreg &= 0xDF;  // Clearing conv bit of the shadow variable since it will be cleared automatically
   return(_status);    
}

int ds3231_read_busybit(short &_bsy_bit) {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   //printf("sreg=%u",_status_reg);
   _bsy_bit = bit_test(_status_reg, 2);
   
   return(_status);
}

int ds3231_read_oscstop_flag(short &_oscillator_stop_flag) {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   //printf("sreg=%u",_status_reg);
   _oscillator_stop_flag  = bit_test(_status_reg, 7);
   
   return(_status);
}

int ds3231_clear_oscstop_flag() {
   int _status, _status_reg;
    
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   //i2c_stop();
   
   _status_reg &= 0x7F;
   
   //delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   _status |= i2c_write(_status_reg);
   i2c_stop();
   
   return(_status);
}

int ds3231_enable_32khz() {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   _status_reg |= 0x08;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   _status |= i2c_write(_status_reg);
   i2c_stop();
   
   _en32khz_shadow = 0x08;
   
   return(_status);
}

int ds3231_disable_32khz() {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   _status_reg &= 0xF7;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   _status |= i2c_write(_status_reg);
   i2c_stop();
   
   _en32khz_shadow = 0x00;
   
   return(_status);
}

int ds3218_check_alarm1(short &_al1_flag) {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   _al1_flag = bit_test(_status_reg, 0);
   
   return(_status);
}

int ds3218_check_alarm2(short &_al2_flag) {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   _al2_flag = bit_test(_status_reg, 1);
   
   return(_status);
}

int ds3218_read_oscfail_flag(short &_osc_fail) {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   i2c_stop();
   
   _osc_fail = bit_test(_status_reg, 7);
   
   return(_status);
}

int ds3218_read_temperature(float &_ds3231_temperature) {
   int _status, _temp_low;
   signed int _temp_high;
   float _aux_temperatura;
   short flag_t_negativa = 0;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_msb_temp_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _temp_high = i2c_read(_ack);
   _temp_low = i2c_read(_nack);
   i2c_stop();
   
   //printf("\n\rth: %u, tl: %u",_temp_high,_temp_low);
   
   if(bit_test(_temp_high, 7)) {                   // if the temperature is negative     
      if(_temp_low != 0)                           // and the fractional portion is different than zero
         _temp_high += 1;                          // add 1 to the MSB since it is in two's complement
         
      _temp_low = ~_temp_low;                        
      _temp_low++;  
      
      flag_t_negativa = 1;
   }  
        
   if(bit_test(_temp_low, 6))
      _aux_temperatura += 0.25;
      
   if(bit_test(_temp_low, 7))
      _aux_temperatura += 0.5;     

   if(flag_t_negativa==1)                       // Se atemperatura for negativa ajusta
      _aux_temperatura*=-1;                     // então a parte fracionária é negativada
   
   _ds3231_temperature = _aux_temperatura + (float)_temp_high;
   
   return(_status);
}

void convert_bcd_to_binary(int &_value1, int &_value2, int &_value3) {
   int _digit1, _digit2;//para 38 _digio2=3 _digit1=8
   
   _digit1 = _value1 & 0x0F;//and bit a bit com os 4 LSB para pegar o digito 1.
   _digit2 = _value1 & 0xF0;//and bit a bit com os 4 MSB
   _digit2 >>= 4; //descola 4 bits para a direita para pegar o digito 2.
   _value1 = _digit2 * 10 + _digit1;

   _digit1 = _value2 & 0x0F;
   _digit2 = _value2 & 0xF0;
   _digit2 >>= 4;
   _value2 = _digit2 * 10 + _digit1;

   _digit1 = _value3 & 0x0F;
   _digit2 = _value3 & 0xF0;
   _digit2 >>= 4;
   _value3 = _digit2 * 10 + _digit1;   
}

void convert_binary_to_bcd(int &_value1, int &_value2, int &_value3) {
   int _digit1, _digit2;
   
   _digit1 = _value1 % 10;
   _digit2 = (_value1 - _digit1) / 10;
   _value1 = (_digit2 << 4) + _digit1;

   _digit1 = _value2 % 10;
   _digit2 = (_value2 - _digit1)/10;
   _value2 = (_digit2 << 4) + _digit1;
   
   _digit1 = _value3%10;
   _digit2 = (_value3 - _digit1)/10;
   _value3 = (_digit2<<4) + _digit1;   
}

int ds3231_read_time(int &_hours, int &_minutes, int &_senconds) {
   int _status;
   int _data[3];
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_seconds_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _data[0] = i2c_read(_ack);    // Seconds
   _data[1] = i2c_read(_ack);    // Minutes
   _data[2] = i2c_read(_nack);   // Hours
   i2c_stop();
   
   //_data[2] &= 0x3F; not needed
   convert_bcd_to_binary(_data[0], _data[1], _data[2]);
   
   _senconds = _data[0];
   _minutes = _data[1];
   _hours = _data[2];
   
   return(_status);
}

int ds3231_set_time(int _hours, int _minutes, int _senconds) {
   int _status;
   
   convert_binary_to_bcd(_hours, _minutes, _senconds);
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_seconds_reg);
   _status |= i2c_write(_senconds);
   _status |= i2c_write(_minutes);
   _status |= i2c_write(_hours);
   i2c_stop();
   
   return(_status);
}

int ds3231_read_date(int &_week_day, int &_month_day, int &_month, int &_year) {
   int _status;
   int _data[4];
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_day_reg);
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _data[0] = i2c_read(_ack);    // Day of the week
   _data[1] = i2c_read(_ack);    // Day of the month
   _data[2] = i2c_read(_ack);    // Month
   _data[3] = i2c_read(_nack);   // Year
   i2c_stop();
   
   //_data[2] &= 0x3F; not needed
   convert_bcd_to_binary(_data[1], _data[2], _data[3]);
   
   _week_day = _data[0];
   _month_day = _data[1];
   _month = _data[2];
   _year = _data[3];
   
   return(_status);
}

int ds3231_set_date(int _week_day, int _month_day, int _month, int _year) {
   int _status;
   
   convert_binary_to_bcd(_month_day, _month, _year);
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_day_reg);
   _status |= i2c_write(_week_day);
   _status |= i2c_write(_month_day);
   _status |= i2c_write(_month);
   _status |= i2c_write(_year);
   i2c_stop();
   
   return(_status);
}

#INLINE
void convert_binary_to_bcd_alarms(int &_value1, int &_value2, int &_value3, int &_value4) {
   int _digit1, _digit2;
   
   _digit1 = _value1 % 10;
   _digit2 = (_value1 - _digit1) / 10;
   _value1 = (_digit2 << 4) + _digit1;

   _digit1 = _value2 % 10;
   _digit2 = (_value2 - _digit1)/10;
   _value2 = (_digit2 << 4) + _digit1;
   
   _digit1 = _value3%10;
   _digit2 = (_value3 - _digit1)/10;
   _value3 = (_digit2<<4) + _digit1;   

   _digit1 = _value4 % 10;
   _digit2 = (_value4 - _digit1) / 10;
   _value4 = (_digit2 << 4) + _digit1;  
}

int ds3231_set_alarm1(int _mode, int _hours, int _minutes, int _seconds, int _day_of_week_or_month) {
   int _status;
   
   convert_binary_to_bcd_alarms(_seconds, _minutes, _hours, _day_of_week_or_month);
   //printf("\n\n\r>>>h%u, m%u, s%u, d%u", _hours, _minutes, _seconds, _day_of_week_or_month);
    
   if(bit_test(_mode, 0))
      _seconds |= 0x80;
   
   if(bit_test(_mode, 1))
      _minutes |= 0x80;
      
   if(bit_test(_mode, 2))   
      _hours |= 0x80;
   
   if(bit_test(_mode, 3))
      _day_of_week_or_month |= 0x80;
   
   if(bit_test(_mode, 4))
      _day_of_week_or_month |= 0x40;
   
   //printf("\n\r>>h%u, m%u, s%u, d%u", _hours, _minutes, _seconds, _day_of_week_or_month);
   
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_al1sec_reg);
   _status |= i2c_write(_seconds);
   _status |= i2c_write(_minutes);
   _status |= i2c_write(_hours);
   _status |= i2c_write(_day_of_week_or_month);
   i2c_stop();   
    
   return(_status);
}

int ds3231_clear_alarm1() {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   _status_reg &= 0xFE;
   
   i2c_start();
   _status |= i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);   
   _status |= i2c_write(_status_reg);   
   
   i2c_stop();   
   
   return(_status);
}

int ds3231_set_alarm2(int _mode, int _hours, int _minutes, int _day_of_week_or_month) {
   int _status;
   
   convert_binary_to_bcd(_minutes, _hours, _day_of_week_or_month);
   //printf("\n\n\r>>>h%u, m%u, s%u, d%u", _hours, _minutes, _seconds, _day_of_week_or_month);
    
   if(bit_test(_mode, 0))
      _minutes |= 0x80;
      
   if(bit_test(_mode, 1))   
      _hours |= 0x80;
   
   if(bit_test(_mode, 2))
      _day_of_week_or_month |= 0x80;
   
   if(bit_test(_mode, 3))
      _day_of_week_or_month |= 0x40;
   
   //printf("\n\r>>h%u, m%u, s%u, d%u", _hours, _minutes, _seconds, _day_of_week_or_month);
   
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_al2min_reg);
   _status |= i2c_write(_minutes);
   _status |= i2c_write(_hours);
   _status |= i2c_write(_day_of_week_or_month);
   i2c_stop();   
    
   return(_status);
}

int ds3231_clear_alarm2() {
   int _status, _status_reg;
   
   delay_us(bus_free_time);
   i2c_start();
   _status = i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);
   
   i2c_start();
   _status |= i2c_write(_ds3231_radd);
   _status_reg = i2c_read(_nack);
   _status_reg &= 0xFD;
   
   i2c_start();
   _status |= i2c_write(_ds3231_wadd);
   _status |= i2c_write(_ds3231_status_reg);   
   _status |= i2c_write(_status_reg);   
   
   i2c_stop();   
   
   return(_status);
}

 

 

mWumaHh.jpg

 

cF62RIS.png

 

 

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

Valeu ai @ViniciusKruz

 

Esqueci de falar... Eu removi o resistor que está em série com o diodo pois a bateria que estou usando é a CR2032 (não recarregável), mesmo assim acho que a qualidade desse carregar (conjunto diodo + resistor) é duvidosa :huh:.


0YszDCn.jpg

 

Outra coisa, a frequência do pino SQW não muda no meu DS3231, não consegui entender o porquê só fica em 1Hz... Escrevo no Control Register e depois leio ele para garantir que foi escrito corretamente mas mesmo assim a frequência não muda :mellow:...

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@test man*~  No meu eu também removi esse resistor pra usar a CR2032, no meu caso estou usando uma biblioteca do arduíno, esse bichim é tão preciso que não alterei nada na frequência, deixei do jeito que veio da fábrica e já deve ter uns 3 meses e ele não alterou nem 20 segundos, pra mim esta precisão já está pra lá de boa, se fossem os outros RTCs que já usei, pra conseguir essa mesma precisão seria necessário um tremendo esforço com os capacitores do cristal.

 

Tem um amigo aqui no fórum que está mexendo nessa frequência, só que ele usa é um ESP + arduíno também, no caso dele, está alcançando uma precisão incrível, o próprio ESP acessa os servidores NTPs e corrige a frequência sozinho. 

 

Caso interesse o link para o tópico com o arquivo de teste que ele disponibilizou é esse:

https://www.clubedohardware.com.br/forums/topic/1134300-esp8266-a-pequena-maravilha-para-comunicação-wifi/?do=findComment&comment=6561099

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!