PCF8563 RTC problem

Hi,
I recently got code working with the DS1307 RTC, but I now need to get a PCF8563 working. The code should be similar, only some addresses changed, but I keep getting errors when I try to read the chip. I’m using SDK 4.3 and VS 2013.
The error message is
A first chance exception of type ‘System.ArgumentOutOfRangeException’ occurred in mscorlib.dll
An unhandled exception of type ‘System.ArgumentOutOfRangeException’ occurred in mscorlib.dll
This is when I try and read the date time.
Any help would be appreciated.


using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;

using GHI.Pins;

namespace P3_2
{
    public class Program
    {
        public static void Main()
        {
            InputPort LDR0 = new InputPort(FEZPandaIII.Gpio.Ldr0, false, Port.ResistorMode.PullUp);
            OutputPort LED1 = new OutputPort(FEZPandaIII.Gpio.Led1, false);//Blue
            OutputPort LED2 = new OutputPort(FEZPandaIII.Gpio.Led2, false);//Blue
            OutputPort LED3 = new OutputPort(FEZPandaIII.Gpio.Led3, false);//Blue
            OutputPort LED4 = new OutputPort(FEZPandaIII.Gpio.Led4, false);//Blue
           
            P3_2.RTC_8563 RTC_time = new P3_2.RTC_8563();
            RTC_time.SetControlRegister();
           
            //Set the date and time
            RTC_time.SetDateTime(new DateTime(2015, 1, 4, 7, 20, 34, 30));//year,month,day of week(0-6),day,hour,minute,second
            
            while(LDR0.Read())
            {
            Debug.Print(RTC_time.GetDateTime().ToString("G"));
            LED1.Write(!LED1.Read());
            Thread.Sleep(5000);
            }            
        }        
    }
}

and the class


using System;
using Microsoft.SPOT.Hardware;

namespace P3_2
{
    class RTC_8563 : IDisposable
    {
        private I2CDevice I2C;
        I2CDevice.I2CTransaction[] xaction;
        ushort PCF8563_Address = 0x51;

        public void Dispose()
        {
            I2C.Dispose();
            xaction = null;
        }

        public RTC_8563()
        {
            //Create I2C object
            I2CDevice.Configuration conf = new I2CDevice.Configuration(PCF8563_Address, 100);
            I2C = new I2CDevice(conf);
        }

        public void SetControlRegister()
        {
            xaction = new I2CDevice.I2CTransaction[2];
            xaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00 });//control reg zero
            xaction[1] = I2CDevice.CreateWriteTransaction(new byte[] { 0x00 });//write data 0
            if (I2C.Execute(xaction, 1000) == 0)
            {
                new Exception("Failed to send I2C data");
            }

        }

        public DateTime GetDateTime()
        {
            xaction = new I2CDevice.I2CTransaction[2];
            xaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x02 });
            byte[] ReturnedDateTime = new byte[7];
            xaction[1] = I2CDevice.CreateReadTransaction(ReturnedDateTime);
            if (I2C.Execute(xaction, 1000) == 0)
            {
                new Exception("Failed to send I2C data");
            }

            int secs = bcdToDec(ReturnedDateTime[0]) & 0x7f;
            int mins = bcdToDec(ReturnedDateTime[1]) & 0x7f;
            int hours = bcdToDec(ReturnedDateTime[2]) & 0x3f;
            int days = bcdToDec(ReturnedDateTime[3]) & 0x3f;
            int weekdays = bcdToDec(ReturnedDateTime[4]) & 0x07;
            int month = bcdToDec(ReturnedDateTime[5]) & 0x1f;
            int year = bcdToDec(ReturnedDateTime[6]) + 2000;

            DateTime dt = new DateTime(year, month, days, hours, mins, secs);
            return dt;

        }       
        
        public void SetDateTime(DateTime datetime)
        {
            xaction = new I2CDevice.I2CWriteTransaction[1];
            byte[] sb = new byte[8] { 0x02,
                                  decToBcd(datetime.Second),
                                  decToBcd(datetime.Minute),
                                  decToBcd(datetime.Hour),
                                  decToBcd((int)datetime.DayOfWeek),
                                  decToBcd(datetime.Day),
                                  decToBcd(datetime.Month),
                                  decToBcd(datetime.Year - 2000)
                                };

            xaction[0] = I2CDevice.CreateWriteTransaction(sb);
            if (I2C.Execute(xaction, 1000) == 0)
            {
                new Exception("Failed to send I2C data");
            }
        }

        private byte decToBcd(int val)
        {
            return (byte)((val / 10 * 16) + (val % 10));
        }

        private byte bcdToDec(byte val)
        {
            return (byte)((val / 16 * 10) + (val % 16));
        }
    }
}

Do you know where it throws the exception? I would have guessed it’s when you call GetDateTime, but where in there does the index exception get thrown? I can’t obviously see an out of range condition though :frowning:

Use the debugger and single step your GetDateTime function (assuming it fails in this) and see where the error is.

Thanks to you both. Yes its the GetDateTime request which crashes. The numbers in the variables are correct for year and minute,but the rest are wrong. I’m travelling at the moment but will try what you suggest regarding single stepping on Monday. Thanks again
Alastair

Thanks again both,
Got it sorted. There were a number of problems.
I didn’t realise that if the data being returned by the DateTime class was invalid it would throw an exception…something learned.
I wasn’t handling the extra register in this RTC for day of the week (0-6) correctly, and finally I was anding (&) the returned BCDtoDec value and not the raw BCD value. Brackets in wrong place!! :wall:

Many lessons learned.

Alastair

3 Likes