PDA

View Full Version : Ds3231 rtc usage



gunayburak
- 8th September 2015, 21:31
Hello everyone ;

I'm trying to get my DS3231 working but no luck so far ... I've read already posted threads about this IC but they don't help ..

Here is the code I'm using on PIC16f628A




'************************************************* ***************
'* Name : RTC.BAS *
'* Author : Burak Günay *
'* Notice : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 8/9/2015 *
'* Version : 1.0 *
'* Notes : REAL TIME CLOCK WITH DS3231 *
'* : *
'************************************************* ***************
#config
__config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BODEN_ON & _LVP_OFF & _CP_OFF
#endconfig



'-------------------------------------------------------------------------
Define OSC 4


DEFINE LCD_EREG PORTA 'LCD Enable port
DEFINE LCD_EBIT 6 'LCD Enable port pin
DEFINE LCD_RSREG PORTA 'LCD RS port
DEFINE LCD_RSBIT 7 'LCD RS port pin
define LCD RWREG PORTA 'LCD R/W port
define LCD_RWBIT 4 'LCD R/W port pin
DEFINE LCD_DREG PORTB 'LCD data port
DEFINE LCD_DBIT 4 'LCD data port starts from pin x
DEFINE LCD_BITS 4 'LCD bus size 4 or 8
DEFINE LCD_LINES 2 'LCD lines
'-------------------------------------------------------------------------




'-------------------------------------------------------------------------
PORTA=%00000000 : PORTB=%00000000
CMCON=%00000111 'Comparators off
OPTION_REG.7=0 'INTERNAL WEAK PULL-UPS OF PORTB ARE ENABLED.
TRISA=%00000000 : TRISB=%00000000
'-------------------------------------------------------------------------


'-------------------------------------------------------------------------
SDA VAR PORTB.0
SCL VAR PORTB.1
'-------------------------------------------------------------------------
i var byte
q var byte[7]
tens var byte
units var byte
tmp var byte
'-------------------------------------------------------------------------


lcdout $FE,1


pause 1000


Q[0]=0
Q[1]=50
Q[2]=20
Q[3]=1
Q[4]=8
Q[5]=9
Q[6]=15


GOSUB TOBCD
i2cwrite sda,scl,%11010000,$00,Q[0],Q[1],Q[2],Q[3],Q[4],Q[5],Q[6]


pause 500


MAIN:'>>>>>>>>>>>>>>>>>>>>>>>>>>>


i2cREAD SDA,SCL,%11010001,$00,Q[0],Q[1],Q[2],Q[3],Q[4],Q[5],Q[6]
GOSUB TODEC


LCDOUT $FE,$80, DEC2 Q[2],":",DEC2 Q[1],":",DEC2 Q[0]
LCDOUT $FE,$C0, DEC2 Q[4],":",DEC2 Q[5],":",DEC2 Q[6]


GOTO MAIN'<<<<<<<<<<<<<<<<<<<<<<<










































'******************************DECIMAL TO BCD***********************************
TOBCD: 'Conversion to BCD


for i=0 to 6
TMP = Q[i] DIG 1 'Get TENS to temp variable
TENS = TMP << 4
UNITS = Q[i] DIG 0 'Get UNITS to units variable
Q[i] = TENS + UNITS
next i


RETURN
'**************************BCD TO DECIMAL SYSTEM********************************
TODEC:


for i=0 to 6
TMP = Q[i] & %01110000
TENS = TMP >> 4
UNITS = Q[i] & %00001111
Q[i] = TENS * 10 + UNITS
next i


RETURN
'************************************************* ******************************



Where do I make the mistake .. I've read its datasheet and wrote a code accordingly step by step but there must be something I'm missing .. By the way I supply the pic and the DS3231 with 5V

Thanks in advance

richard
- 8th September 2015, 23:27
I've read already posted threads about this IC but they don't help ..

probably not a good idea to keep starting new threads then . whats the history ? what has been tried and failed ?

so we start again at the beginning

what is the actual problem ?
do you have a accurate schematic of your setup ?
do you have suitable pullup resistors ?
can you flash a led with your pic ? do the scl,sda pins do anything ?
do you have a oscilloscope or a logic analyser to check output ?
have you tried to read the command and status regs of the ds3231 (0x0e,0x0f) ? if so what do you get ?
is the ds3231 osc running ?

MichelJasmin
- 9th September 2015, 04:02
I think each I2C call address must be passed trought a variable:



I2C_Adr = $0F
I2C_NACK = 0
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTC_Reg], I2CNACK


I've made an include file to deal with my DS3231 if you are interested:



'************************************************* ***************
'* Name : ..\_INCLUDE\DS3231.PBP *
'* Author : Michel Jasmin *
'* Notice : NOT Copyright (c) 2015 Michel Jasmin *
'* : All Rights NOT Reserved *
'* Date : 2015-04-11 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
GOTO OverDS3231

'ToDo: Alias pins
'RTC_SDA Var PORTA.4
'RTC_SCL Var PORTA.5


'------------ Const -------------------------
AL1_OpS CON %00001111 'once per second
AL1_S CON %00001110 'when seconds match
AL1_MS CON %00001100 'when minutes and seconds match
AL1_HMS CON %00001000 'when hours, minutes and seconds match
AL1_DtHMS CON %00000000 'when DATE, hours, minutes and seconds match
AL1_DayHMS CON %00010000 'when DAY, hours, minutes and seconds match

AL2_OpM CON %00001110 'once per minute
AL2_M CON %00001100 'when minutes match
AL2_HM CON %00001000 'when hours and minutes match
AL2_DtHM CON %00000000 'when DATE, hours and minutes match
AL2_DayHM CON %00010000 'when DAY, hours and minutes match


'------------ Variables -------------------------

RTCYear Var Byte
RTCMonth Var Byte
RTCDate Var Byte
RTCDay Var Byte
RTCHour Var Byte
RTCMin Var Byte
RTCSec Var Byte
RTCCtrl Var Byte
HexValue var byte
DecValue var byte
I2C_Adr VAR BYTE
I2C_Flags VAR BYTE
I2C_NACK VAR I2C_Flags.0

'General Register variable
RTC_Reg var byte

'Aliases for Control Register @ $0E
'EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE
RTC_EOsc var RTC_Reg.7 'Enable Oscillator
RTC_BBSQW var RTC_Reg.6 'Battery-Backed Square-Wave Enable
RTC_CONV var RTC_Reg.5 'Convert Temperature
RTC_RS2 var RTC_Reg.4 'Rate Select
RTC_RS1 var RTC_Reg.3 'Rate Select
RTC_INTCN var RTC_Reg.2 'Interrupt Control
RTC_A2IE var RTC_Reg.1 'Alarm 2 Interrupt Enable
RTC_A1IE var RTC_Reg.0 'Alarm 1 Interrupt Enable

'Aliases for Status Register @ $0F
'OSF x x x EN32kHz BSY A2F A1F
RTC_OSF var RTC_Reg.7 'Oscillator Stop Flag
RTC_EN32kHz var RTC_Reg.3 'Enable 32kHz Output
RTC_BSY var RTC_Reg.2 'Busy
RTC_A2F var RTC_Reg.1 'Alarm 2 Flag
RTC_A1F var RTC_Reg.0 'Alarm 1 Flag


' Subroutine to write time to RTC
SetTime:
I2C_NACK = 0
I2C_Adr = $00
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCSec, RTCMin, RTCHour, RTCDay, RTCDate, RTCMonth, RTCYear], I2CNACK

RETURN

' Subroutine to read time from RTC
GetTime:
I2C_NACK = 0
I2C_Adr = $00
I2CRead RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCSec, RTCMin, RTCHour, RTCDay, RTCDate, RTCMonth, RTCYear], I2CNACK

RETURN


SetAlarm1:
'Usage:
'
' set values to RTCSec, RTCMin, RTCHour, [RTCDay | RTCDate]
'
' RTC_Reg = AL1_HMS 'Set alarm type
' gosub SetAlarm1
HSEROUT2 ["Alarm1 at: ", hex2 RTCDate, " ", hex2 RTCHour, ":", hex2 RTCMin, ":", hex2 RTCSec, 13, 10]
'HSEROUT2 ["RTC_Reg = ", bin8 RTC_Reg, 13, 10]
I2C_Adr = $07
I2C_NACK = 0

RTCSec.7 = RTC_Reg.0 'A1M1
RTCMin.7 = RTC_Reg.1 'A1M2
RTCHour.7 = RTC_Reg.2 'A1M3

'Test A1M4
if RTC_Reg.3 = 1 then
'alarm by time only

'Get the alarm1 date
' I2C_Adr = $0A
' I2CRead SDA, RTC_SCL, $D0, I2C_Adr, [RTCDate], I2CNACK

RTCDate.7 = RTC_Reg.3 'A1M4
RTCDate.6 = 0 'DY/DT!

I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCSec, RTCMin, RTCHour, RTCDate], I2CNACK
HSEROUT2 ["alarm1 by time only", 13, 10]
'HSEROUT2 [" at: ", bin8 RTCDate, " ", bin8 RTCHour, ":", bin8 RTCMin, ":", bin8 RTCSec, 13, 10]

else
'alarm by time and (DAY or DATE)


if RTC_Reg.4 = 1 then
'alarm by DAY




RTCDay.7 = 0 'A1M4
RTCDay.6 = 1 'DY/DT!
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCSec, RTCMin, RTCHour, RTCDay], I2CNACK
HSEROUT2 ["alarm1 by DAY", 13, 10]
'HSEROUT2 [" at: ", bin8 RTCDay, " ", bin8 RTCHour, ":", bin8 RTCMin, ":", bin8 RTCSec, 13, 10]
else
'alarm by DATE
RTCDate.7 = 0 'A1M4
RTCDate.6 = 0 'DY/DT!
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCSec, RTCMin, RTCHour, RTCDate], I2CNACK
HSEROUT2 ["alarm1 by DATE", 13, 10]
'HSEROUT2 [" at: ", bin8 RTCDate, " ", bin8 RTCHour, ":", bin8 RTCMin, ":", bin8 RTCSec, 13, 10]

endif

endif



RETURN


SetAlarm2:
'Usage:
'
' set values to RTCMin, RTCHour, [RTCDay | RTCDate]
'
' RTC_Reg = AL1_HMS 'Set alarm type
' gosub SetAlarm1
HSEROUT2 ["Alarm2 at: ", hex2 RTCDate, " ", hex2 RTCHour, ":", hex2 RTCMin, 13, 10]
I2C_Adr = $0B
I2C_NACK = 0

RTCMin.7 = RTC_Reg.1 'A1M2
RTCHour.7 = RTC_Reg.2 'A1M3

'Test A1M4
if RTC_Reg.3 = 1 then
'alarm by time only

RTCDate.7 = RTC_Reg.3 'A1M4
RTCDate.6 = 0 'DY/DT!

I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCMin, RTCHour, RTCDate], I2CNACK
HSEROUT2 ["alarm2 by time only", 13, 10]
' HSEROUT2 [" at: ", bin8 RTCDate, " ", bin8 RTCHour, ":", bin8 RTCMin, 13, 10]

else
'alarm by time and (DAY or DATE)

if RTC_Reg.4 = 1 then
'alarm by DAY

RTCDay.7 = 0 'A1M4
RTCDay.6 = 1 'DY/DT!
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCMin, RTCHour, RTCDay], I2CNACK
HSEROUT2 ["alarm2 by DAY", 13, 10]
' HSEROUT2 [" at: ", bin8 RTCDay, " ", bin8 RTCHour, ":", bin8 RTCMin, 13, 10]
else
'alarm by DATE
RTCDate.7 = 0 'A1M4
RTCDate.6 = 0 'DY/DT!
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCMin, RTCHour, RTCDate], I2CNACK
HSEROUT2 ["alarm2 by DATE", 13, 10]
' HSEROUT2 [" at: ", bin8 RTCDate, " ", bin8 RTCHour, ":", bin8 RTCMin, 13, 10]

endif

endif



RETURN


'GetAlarm1:
' I2C_Adr = $07
' I2CRead RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTCSec, RTCMin, RTCHour, RTCDay, RTCDate], I2CNACK


' RETURN


ReadControlRegister:
I2C_Adr = $0E
I2C_NACK = 0
I2CRead RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTC_Reg], I2CNACK

return

WriteControlRegister:
I2C_Adr = $0E
I2C_NACK = 0
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTC_Reg], I2CNACK

return

ReadStatusRegister:
I2C_Adr = $0F
I2C_NACK = 0
I2CRead RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTC_Reg], I2CNACK

return

WriteStatusRegister:
I2C_Adr = $0F
I2C_NACK = 0
I2CWrite RTC_SDA, RTC_SCL, $D0, I2C_Adr, [RTC_Reg], I2CNACK

return

I2CNACK:
I2C_NACK = 1
RETURN


Hex2BCD:
DecValue = 10 * (HexValue >> 4)
DecValue = DecValue + (HexValue & $0F)

return

BCD2Hex:
HexValue = (DecValue DIG 0) + ((DecValue DIG 1) << 4)

return

OverDS3231:




Usage:



'Init
gosub ReadStatusRegister
RTC_OSF = 0
RTC_EN32kHz = 1
RTC_A2F = 0
RTC_A1F = 0
gosub WriteStatusRegister

RTC_Reg = %00000100
'RTC_EOsc var RTC_Reg.7 'Enable Oscillator
'RTC_BBSQW var RTC_Reg.6 'Battery-Backed Square-Wave Enable
'RTC_CONV var RTC_Reg.5 'Convert Temperature
'RTC_RS2 var RTC_Reg.4 'Rate Select
'RTC_RS1 var RTC_Reg.3 'Rate Select
'RTC_INTCN var RTC_Reg.2 'Interrupt Control
'RTC_A2IE var RTC_Reg.1 'Alarm 2 Interrupt Enable
'RTC_A1IE var RTC_Reg.0 'Alarm 1 Interrupt Enable
gosub WriteControlRegister

' Set initial time to 2014-01-01 8:02:01, day 4
RTCYear = $14
RTCDay = $04
RTCMonth = $01
RTCDate = $01
RTCHour = $08
RTCMin = 2
RTCSec = 1
Gosub SetTime ' Set the time



'Set Alarm 1

RTCHour = 2
RTCMin = 0
RTCSec = 0

RTC_Reg = AL1_MS
gosub SetAlarm1

gunayburak
- 9th September 2015, 10:30
Let me get this straight ...

A read op from DS3231 must be in this form I think ...

i2cREAD SDA,SCL,%11010001,$00,var

Am I mistaken ?

richard
- 9th September 2015, 10:33
from the book



I2CREAD DataPin, ClockPin, Control,{Address,}[Var{,Var...}]{,Label}

gunayburak
- 9th September 2015, 15:38
from the book

Indeed from the book yet not PBP's but DS3231's ... Obviously you haven't seen the number written in different format in my message .. Observe the bold formatted number .. The slave address + direction bit ...

richard
- 9th September 2015, 22:02
again
from the book (i2cread)





The upper 7 bits of the


Control byte contain the control code along with chip select
or additional address information, depending on the particular device. The low
order bit is an internal flag indicating whether it is a read or write command and
should be kept clear.

Scampy
- 10th September 2015, 00:13
Here is the code I'm using on PIC16f628A


Where do I make the mistake .. I've read its datasheet and wrote a code accordingly step by step but there must be something I'm missing .. By the way I supply the pic and the DS3231 with 5V

Thanks in advance

I'm no expert, but I don't think the PIC you are using has a Master Synchronous Serial Port (MSSP) module so doesn't actually support i2C communications. There are certainly no pins marked SCL and SDA in the datasheet

Juts checked here http://www.microchip.com/ParamChartSearch/chart.aspx?branchID=1005 and the PIC you are using has no i2c support

Dave
- 10th September 2015, 11:55
Scampy, I2CREAD and I2CWRITE are PBP "software" routines to emulate I2C operations. You don't need to have MSSP capability in hardware to use them. Infact you can use almost any pin to do the interface.

gunayburak
- 10th September 2015, 14:41
again
from the book (i2cread)
So there is no use of the lsb of the control bit , then it's determined by the command's itself ... I mean if it is I2CREAD op then it automatically determines this bit itself ... Am I correct ? I'll give it a try once more by using



i2cREAD SDA,SCL,%11010000,$00,var


At least I may read the control or the status register ...

Thanks .. :)

Scampy
- 10th September 2015, 17:54
Scampy, I2CREAD and I2CWRITE are PBP "software" routines to emulate I2C operations. You don't need to have MSSP capability in hardware to use them. Infact you can use almost any pin to do the interface.

Dave,
Interesting to know... but wouldn't it be better to use a chip that had an I2C module, rather than rely on software emulation ? Or doen't PBP make use of the physical modules incorporated in various PICs ?

gunayburak
- 12th September 2015, 00:05
So there is no use of the lsb of the control bit , then it's determined by the command's itself ... I mean if it is I2CREAD op then it automatically determines this bit itself ... Am I correct ? I'll give it a try once more by using



i2cREAD SDA,SCL,%11010000,$00,var


At least I may read the control or the status register ...

Thanks .. :)

No luck with that either ... I have even pulled the scl and sda up with 4.7 k resistors ... neither I can write nor read the control and status registers ... 😕

MichelJasmin
- 12th September 2015, 03:46
I don't want to be rude but RTFM, p.156:



The Address size sent (byte or word) is determined by the size of the variable that is used. If a byte-sized variable is used for the Address, an 8-bit address is sent. If a word-sized variable is used, a 16-bit address is sent. Be sure to use the proper sized variable for the device you wish to communicate with. Constants should not be used for the Address as the size can vary dependent on the size of the constant. Also, expressions should not be used as they can cause an improper Address size to be sent.


Pull-up resistors are mandatory for I2C. Keep trying, the DS3231 has nice features like alarms and is more accurate than the DS1307.

richard
- 12th September 2015, 10:49
you keep showing this

i2cREAD SDA,SCL,%11010000,$00,var
it should be (apart from what michelj has pointed out)
i2cREAD SDA,SCL,%11010000,0,[var]

yet to be addressed :-
none of the code you have posted seems to have the correct syntax for i2c commands .
do you have a accurate schematic of your setup ?
can you flash a led with your pic ? do the scl,sda pins do anything ?
do you have a oscilloscope or a logic analyser to check output ?
what do you get when you read the command and status regs of the ds3231 (0x0e,0x0f) ?

gunayburak
- 13th September 2015, 09:33
I'm a total idiot ... I'll correct the code ...
Thanks guys ...

gunayburak
- 13th September 2015, 11:53
Now the clock ticks like a clock :) But another problem has revealed .... The RTC I'm using has arrived in a form of a module bought from eBay it has everything on it including an EEPROM ... But the thing is when I remove the primary power source it stops ticking , but I assume the 3V battery on it (it's full by the way 3.2V measured) would take the rebound as it should but it doesn't , I guess there is something I must set in the register which I can not see ... Any ideas ?

gunayburak
- 13th September 2015, 12:29
EOSC bit it was .. It must be cleared for once .. Then the Vbat takes the job when the primary power source is removed ...
Thanks to everyone for correcting the syntax mistake in my code .. The paranthesis .... God .. How can I be so blind ...

n0yox
- 4th January 2016, 23:51
'DS3231
'Can anyone tell me why this code does not work?
settime:
sda var portb.6
scl var portb.5
cntrl CON $10
rtc CON %11010000
SecReg CON $00
hours = $16
minutes = $40
seconds = $00
month = $01
date = $04
year = $16
day = $02
I2cwrite sda,scl, rtc, $D0, $00,[seconds,minutes,hours,day,date,month,year,cntrl]
return

'This line works fine to read from the DS3231
I2CRead sda,scl, rtc, secreg,[seconds,minutes,hours,day,date,month,year]

MichelJasmin
- 5th January 2016, 00:13
See page 159:



The Address size sent (byte or word) is determined by the size of the variable that is used. If a byte-sized variable is used for the Address, an 8-bit address is sent. If a word-sized variable is used, a 16-bit address is sent. Be sure to use the proper sized variable for the device you wish to communicate with. Constants should not be used for the Address as the size can vary dependent on the size of the constant. Also, expressions should not be used as they can cause an improper Address size to be sent.







I2C_Adr VAR BYTE

I2C_Adr = $00
I2cwrite sda,scl, rtc, $D0, I2C_Adr,[seconds,minutes,hours,day,date,month,year,cntrl]



HTH

n0yox
- 5th January 2016, 00:42
After reading your post I took a look at all of the things you mentioned. While doing this I noticed that I had put the RTC variable in the I2cwrite statement two times .

This did not work > I2cwrite sda,scl,rtc,$D0,I2C_Adr,[seconds,minutes,hours,day,date,month,year,cntrl]

This works > I2cwrite sda,scl,$D0,I2C_Adr,[seconds,minutes,hours,day,date,month,year,cntrl]

I would have looked at that code for a week if you had not helped me!

Thank You !
rc

fratello
- 5th January 2016, 07:53
Hi ! Can you post your full code for DS3231 ? I intend to build something based on Nokia 3310 display ... (upgrade of this : http://www.picbasic.co.uk/forum/showthread.php?t=327&page=8&p=129083#post129083 )

MichelJasmin
- 6th January 2016, 02:59
Hi ! Can you post your full code for DS3231 ? I intend to build something based on Nokia 3310 display ... (upgrade of this : http://www.picbasic.co.uk/forum/showthread.php?t=327&page=8&p=129083#post129083 )

See attached file. I use it as an include.

Displaying time is like



'----[ ALIAS }-------------------------
RTC_SDA Var PORTB.3
RTC_SCL Var PORTB.2

'----[ INCLUDES }-------------------------
INCLUDE "..\_Include\DS3231.pbp"

...

gosub GetTime
HSEROUT2 [hex2 RTCHour, ":", hex2 RTCMin, ":", hex2 RTCSec, 13, 10]

fratello
- 6th January 2016, 06:40
Thank You so much !

JBKerner
- 11th August 2018, 17:23
See attached file. I use it as an include.

Displaying time is like



'----[ ALIAS }-------------------------
RTC_SDA Var PORTB.3
RTC_SCL Var PORTB.2

'----[ INCLUDES }-------------------------
INCLUDE "..\_Include\DS3231.pbp"

...

gosub GetTime
HSEROUT2 [hex2 RTCHour, ":", hex2 RTCMin, ":", hex2 RTCSec, 13, 10]



Michel, I know it's been a long time since this was posted, but doesn't the statement "GOTO OverDS3231" skip over the entire program? Or is this just a case of me not understanding how include files work? -Jeff

MichelJasmin
- 12th August 2018, 00:39
Michel, I know it's been a long time since this was posted, but doesn't the statement "GOTO OverDS3231" skip over the entire program? Or is this just a case of me not understanding how include files work? -Jeff

It skips the include file which contains only functions to be called.