PIC24 onboard RTC

General discussion on mikroPascal for dsPIC30/33 and PIC24.
Post Reply
Author
Message
anton
Posts: 807
Joined: 23 Sep 2004 09:16
Location: South-Africa
Contact:

PIC24 onboard RTC

#1 Post by anton » 22 Sep 2008 11:02

Hi,

Most of the PIC24 microcontrollers comes with an on chip RTC. Here is a library to interface the RTC making use of mikroPascal.

I'm busy with the alarm interrupt and will post the code as soon as it is ready.

Please scroll down for new version

Code: Select all

//******************************************************************************
// PIC24FJxx  - Real time clock library
//
// Author: Anton Rieckert       Email: anton@riecktron.co.za
// Date: 22 September 2008
// Webpage: www.riecktron.co.za
//
// Compiler: mikroPascal for dsPIC  v 6.01
//
//******************************************************************************
unit PIC24_RTC;

implementation

//******************************************************************************
// Sets the time on the RTC
//******************************************************************************
Procedure PIC24_RTU_SetTime(hour, min, sec : byte);
var tempVal : word;
Begin
  hour := ((hour DIV 10) shl 4) or (hour MOD 10);
  min := ((min DIV 10) shl 4) or (min MOD 10);
  sec := ((sec DIV 10) shl 4) or (sec MOD 10);

  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  tempVal := RTCVAL AND 0x0700;

  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  RTCVAL := tempVal or hour;
  RTCVAL := (min shl 8) or sec;
End;

//******************************************************************************
// Read the date on the RTC
//******************************************************************************
Procedure PIC24_RTU_SetDate(day, month, year : byte);
Begin
  day := ((day DIV 10) shl 4) or (day MOD 10);
  month := ((month DIV 10) shl 4) or (month MOD 10);
  year := ((year DIV 10) shl 4) or (year MOD 10);

  SetBit(RCFGCAL, 8);
  SetBit(RCFGCAL, 9);

  RTCVAL := year AND 0x00FF;
  RTCVAL := (month shl 8) or day;
End;

//******************************************************************************
// Read the time on the RTC
//******************************************************************************
Procedure PIC24_RTU_GetTime(var hour, min, sec : byte);
Begin
  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  hour := lo(RTCVAL);
  min := hi(RTCVAL);
  sec := lo(RTCVAL);

  hour := (((hour AND 0x30) shr 4) * 10) + (hour AND 0x0F);
  min := (((min AND 0x70) shr 4) * 10) + (min AND 0x0F);
  sec := (((sec AND 0x70) shr 4) * 10) + (sec AND 0x0F);
End;

//******************************************************************************
// Read the date on the RTC
//******************************************************************************
Procedure PIC24_RTU_GetDate(var day, month, year : byte);
Begin
  SetBit(RCFGCAL, 8);
  SetBit(RCFGCAL, 9);

  year := lo(RTCVAL);
  month := hi(RTCVAL);
  
  SetBit(RCFGCAL, 9);
  ClearBit(RCFGCAL, 8);

  day := lo(RTCVAL);

  year := (((year AND 0xF0) shr 4) * 10) + (year AND 0x0F);
  month := (((month AND 0x10) shr 4) * 10) + (month AND 0x0F);
  day := (((day AND 0x30) shr 4) * 10) + (day AND 0x0F);
End;

//******************************************************************************
// Get the weekday number (0 - 6) from RTC
//******************************************************************************
Function PIC24_RTC_GetWeekDay : byte;
Begin
  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  result := (RTCVAL shr 8) AND 0x07;
End;

//******************************************************************************
// Init the RTC on a PIC24 microcontroller
//******************************************************************************
Procedure PIC24_RTC_Init;
var tempASM : word;
Begin
  tempASM := OSCCON;      // Only for linker to include the register

  // Unlock the OSCCON register and then enable SOSC to enable the 32.xxxkHz
  // crystal for the RTC
  asm
     disi #7
     mov #@OSCCON, W1
     mov.b #0x02, W0
     mov.b #0x46, W2
     mov.b #0x57, W3
     mov.b W2, [W1]
     mov.b W3, [W1]
     mov.b W0, [W1]
  end;

  tempASM := NVMKEY;      // Only for linker to include the register
  tempASM := RCFGCAL;     // Only for linker to include the register
  RCFGCAL  := 0x0000;

  // Unlock the RCFGCAL register and enable the RTC
  asm
    PUSH	W12
    DISI	#9
    MOV	#0x55, W12
    MOV	W12, NVMKEY
    MOV	#0xAA, W12
    MOV	W12, NVMKEY
    BSET RCFGCAL, #13
    NOP
    NOP
    BSET RCFGCAL, #15
    POP	W12
  end;
End;

end.
Anton
Last edited by anton on 22 Sep 2008 14:16, edited 1 time in total.
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)

User avatar
marko.medic
mikroElektronika team
Posts: 173
Joined: 05 Jun 2008 08:07

#2 Post by marko.medic » 22 Sep 2008 13:14

Hi,
Thank you Anton.

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

#3 Post by yo2lio » 22 Sep 2008 13:53

Thanks Anton,

One remark : you can use instructions like this for linker to include the registers :

Code: Select all

  OSCCON := OSCCON; 
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

anton
Posts: 807
Joined: 23 Sep 2004 09:16
Location: South-Africa
Contact:

#4 Post by anton » 22 Sep 2008 13:59

Hi yo2lio,
yo2lio wrote:Thanks Anton,

One remark : you can use instructions like this for linker to include the registers :

Code: Select all

  OSCCON := OSCCON; 
Thank you for the note. I will remember it.

Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)

anton
Posts: 807
Joined: 23 Sep 2004 09:16
Location: South-Africa
Contact:

#5 Post by anton » 22 Sep 2008 14:15

Hi,

Here is the new code that supports the Alarm interrupt also

Code: Select all

//******************************************************************************
// PIC24FJxx  - Real time clock library     Version 1.1
//
// Author: Anton Rieckert       Email: anton@riecktron.co.za
// Date: 22 September 2008
// Webpage: www.riecktron.co.za
//
// Compiler: mikroPascal for dsPIC  v 6.01
//
//******************************************************************************
unit PIC24_RTC;

implementation

//******************************************************************************
// Interrupt procedure for the RTC Alarm
//******************************************************************************
Procedure PIC24_RTC_Alarm_Int;  org $90;
Begin
  {PLACE YOUR CODE HERE TO EXECUTE WHEN THE ALARM IS TRIGERED}

  //If TestBit(PortB, 8) = 0 then SetBit(PortB, 8) else ClearBit(PortB, 8);

  IFS3 := IFS3 AND 0xBFFF;  // Clear RTC flag
End;

//******************************************************************************
// Sets the time on the RTC
//******************************************************************************
Procedure PIC24_RTC_SetTime(hour, min, sec : byte);
var tempVal : word;
Begin
  hour := ((hour DIV 10) shl 4) or (hour MOD 10);
  min := ((min DIV 10) shl 4) or (min MOD 10);
  sec := ((sec DIV 10) shl 4) or (sec MOD 10);

  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  tempVal := RTCVAL AND 0x0700;

  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  RTCVAL := tempVal or hour;
  RTCVAL := (min shl 8) or sec;
End;

//******************************************************************************
// Read the date on the RTC
//******************************************************************************
Procedure PIC24_RTC_SetDate(day, month, year : byte);
Begin
  day := ((day DIV 10) shl 4) or (day MOD 10);
  month := ((month DIV 10) shl 4) or (month MOD 10);
  year := ((year DIV 10) shl 4) or (year MOD 10);

  SetBit(RCFGCAL, 8);
  SetBit(RCFGCAL, 9);

  RTCVAL := year AND 0x00FF;
  RTCVAL := (month shl 8) or day;
End;

//******************************************************************************
// Read the time on the RTC
//******************************************************************************
Procedure PIC24_RTC_GetTime(var hour, min, sec : byte);
Begin
  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  hour := lo(RTCVAL);
  min := hi(RTCVAL);
  sec := lo(RTCVAL);

  hour := (((hour AND 0x30) shr 4) * 10) + (hour AND 0x0F);
  min := (((min AND 0x70) shr 4) * 10) + (min AND 0x0F);
  sec := (((sec AND 0x70) shr 4) * 10) + (sec AND 0x0F);
End;

//******************************************************************************
// Read the date on the RTC
//******************************************************************************
Procedure PIC24_RTC_GetDate(var day, month, year : byte);
Begin
  SetBit(RCFGCAL, 8);
  SetBit(RCFGCAL, 9);

  year := lo(RTCVAL);
  month := hi(RTCVAL);
  
  SetBit(RCFGCAL, 9);
  ClearBit(RCFGCAL, 8);

  day := lo(RTCVAL);

  year := (((year AND 0xF0) shr 4) * 10) + (year AND 0x0F);
  month := (((month AND 0x10) shr 4) * 10) + (month AND 0x0F);
  day := (((day AND 0x30) shr 4) * 10) + (day AND 0x0F);
End;

//******************************************************************************
// Get the weekday number (0 - 6) from RTC
//******************************************************************************
Function PIC24_RTC_GetWeekDay : byte;
Begin
  SetBit(RCFGCAL, 8);
  ClearBit(RCFGCAL, 9);

  result := (RTCVAL shr 8) AND 0x07;
End;

//******************************************************************************
// Activates the alarm with given Alarm Mask Configuration
// %00000000 = Every half second
// %00000001 = Every second
// %00000010 = Every 10 seconds
// %00000011 = Every minute
// %00000100 = Every 10 minutes
// %00000101 = Every hour
// %00000110 = Once a day
// %00000111 = Once a week
// %00001000 = Once a month
// %00001001 = Once a year (except when configured for February 29th, once every 4 years)
//******************************************************************************
Procedure PIC24_RTC_ActivateAlarm(alarm_mask, alarm_count : byte; alarm_int : boolean);
Begin
  ALCFGRPT := 0xC000 OR ((alarm_mask AND 0x0F) shl 10);
  
  if alarm_int then     // If true, we activate the interrupt
  Begin
    IFS3 := IFS3 AND 0xBFFF;  // Clear RTC flag
    IEC3 := IEC3 OR 0x4000;   // Enable RTC Int
  End;
End;

//******************************************************************************
// Set the time and date the alarm should interrupt. Please consult the datasheet
// for the parameters that is required by the alarm mask specified
//******************************************************************************
Procedure PIC24_RTC_SetAlarm(workday, day, month, hour, min, sec : byte);
var tempALCF : word;
Begin
  tempALCF := ALCFGRPT;
  ALCFGRPT := 0;                      // Deactivate the alarm to set time

  SetBit(ALCFGRPT, 9);
  ClearBit(ALCFGRPT, 8);
  
  hour := ((hour DIV 10) shl 4) or (hour MOD 10);
  min := ((min DIV 10) shl 4) or (min MOD 10);
  sec := ((sec DIV 10) shl 4) or (sec MOD 10);

  workday := (((workday AND 0xF0) shr 4) * 10) + (workday AND 0x0F);
  month := (((month AND 0x10) shr 4) * 10) + (month AND 0x0F);
  day := (((day AND 0x30) shr 4) * 10) + (day AND 0x0F);

  ALRMVAL := (day shl 8) or month;
  ALRMVAL := (hour shl 8) or workday;
  ALRMVAL := (sec shl 8) or min;
  
  ALCFGRPT := tempALCF;                // Activate the alarm again
End;

//******************************************************************************
// Deactivates the alarm and it's interrupt
//******************************************************************************
Procedure PIC24_RTC_DeactivateAlarm;
Begin
  ALCFGRPT := 0x0000;
  
  IEC3 := IEC3 AND 0xBFFF;  // Disable RTC Int
  IFS3 := IFS3 AND 0xBFFF;  // Clear RTC flag
End;

//******************************************************************************
// Init the RTC on a PIC24 microcontroller
//******************************************************************************
Procedure PIC24_RTC_Init;
var tempASM : word;
Begin
  tempASM := OSCCON;      // Only for linker to include the register

  // Unlock the OSCCON register and then enable SOSC to enable the 32.xxxkHz
  // crystal for the RTC
  asm
     disi #7
     mov #@OSCCON, W1
     mov.b #0x02, W0
     mov.b #0x46, W2
     mov.b #0x57, W3
     mov.b W2, [W1]
     mov.b W3, [W1]
     mov.b W0, [W1]
  end;

  tempASM := NVMKEY;      // Only for linker to include the register
  tempASM := RCFGCAL;     // Only for linker to include the register
  RCFGCAL  := 0x0000;

  // Unlock the RCFGCAL register and enable the RTC
  asm
    PUSH	W12
    DISI	#9
    MOV	#0x55, W12
    MOV	W12, NVMKEY
    MOV	#0xAA, W12
    MOV	W12, NVMKEY
    BSET RCFGCAL, #13
    NOP
    NOP
    BSET RCFGCAL, #15
    POP	W12
  end;
End;

end.
Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)

5willow5
Posts: 27
Joined: 19 Sep 2008 08:14

Re: PIC24 onboard RTC

#6 Post by 5willow5 » 10 Mar 2011 09:16

First of all, thanks for you code. It has been very usefull for me.

But I think it has an error in the method PIC24_RTC_SetAlarm.

I think you have to change the original code

Code: Select all

  ALRMVAL := (day shl 8) or month;
  ALRMVAL := (hour shl 8) or workday;
  ALRMVAL := (sec shl 8) or min;
for this one:

Code: Select all


  ALRMVAL := (month shl 8) or day;
  ALRMVAL := (workday shl 8) or hour;
  ALRMVAL := (min shl 8) or sec;
You can read this datasheet:
http://ww1.microchip.com/downloads/en/D ... 39696b.pdf

The table 29-4 shows the ALRMVAL Register Mapping.

Thanks, Willow.

Post Reply

Return to “mikroPascal for dsPIC30/33 and PIC24 General”