Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

the critiria of throwing (setting/initializing) the time of the RTC

Status
Not open for further replies.

7@rB

Junior Member level 3
Junior Member level 3
Joined
Feb 19, 2012
Messages
25
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Location
Lebanon
Visit site
Activity points
1,458
hello,
am using a pic18f4525 microcontroller with an interface with a pcf8583 (RTC) and a 16x2 LCD, everything is going right and the time is appearing at the LCD, that is with simulation on proteus.
my question is:
the time appearing with the simulation is correct (the real time), but it is taken from the computer!, when I move for the real application (testing with bread board) what time will be displayed and what is the method or the way to initialize or set the time of the RTC?!

this is a part of my code:

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Read_Time() {
 
  Soft_I2C_Start();               // Issue start signal
  Soft_I2C_Write(0xA0);           // Address PCF8583, see PCF8583 datasheet
  Soft_I2C_Write(2);              // Start from address 2
  Soft_I2C_Start();               // Issue repeated start signal
  Soft_I2C_Write(0xA1);           // Address PCF8583 for reading R/W=1
 
  seconds = Soft_I2C_Read(1);     // Read seconds byte
  minutes = Soft_I2C_Read(1);     // Read minutes byte
  hours = Soft_I2C_Read(1);       // Read hours byte
  day = Soft_I2C_Read(1);         // Read year/day byte
  month = Soft_I2C_Read(0);       // Read weekday/month byte
  Soft_I2C_Stop();                // Issue stop signal
 
}
 
//-------------------- Formats date and time
void Transform_Time() {
  seconds  =  ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F) ;  // Transform seconds
  minutes  =  ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F);  // Transform months
  hours    =  ((hours & 0xF0)  >> 4)*10  + (hours & 0x0F);    // Transform hours
  year     =   (day & 0xC0) >> 6;                             // Transform year
  day      =  ((day & 0x30) >> 4)*10    + (day & 0x0F);       // Transform day
  month    =  ((month & 0x10)  >> 4)*10 + (month & 0x0F);     // Transform month
}



I tried to set the time using buttons by which I increase the hours variable for example when pushing one of these buttons but the time then reaches 27:24:12 for example!

help plzzz
 
Last edited by a moderator:

what is the method or the way to initialize or set the time of the RTC?!

You must first halt the clock before writing the appropriate BCD values into the proper location of the PCF8583.

Reference: t, Section: 7.11 Initialization, Page: 14
Initialization
When power-on occurs the I2C-bus interface, the control and status register and all clock
counters are reset. The device starts time-keeping in the 32.768 kHz clock mode with the
24 hour format on the first of January at 0.00.00:00. A 1 Hz square wave with 50 % duty
cycle appears at the interrupt output pin (starts HIGH).

The stop counting flag of the control and status register must be set before loading the
actual time into the counters.
Loading of illegal states leads to a temporary clock
malfunction.

The following is a driver intended for the CCS compiler, however you should be able to port it to most PIC C Compilers:

Reference: PCF8583 driver
Code:
// PCF8583.C

#ifndef PCF8583_SDA
#define PCF8583_SDA  PIN_C4
#define PCF8583_SCL  PIN_C3
#endif

#use i2c(master, sda=PCF8583_SDA, scl=PCF8583_SCL)

#ifndef PCF8583_WRITE_ADDRESS
#define PCF8583_WRITE_ADDRESS 0xA0
#define PCF8583_READ_ADDRESS  0xA1
#endif

// Register addresses
#define PCF8583_CTRL_STATUS_REG    0x00
#define PCF8583_100S_REG           0x01
#define PCF8583_SECONDS_REG        0x02
#define PCF8583_MINUTES_REG        0x03
#define PCF8583_HOURS_REG          0x04
#define PCF8583_DATE_REG           0x05
#define PCF8583_MONTHS_REG         0x06
#define PCF8583_TIMER_REG          0x07

#define PCF8583_ALARM_CONTROL_REG  0x08
#define PCF8583_ALARM_100S_REG     0x09
#define PCF8583_ALARM_SECS_REG     0x0A
#define PCF8583_ALARM_MINS_REG     0x0B
#define PCF8583_ALARM_HOURS_REG    0x0C
#define PCF8583_ALARM_DATE_REG     0x0D
#define PCF8583_ALARM_MONTHS_REG   0x0E
#define PCF8583_ALARM_TIMER_REG    0x0F

// Use the first NVRAM address for the year byte.
#define PCF8583_YEAR_REG           0x10


// Commands for the Control/Status register.
#define PCF8583_START_COUNTING     0x00
#define PCF8583_STOP_COUNTING      0x80



char const weekday_names[7][10] =
{
{"Sunday"},
{"Monday"},
{"Tuesday"},
{"Wednesday"},
{"Thursday"},
{"Friday"},
{"Saturday"}
};   
               
// This structure defines the user's date and time data.
// The values are stored as unsigned integers.  The user
// should declare a structure of this type in the application
// program. Then the address of the structure should be
// passed to the PCF8583 read/write functions in this
// driver, whenever you want to talk to the chip.
typedef struct
{
int8 seconds;    // 0 to 59
int8 minutes;    // 0 to 59
int8 hours;      // 0 to 23  (24-hour time)
int8 day;        // 1 to 31
int8 month;      // 1 to 12
int8 year;       // 00 to 99
int8 weekday;    // 0 = Sunday, 1 = Monday, etc.
}date_time_t;


//----------------------------------------------
void PCF8583_write_byte(int8 address, int8 data)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(address);
i2c_write(data);
i2c_stop();
enable_interrupts(GLOBAL);
}   

//----------------------------------------------
int8 PCF8583_read_byte(int8 address)
{
int8 retval;

disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(address);
i2c_start();
i2c_write(PCF8583_READ_ADDRESS);
retval = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
return(retval);
}   


void PCF8583_init(void)
{
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,
                              PCF8583_START_COUNTING);
}   

//----------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.

int8 bin2bcd(int8 value)
{
char retval;

retval = 0;

while(1)
  {
   // Get the tens digit by doing multiple subtraction
   // of 10 from the binary value.
   if(value >= 10)
     {
      value -= 10;
      retval += 0x10;
     }
   else // Get the ones digit by adding the remainder.
     {
      retval += value;
      break;
     }
   }

return(retval);
}

//----------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.

char bcd2bin(char bcd_value)
{
char temp;

temp = bcd_value;

// Shifting the upper digit right by 1 is
// the same as multiplying it by 8.
temp >>= 1;

// Isolate the bits for the upper digit.
temp &= 0x78;

// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));

}

//----------------------------------------------
void PCF8583_set_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 bcd_mon;

// Convert the input date/time into BCD values
// that are formatted for the PCF8583 registers. 
bcd_sec = bin2bcd(dt->seconds);
bcd_min = bin2bcd(dt->minutes);
bcd_hrs = bin2bcd(dt->hours);   
bcd_day = bin2bcd(dt->day) | (dt->year << 6);
bcd_mon = bin2bcd(dt->month) | (dt->weekday << 5);

// Stop the RTC from counting, before we write to
// the date and time registers.
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,
                              PCF8583_STOP_COUNTING);

// Write to the date and time registers.  Disable interrupts
// so they can't disrupt the i2c operations.
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(PCF8583_100S_REG);   // Start at 100's reg.   
i2c_write(0x00);               // Set 100's reg = 0
i2c_write(bcd_sec); 
i2c_write(bcd_min);
i2c_write(bcd_hrs);   
i2c_write(bcd_day);
i2c_write(bcd_mon);
i2c_stop();
enable_interrupts(GLOBAL);

// Write the year byte to the first NVRAM location.
// Leave it in binary format.
PCF8583_write_byte(PCF8583_YEAR_REG, dt->year);

// Now allow the PCF8583 to start counting again.
PCF8583_write_byte(PCF8583_CTRL_STATUS_REG,
                              PCF8583_START_COUNTING);
}

//----------------------------------------------
// Read the Date and Time from the hardware registers
// in the PCF8583.   We don't have to disable counting
// during read operations, because according to the data
// sheet, if any of the lower registers (1 to 7) is read,
// all of them are loaded into "capture" registers.
// All further reading within that cycle is done from
// those registers.

void PCF8583_read_datetime(date_time_t *dt)
{
int8 year_bits;
int8 year;

int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 bcd_mon;

// Disable interrupts so the i2c process is not disrupted.
disable_interrupts(GLOBAL);

// Read the date/time registers inside the PCF8583.
i2c_start();
i2c_write(PCF8583_WRITE_ADDRESS);
i2c_write(PCF8583_SECONDS_REG);   // Start at seconds reg.
i2c_start();
i2c_write(PCF8583_READ_ADDRESS);

bcd_sec = i2c_read();     
bcd_min = i2c_read();     
bcd_hrs = i2c_read(); 
bcd_day = i2c_read();
bcd_mon = i2c_read(0);
i2c_stop();

enable_interrupts(GLOBAL);

// Convert the date/time values from BCD to
// unsigned 8-bit integers.  Unpack the bits
// in the PCF8583 registers where required.
dt->seconds = bcd2bin(bcd_sec);     
dt->minutes = bcd2bin(bcd_min);     
dt->hours   = bcd2bin(bcd_hrs & 0x3F); 
dt->day     = bcd2bin(bcd_day & 0x3F);
dt->month   = bcd2bin(bcd_mon & 0x1F);
dt->weekday = bcd_mon >> 5;
year_bits   = bcd_day >> 6;   

// Read the year byte from NVRAM.
// This is an added feature of this driver.
year = PCF8583_read_byte(PCF8583_YEAR_REG);

// Check if the two "year bits" were incremented by
// the PCF8583.  If so, increment the 8-bit year
// byte (read from NVRAM) by the same amount.
while(year_bits != (year & 3))
      year++;

dt->year = year;

// Now update the year byte in the NVRAM
// inside the PCF8583.
PCF8583_write_byte(PCF8583_YEAR_REG, year);

}


BigDog
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top