PDA

View Full Version : DS1337 - 12h to 24h mode



lerameur
- 13th January 2015, 19:17
Hello,

I am trying to convert from 12h mode to 25H mode and vice versa with a Ds1337 chip. Not getting great results for now.

What I understand Bit 5 and 6 or the hours plays a role in converting. Her is a clip from the datasheet:
The DS1337 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12- or 24-
hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit with
logic high being PM. In the 24-hour mode, bit 5 is the second 10-hour bit (20–23 hours).
I am configuring it so that when two buttons are pressed down for over 1.5 seconds, the conversion between 12h mode to 24h mode is done. From what I understan, I also need to convert the time myself example: from 20H to 8H. The code for me should work but keeps giving me random values, any ideas ?
thanks


If (PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
'IF hourly mode = AM
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
Pause 10
if RTCHour.6 = 1 then 'turn into 24h mode therefore 1 to 11 converts to 13 to 23
point =2
gosub bcd_to_bin
RTCHour = TempVal + 12
RTCHour.6 = 0
endif
if RTCHour.6 = 0 then 'turn into 12h mode therefore 13 to 23 converts to 1 to 11
point =3
gosub bcd_to_bin
RTCHour = TempVal - 12
RTCHour.6 = 1
endif
I2cwrite SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
Pause 100
endif

Tabsoft
- 13th January 2015, 21:00
I could see a couple of issues here, but without additional information it's a guess.

1. You do not post your RTC Initialization routine so how are you setting up the RTC 12 Hour or 24 Hour mode initially?
1a. After initialization does your project display the correct values before you enter your 12/24 Hour configuration routine?

Note: If you change the 12/24 hour mode at any time with a write to the RTC, you will need to perform a second write to the RTCHour register (noted in the DS Pg 9 last paragraph under "Clock and Calendar").

2. I see that you are looking at the 12/24 hour bit, but I do not see that you are checking/setting the AM/PM bit (RTCHour.5). When the RTC is set for 12 hour mode you might want to set this or the calendar values of the RTC will be off.

3. You did not include your bcd_bin routine so there may be issues there, can't tell without seeing it.
3a. You seem to be converting from BCD to BIN (gosub bcd_bin) when you read and are wanting to change to the other mode (12/24 Hr) but...
I do not see where you are converting from BIN back to BCD before you write back to the RTC.
Unless you are using the "point" variable in a IF/Then or Select Case structure in the bcd_bin routine to select BcdToBin or BinToBcd, again hard to tell without seeing the code. I also assume the TempVar variable holds the converted value from the bcd_bin routine??

Also, if you are using and LCD or other output device, try and display out the variables at different stages of your configuration routine to make sure that the values are what you expect.

Perhaps you might want to post more of your code to see if we can help further.

Just my thoughts.

Regards,

richard
- 13th January 2015, 21:17
I think your becoming a good case for the snippets are us award
but if you intention is to just to set/reset 24 h mode on the chip


If(PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
'IF hourly mode = AM
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
RTCHour.6 = ! RTCHour.6
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
endif
endif

lerameur
- 13th January 2015, 21:25
Here is the full code.
The display gosub is not being used, will be used when display in a 7 segment display.
Now I am using a LCDout command to view my numbers


'////////////////////////////////////////////////////
'////////////////// PROGRAM /////////////////////////
'////////////////////////////////////////////////////
I2CWRITE SDApin,SCLpin,$D0,$00,[$56,$59,$20,$00,$00,$00,$00,$00] ' Write to DS1337 to initialize RTC
pause 10
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour] ' bit 5 of hour is 1 for PM , 0 for AM
pause 10
'RTCHour.5 = 1 'bit 5 is the AM/PM bit with logic high being PM AND NOT USED
' RTCHour.6 = 0 '24h selected ' for 12 or 24 h mode , when high 12h mode is selected
'in 24 hour mode (=0) bit 5 is used for hours 20 to 23

I2CwRITE SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
pause 10

Mainloop:
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
gosub bcd_to_bin

If (PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
'IF hourly mode = AM
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
Pause 10
if RTCHour.6 = 1 then 'turn into 24h mode therefore 1 to 11 converts to 13 to 23
point =2

RTCHour.6 = 0
endif
if RTCHour.6 = 0 then 'turn into 12h mode therefore 13 to 23 converts to 1 to 11
point =3
RTCHour.6 = 1
endif
I2cwrite SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
Pause 100
endif

temp1_min = RTCMin_temp1
m = temp1_min
'PortA.0 =1
'gosub display
' PortA.0 =0

temp2_min = RTCMin_temp2
n = temp2_min
' PortA.1 =1
' gosub display
' PortA.1 =0

temp1_sec = RTCSec_temp1
o = temp1_sec
' PortA.2 =1
' gosub display
' PortA.2 =0

temp2_sec = RTCSec_temp2
p = temp2_sec
' PortA.4 =1
'gosub display
'PortA.4 =0

lcdout $FE,1, "Time: ", HEX2 RTCHour, ":", hex2 RTCmin ,":", HEX2 RTCsec 'in decimals... wow
lcdout $FE,$C0, dec TempVal , " :" ,dec RTCHour_temp1,":", dec RTCHour_temp2,":", dec point
Pause 150

goto Mainloop
end

bcd_to_bin:

if (RTCHour.6 = 1 ) then 'bit 5 is used if RTCHour.6 = 0 ; 24h selected
RTCHour.6 = 0
RTCHour.5 = 0
RTCHour_temp2 = $0F & RTCHour
RTCHour_temp1= RTCHour >> 4
endif
if (RTCHour.6 = 0 ) then
RTCHour_temp2 = %00001111 & RTCHour
RTCHour_temp1= RTCHour >> 4 ' Shift down four to read 2 BCD value
TempVal = RTCHour_temp1 * 10 + RTCHour_temp2 ' this calculate the hours in decima

if ( TempVal > 19 ) then
return
else
RTCHour.5 = 0
RTCHour_temp2 = $0F & RTCHour
RTCHour_temp1= RTCHour >> 4
endif
endif

RTCMin_temp2 = $0F & RTCMin ' Clear off the top four bits
RTCMin_temp1= RTCMin >> 4 ' Shift down four to read 2 BCD value

RTCSec_temp2 = $0F & RTCSec ' Clear off the top four bits
RTCSec_temp1= RTCSec >> 4 ' Shift down four to read 2 BCD value

return

richard
- 13th January 2015, 22:29
this may be better



If(PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
'IF hourly mode = AM
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
temp1 = ((RTCHour>> 4) * 10) + (RTCHour& $0f) , to binary

if RTCHour.6=1 then ' 12h mode
if RTCHour.5=1then temp1=temp1+12 ' pm

else
if temp1 > 12 then
temp1=temp1-12
endif

rtcHOUR = ((temp1 / 10) << 4) + (tEmp1 // 10) ' to bcd


RTCHour.6 = ! RTCHour.6 ' set/reset 24h mode

I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
endif
endif

richard
- 13th January 2015, 23:01
no I'm still wrong, why is time so complicated

try






If(PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
if RTCHour.6=1 then
temp1 = (((RTCHour&$1f)>> 4) * 10) + (RTCHour& $0f) ' to binary mask off am/pm
else
temp1 = ((RTCHour>> 4) * 10) + (RTCHour& $0f) ' to binary
endif
if RTCHour.6=1 then ' 12h mode
if RTCHour.5=1then temp1=temp1+12 ' pm

else
if temp1 > 12 then
temp1=temp1-12
endif

rtcHOUR = ((temp1 / 10) << 4) + (temp1 // 10) ' to bcd


RTCHour.6 = ! RTCHour.6 ' set/reset 24h mode

I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
endif
endif

lerameur
- 13th January 2015, 23:16
Hi Richard,

Trie both code with same error,
It does seem to go from 19h to 7h.
When I attempt to go back to 19H I get a four appearing before the hours .. like so : 7:01:01 to 47:01:01 then the four disappear to come back to 7:01:01 ( yes minutes and seconds are still incrementing. But this is weird that the four would just leave by its own !

Also the datasheet specifies that the bit 5 hour.5 is used for the hours between the 20 to 23 hours.

richard
- 14th January 2015, 00:17
the "4 " probably comes from the fact that temp1 is used in you display routine and its getting messed with by my code

make a new byte var temp12 for use in the 12/24 routine in place of temp1


but it should go to 19h not stay at 7h check if the am/pm is getting cleared when 24h mode is selected
I have to go to work for a while

Tabsoft
- 14th January 2015, 00:24
Give this a whirl.




rtcAMPM var bit ' Storage flag to indicate AM or PM ; 0=AM, 1=PM
hourmode var bit ' Storage flag for RTC 12/24 hour mode ; 0=24Hr, 1=12Hr
BCDResult var byte ' Storage for temporary result for BCD Conversions


If(PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
hourmode = RTCHour.6
if hourmode = 1 then ' Is the RTC set for 12-hour mode
rtcAMPM = RTCHour.5 ' Assign AM/PM
RTCHour = RTCHour & %00011111 ' Bits 4-0 = Hours 0-12
endif
BCDResult = RTCHour
gosub Bcd2Dec

if hourmode = 1 then '12Hr
if rtcAMPM = 1 then 'PM
BCDResult = BCDResult + 12 'PM
endif
else
if BCDResult > 12 then
BCDResult = BCDResult - 12
rtcAMPM = 1
else
rtcAMPM = 0
endif
endif
gosub Dec2Bcd
RTCHour = BCDResult
hourmode = ! hourmode
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
pause 10
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour] ' Need to write twice because you changed the mode bit



Bcd2Dec:
' Subroutine to convert BCD (2 hex digits) to Decimal
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult >> 4) * 10) + (BCDResult & $0f))

return

Dec2Bcd:
' Subroutine to convert Decimal to BCD (2 hex digits)
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult / 10) << 4) | (BCDResult // 10))

return

lerameur
- 14th January 2015, 00:42
Thanks for all the help.
I just tried your code tabsoft, work very good from 18H to 7H, but not the opposite.
hourmode = not hourmode
but still I print out on the LCD that specific bit and I always get a 1 ...
wird.. I also have RTChour output in binary and I only get 111 (7) and not 100111 as I thought ..

lerameur
- 14th January 2015, 01:19
I try these lines:
if RTCHour.6 =0 then RTCHour.6 =1
if RTCHour.6 =1 then RTCHour.6 =0
instead of hourmode = ! hourmode
hourmode is always showing 0 after going from 19 to 7 . and stays at 7 even with buttons pressed

Tabsoft
- 14th January 2015, 02:17
See if this works for you. I can't try it on the HW, but I think this will do it for you




rtcAMPM var bit ' Storage flag to indicate AM or PM ; 0=AM, 1=PM
hourmode var bit ' Storage flag for RTC 12/24 hour mode ; 0=24Hr, 1=12Hr
BCDResult var byte ' Storage for temporary result for BCD Conversions


If(PortC.5 = 1) & (PortC.6 = 1) then Pause 1500
If (PortC.5 = 1) & (PortC.6 = 1) then
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
hourmode = RTCHour.6
if hourmode = 1 then ' Is the RTC set for 12-hour mode
rtcAMPM = RTCHour.5 ' Assign AM/PM
RTCHour = RTCHour & %00011111 ' Bits 4-0 = Hours 0-12
endif
BCDResult = RTCHour
gosub Bcd2Dec

if hourmode = 1 then '12Hr Convert to 24Hr
hourmode = 0 ' change to 24Hr
if rtcAMPM = 1 then 'PM
BCDResult = BCDResult + 12 'PM
endif
else '24Hr Convert to 12Hr
hourmode = 1
if BCDResult > 12 then
BCDResult = BCDResult - 12
rtcAMPM = 1
else
rtcAMPM = 0
endif
endif
gosub Dec2Bcd
RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
pause 10
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour] ' Need to write twice because you changed the mode bit



Bcd2Dec:
' Subroutine to convert BCD (2 hex digits) to Decimal
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult >> 4) * 10) + (BCDResult & $0f))

return

Dec2Bcd:
' Subroutine to convert Decimal to BCD (2 hex digits)
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult / 10) << 4) | (BCDResult // 10))

return

lerameur
- 14th January 2015, 02:37
Starting with 19H pushing button attempts shows (4 trials one after the other) :
- 87 very briefly then 7H. ok, good enough..
- 1H
-23H
-73H briefly then 13H

I really need to sit down and look at the problem more closely.
But in this case the hourmode bit changes heyyyy !!

Tabsoft
- 14th January 2015, 03:32
I would eliminate the key presses for testing. Setup a pause in your main loop and a just change a new bit variable to mimic the key press action. Just to isolate where the issue may be.

Something like.
Keypressbit var bit

Keypressbit = 0

Mainloop:
Pause 1500
If Keypressbit = 1 then
......... Etc

' at the end of Mainloop
Keypressbit = ~ Keypressbit
Pause 2000 ' 2 second pause
GOTO Mainloop

Btw, ! hourmode should have been ~ hourmode (bit wise not)

Good luck

richard
- 14th January 2015, 05:46
the code by tabsoft works fine with a ds1307 and the double write is not needed , I have not got a 1337 to test



' pic16f688
#CONFIG
__config _INTRC_OSC_NOCLKOUT & _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _BOD_ON & _BOR_ON
#ENDCONFIG



DEFINE OSC 8
DEFINE NO_CLRWDT 1
CRC VAR BYTE BANK0 SYSTEM 'CRC

SDApin var PORTC.0 'SDA
SCLpin var PORTC.1 'SCL

tmp var byte
pkt var byte[11]
rtcAMPM var bit ' Storage flag to indicate AM or PM ; 0=AM, 1=PM
hourmode var bit ' Storage flag for RTC 12/24 hour mode ; 0=24Hr, 1=12Hr
BCDResult var byte ' Storage for temporary result for BCD Conversions
RTCHour var byte
osccon=$70 '8 mhz
ansel=0 'dig i/o
CMCON0=7 ' compare off
trisc=%100000
portc=3
pause 10


i2cwrite sdapin,sclpin,$D0,0,[$0,$14,$21,3,$14,1,$14] 'SANE TIME AND DATE
'i2cwrite sdapin,sclpin,$D0,0,[0]
pause 3000
serout2 porta.0,84, ["ready",13,10]
main:

i2cREAD sdapin,sclpin,$D0,0,[str pkt \3 ]
RTCHour = pkt[2]
if RTCHour.6 then
serout2 porta.0,84, [hex2 (pkt[2]&$1f),":",hex2 pkt[1],":",hex2 pkt[0]]
if RTCHour.5 then serout2 porta.0,84, [" pm" ]
serout2 porta.0,84, [13,10]

else
serout2 porta.0,84, [hex2 pkt[2],":",hex2 pkt[1],":",hex2 pkt[0],13,10]
endif
pause 5000
gosub ampm
goto main

ampm:

I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
hourmode = RTCHour.6
if hourmode = 1 then ' Is the RTC set for 12-hour mode
rtcAMPM = RTCHour.5 ' Assign AM/PM
RTCHour = RTCHour & %00011111 ' Bits 4-0 = Hours 0-12
endif
BCDResult = RTCHour

gosub Bcd2Dec


if hourmode = 1 then '12Hr Convert to 24Hr
hourmode = 0 ' change to 24Hr
if rtcAMPM = 1 then 'PM
BCDResult = BCDResult + 12 'PM
endif
else '24Hr Convert to 12Hr
hourmode = 1
if BCDResult > 12 then
BCDResult = BCDResult - 12
rtcAMPM = 1
else
rtcAMPM = 0
endif
endif
gosub Dec2Bcd
RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
'pause 10
'I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour] ' Need to write twice because you changed the mode bit

return


Bcd2Dec:
' Subroutine to convert BCD (2 hex digits) to Decimal
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult >> 4) * 10) + (BCDResult & $0f))

return

Dec2Bcd:
' Subroutine to convert Decimal to BCD (2 hex digits)
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult / 10) << 4) | (BCDResult // 10))

return

lerameur
- 14th January 2015, 17:24
HI,

I rework your code so I can read it on my LCD:
Its works ! dont know what we did wrong in the previous version.
Also works equally good on DS1337 and DS1307 !
Thanks a lot to all

lerameur
- 14th January 2015, 23:35
HI,

I am adding to the program and came across another difficulty,
I used one button to increments hours and another to increments minutes. Minutes works fine.
But hours, when I start with 19H, do a 24h to 12H conversion.. then when I increase the hours, no matter what time I have the output is 20H, with RTChour.6 = 0 and RTCHour.5 = 1.
I'm stuck in this loop, anybody can see why??
thanks
I posted the complete code, the rest is working great.

INCLUDE "modedefs.bas"
Define OSC 8
CM1CON0.7 = 0
CM2CON0.7 = 0
DEFINE BUTTON_PAUSE 50

'////////////////// HPWM /////////////////////////
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2
Pause 20

'/////////////////////////
'// LCD configuration //
'/////////////////////////

DEFINE LCD_DREG PORTA ' Set LCD Data port
DEFINE LCD_DBIT 0 ' Set starting Data bit (0 or 4) if 4-bit bus RB.4, RB.5, RB.6, RB.7
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 7 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 6 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits) '4 therefore put wire at 4, 5, 6 and 7 of LCD
DEFINE LCD_LINES 2 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2500
DEFINE LCD_DATAUS 250
DEFINE CHAR_PACING 2000
pause 1000

'///////////////////////////////////////////////
'// Variable Declaration and initialization //
'///////////////////////////////////////////////

TrisB= 0
TrisA= 0
'TrisC=%00110000
SDApin var PORTC.4 ' RTC data
SCLpin var PORTC.3 ' RTC clock

tmp var byte
RTCSec var byte
RTCMin var byte
temp_hour var byte
temp_min var byte
pkt var byte[11]
rtcAMPM var bit ' Storage flag to indicate AM or PM ; 0=AM, 1=PM
hourmode var bit ' Storage flag for RTC 12/24 hour mode ; 0=24Hr, 1=12Hr
BCDResult var byte ' Storage for temporary result for BCD Conversions
RTCHour var byte
' osccon=$70 '8 mhz
ansel=0 'dig i/o
' CMCON0=7 ' compare off
trisc=%1110000

pause 10


i2cwrite sdapin,sclpin,$D0,0,[$0,$14,$13,3,$14,1,$14] 'SANE TIME AND DATE
'i2cwrite sdapin,sclpin,$D0,0,[0]
pause 500
lcdout $fe,$c0," Ready",13,10
'serout2 porta.0,84, ["ready",13,10]
main:

Gosub gethour
if PortC.6=1 then gosub ADDHour
if PortC.5=1 then gosub ADDMin


goto main
end


gethour:
i2cREAD sdapin,sclpin,$D0,0,[str pkt \3 ]
RTCHour = pkt[2]
if RTCHour.6 then
lcdout $fe,1,"Time=", hex2 (pkt[2]&$1f),":",hex2 pkt[1],":",hex2 pkt[0] 'bit 0=sec, bit 1=min, bit 2=hrs
lcdout $FE,$C0, bin RTCHour.6, " : ", bin RTCHour.5
if RTCHour.5 then lcdout $fe,$c0, bin RTCHour.6, " pm" 'serout2 porta.0,84, [" pm" ]

else ' if RTCHour.6 =0
lcdout $fe,1,"Time=", hex2 pkt[2],":",hex2 pkt[1],":",hex2 pkt[0]
lcdout $FE,$C0, bin RTCHour.6, " : ", bin RTCHour.5
endif
pause 100
if PortC.5 & PortC.6 then gosub ampm
return

ampm:
Pause 500
if PortC.5 & PortC.6 then
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
hourmode = RTCHour.6
if hourmode = 1 then ' Is the RTC set for 12-hour mode
rtcAMPM = RTCHour.5 ' Assign AM/PM
RTCHour = RTCHour & %00011111 ' Bits 4-0 = Hours 0-12
endif
BCDResult = RTCHour

gosub Bcd2Dec
if hourmode = 1 then '12Hr Convert to 24Hr
hourmode = 0 ' change to 24Hr
if rtcAMPM = 1 then 'PM
BCDResult = BCDResult + 12 'PM
endif
else '24Hr Convert to 12Hr
hourmode = 1
if BCDResult > 12 then
BCDResult = BCDResult - 12
rtcAMPM = 1
else
rtcAMPM = 0
endif
endif
gosub Dec2Bcd
RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
'pause 10
endif

return


Bcd2Dec:
' Subroutine to convert BCD (2 hex digits) to Decimal
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult >> 4) * 10) + (BCDResult & $0f))

return

Dec2Bcd:
' Subroutine to convert Decimal to BCD (2 hex digits)
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult / 10) << 4) | (BCDResult // 10))

return

ADDHour: 'increment hours
pause 200
if PortC.5=1 then return
if PortC.6=1 then

I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
hourmode = RTCHour.6
rtcAMPM = RTCHour.5

BCDResult = RTCHour
gosub Bcd2Dec

if hourmode = 0 then ' this is 24H mode 0H to 23H
hourmode = 1
BCDResult = BCDResult + 1
if BCDResult > 23 then BCDResult = 0
Pause 2
gosub Dec2Bcd
RTCHour = BCDResult
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]

elseif hourmode = 1 then ' this is 12H mode 0H to 11H
hourmode = 0
BCDResult = BCDResult + 1
if BCDResult > 11 then BCDResult = 0
Pause 2
gosub Dec2Bcd
RTCHour = BCDResult
RTCHour.5 = rtcAMPM
' lcdout $FE,1, "RTCH2: ", bin RTCHour
' lcdout $FE,$C0, "BCDR: ", bin BCDResult
' pause 5000
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
endif
endif
return


ADDMin: ' increment a minutes
pause 200
if PortC.6=1 then return
if PortC.5=1 then

' I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
BCDResult = RTCMin
gosub Bcd2Dec
BCDResult = BCDResult + 1
if BCDResult > 59 then BCDResult = 0
Pause 2
gosub Dec2Bcd
RTCMin = BCDResult
I2cwrite SDApin,SCLpin,$D0,$01,[RTCMin]

endif
return

lerameur
- 15th January 2015, 00:00
The bit RTCHour.5 is mixing the time up.. I think..
Why did they use it at a dual purpose.... !

Tabsoft
- 15th January 2015, 02:02
Lerameur,

So, just some basic high-level things to understand when dealing with these RTC ICs.
The data in the RTC registers are in BCD format.
When you make changes to them, say the Hours register you should follow some specific steps.

Get the BCD Hours from the RTC
Save the value of 12/24 mode in your code
Save the value of the am/pm bit value in your code
Mask out the am/pm and 12/24 bits if required
Convert the BCD hours to Decimal hours
Change the Decimal Hours to the value you want
Convert the Decimal Hours to BCD Hours
Set the 12/24 Bit correctly in the New BCD Hours value
Set the am/pm Bit correctly in the New BCD Hours value
Write the new BCD Hours value to the RTC

Try not not intermix operations.
Change the Hour value or change the 12/24 mode, but not both in the same action.

When in 12hr mode, change the time the way you need to for that mode.
When in 24hr mode, change the time the way you need to for that mode.

Another suggestion is create yourself a table for hours in Excel or a text editor.
List all the hours in 12hr mode and also for 24hr mode.
Then for each hour record the byte (in binary) value for the RTC Hour register you would need for that time, making sure to set/clear the 12/24 mode and am/pm bits appropriately.
Looking at that kind of table may help you visualize what you need in your code to change time values to/from different values and when changing 12/24 modes.

Just some thoughts that I followed quite a while back to get a handle on using RTC ICs.

Regards,
TABSoft

Tabsoft
- 15th January 2015, 03:12
Some additional direction.

12hr Mode

Display Value to LCD:

Mask off 12/24Hr mode bit
Mask off am/pm bit
Display new masked value with Hex2 modifier



Change Hour Value in RTC:

Mask off 12/24Hr mode bit
Mask off am/pm bit
Convert new masked value from BCD to Decimal
Change Hour value in Decimal
Convert Decimal Hour back to BCD
Set am/pm bit
Set 12/24Hr mode bit
Write new value to RTC Hour register




24hr Mode

Display Value to LCD:

Display value with Hex2 modifier



Change Hour Value in RTC:

Convert value from BCD to Decimal
Change Hour value in Decimal
Convert Decimal Hour back to BCD
Write new value to RTC Hour register




Here is a table that shows two hour values in their various permutations.
7678

Hope this helps.

lerameur
- 15th January 2015, 03:32
I am having difficulty dealing with the bit 5 and 6 of the hours..
using the subroutine add hours:
I have 11 with bi6 and bit = 0
click on addhour, brings me at hour 32 with bit 6 = 0 and bit 5 = 1
...
ADDHour: 'increment hours
pause 200
if PortC.5=1 then return
if PortC.6=1 then

I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
hourmode = RTCHour.6
rtcAMPM = RTCHour.5
' lcdout $FE,1, "RTCH1: ", bin RTCHour
' lcdout $FE,$C0, "BCDR: ", dec BCDResult
' pause 2000

if hourmode = 0 then ' this is 24H mode 0H to 23H
' hourmode = 1
BCDResult = RTCHour
gosub Bcd2Dec

BCDResult = BCDResult + 1
if BCDResult > 23 then BCDResult = 0
Pause 2
BCDResult_temp = BCDResult
gosub Dec2Bcd
RTCHour = BCDResult
if BCDResult_temp > 12 then RTCHour.5 = 1
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]

elseif hourmode = 1 then ' this is 12H mode 0H to 12H
' hourmode = 0
rtcAMPM = RTCHour.5 ' Assign AM/PM
RTCHour = RTCHour & %00011111 ' Bits 4-0 = Hours 0-12
BCDResult = RTCHour
' lcdout $FE,1, "RTCH1: ", bin RTCHour
' lcdout $FE,$C0, "BCDR: ", dec BCDResult
' pause 2000
gosub Bcd2Dec

BCDResult = BCDResult + 1 ' in decimal
if BCDResult > 12 then BCDResult = 1
Pause 2
gosub Dec2Bcd
RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM
' lcdout $FE,1, "RTCH2: ", bin RTCHour
' lcdout $FE,$C0, "BCDR: ", bin BCDResult
' pause 2000
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
endif
endif
return

lerameur
- 15th January 2015, 03:46
Concerning your table:
With 12Hr 04PM $64 0110 0100 100
Without 12Hr 04PM $4 0000 0100 4

what do you mean with or without ? the AM PM bit ?? because bit 6 is a 1 on the first line, a one means 24H mode, you have 12H showing. What am I not getting ???

Tabsoft
- 15th January 2015, 04:38
Reading the DS1337 Datasheet if bit 6 is High (1) 12hr mode is selected. See snippet from the Datasheet below.

"The DS1337 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12- or 24-hour mode-select bit. When high, the 12-hour mode is selected."

With or without refers to the need, when in 12Hr mode, to mask off(set to 0) BOTH the 12/24Hr and AM/PM bits when using LCDOUT, SEROUT, HSEROUT, etc ; and when changing the value of the Hours in your code to be written back to the RTC. Such as when you allow the user to change the time via buttons.
With = Bits ARE NOT masked ( leads to errors)
Without = Bits ARE masked

Not performing these actions when needed during hour value manipulation and displaying the values will lead to incorrect settings in the RTC and visually strange clock display. E.g. 44 being displayed on the LCD instead of the expected 4 AM or 64 being displayed on the LCD instead of expected 4 PM.

Tabsoft
- 15th January 2015, 05:47
Just for grins, try doing 2 successive writes to the RTC with a 10ms pause in between.

I've ran into these kind of issues whenever the hours.6 bit is changed in the RTC.
Do this when you 1st initialize the RTC on startup and every time you write to the RTC.
The issue is when the 12/24hr mode bit is changed (hours.6).

From the DS
"All hours values, including the alarms, must be reinitialized whenever the 12/24-hour mode bit is changed."

lerameur
- 15th January 2015, 19:21
Hello,

I think I found the problem but I dont know how to get around it,
I have bit 5 confusing me when in 24H mode. How do you remove it from calculation,
The problem is this,
You need to get only number between 20 and 23H used with bit 5.
You also need to know what time you are now to do the calculation, at 18H hour you dont need it so RTCHour is 4 bits
at 20H you need the 5 bits,
So which and when to separate the two,... it seems to me like a chicken or egg issue.. which came first,, or in this case .. which to calculate first

Tabsoft
- 15th January 2015, 20:09
The only time you should need to worry about bit 5 is when bit 6 = 1 (12 hour mode).

When bit 6 = 0 (24 hour mode) you do not have to remove or mess with bit 5. Bit 5 is part of the number [B]not[B] an am/pm bit.

24Hr mode

Time is 11:00 hours, hours = %00010001 notice bit 5 is a zero which means the 2nd 10s is clear, and bit 4 (1st 10s) is a one which is set.
Time is 21:00 hours, hours = %00100001 notice bit 5 is a one which means the 2nd 10s is set, and bit 4 (1st 10s) is zero which is clear.

Tabsoft
- 15th January 2015, 23:16
Try removing or commenting out the following line from your ADDHour routine within the "if hourmode = 0" block (24 hour mode)
if BCDResult_temp > 12 then RTCHour.5 = 1

lerameur
- 16th January 2015, 00:06
Hi again,

here is you example with different hours..

24Hr mode

Time is 23:00 hours, hours = %00100110 notice bit 5 is a one
add 1 to 23
Time is 00:00 hours, hours = %00000000 notice bit 5 is zero
SO the bit 5 does changes int he 24H mode...
maybe i'm still not seeing it good..

lerameur
- 16th January 2015, 01:51
HooHoo ! , got it all working now.

Ya bit 5 was a bit confusing,
thanks a million for your time

Tabsoft
- 16th January 2015, 02:02
Great! Glad to help.
The hour register of the RTC can be a bit confusing with its mix of hour mode and am/pm options/values.
When I did this a while back I created a spreadsheet to to visual all of the possible values and how to deal with them.

How about posting your final code so the readers can see your final solution?:)

lerameur
- 16th January 2015, 02:43
Here you go :

'/////////////////////////
'//
'// Using the PIC16F886
'// AM PM mode
'// Increment Hour and Minutes
'// Output to LCD 2x16
'//
'/////////////////////////

'/////////////////////////
'// Define section //
'/////////////////////////


INCLUDE "modedefs.bas"
Define OSC 8
CM1CON0.7 = 0
CM2CON0.7 = 0
DEFINE BUTTON_PAUSE 50

'////////////////// HPWM /////////////////////////
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2
Pause 20

'/////////////////////////
'// LCD configuration //
'/////////////////////////

DEFINE LCD_DREG PORTA ' Set LCD Data port
DEFINE LCD_DBIT 0 ' Set starting Data bit (0 or 4) if 4-bit bus RB.4, RB.5, RB.6, RB.7
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 7 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 6 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits) '4 therefore put wire at 4, 5, 6 and 7 of LCD
DEFINE LCD_LINES 2 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2500
DEFINE LCD_DATAUS 250
DEFINE CHAR_PACING 2000
pause 1000

'///////////////////////////////////////////////
'// Variable Declaration and initialization //
'///////////////////////////////////////////////

TrisB= 0
TrisA= 0
TrisC=%1110000
SDApin var PORTC.4 ' RTC data
SCLpin var PORTC.3 ' RTC clock

tmp var byte
pkt var byte[11]
rtcAMPM var bit ' Storage flag to indicate AM or PM ; 0=AM, 1=PM
hourmode var bit ' Storage flag for RTC 12/24 hour mode ; 0=24Hr, 1=12Hr
BCDResult var byte ' Storage for temporary result for BCD Conversions
RTCHour var byte
RTCMin var byte
RTCSec var byte
'The DS1337 can be run in either 12-hour or 24-hour mode. Bit 6 of the hours register is defined as the 12- or 24-
'hour mode-select bit. When high, the 12-hour mode is selected. In the 12-hour mode, bit 5 is the AM/PM bit with
'logic high being PM. In the 24-hour mode, bit 5 is the second 10-hour bit (20–23 hours).
'The only time you should need to worry about bit 5 is when bit 6 = 1 (12 hour mode).
ansel=0 'dig i/o
' CMCON0=7 ' compare off
trisc=%1110000

'i2cwrite sdapin,sclpin,$D0,0,[$0,$14,$18,3,$14,1,$14] ' TIME AND DATE
pause 10

main:

Gosub gethour
if PortC.5 & PortC.6 then gosub ampm
if PortC.6 then gosub ADDHour
if PortC.5 then gosub ADDMin
goto main


end

Gethour:
i2cREAD sdapin,sclpin,$D0,0,[str pkt \3 ]
RTCHour = pkt[2]
if RTCHour.6 then ' this is HIGH, therfore 12H mode
lcdout $fe,1,"Time=", hex2 (pkt[2]& %00011111),":",hex2 pkt[1],":",hex2 pkt[0] 'bit 0=sec, bit 1=min, bit 2=hrs
if RTCHour.5 then
lcdout $fe,$c0, "pm:"' ,bin RTCHOUR.6,":", Bin RTCHOUR.5,":", bin RTCHOUR
else
lcdout $fe,$c0, "am:"' ,bin RTCHOUR.6,":", Bin RTCHOUR.5,":", bin RTCHOUR
endif
else
lcdout $fe,1,"Time2=", hex2 pkt[2],":",hex2 pkt[1],":",hex2 pkt[0]
' lcdout $fe,$c0, " :" ,bin RTCHOUR.6,":", Bin RTCHOUR.5,":", bin RTCHOUR
endif
pause 100

return

ampm:
pause 500
if PortC.5 & PortC.6 then
I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
hourmode = RTCHour.6
if hourmode = 1 then ' Is the RTC set for 12-hour mode
rtcAMPM = RTCHour.5 ' Assign AM/PM
RTCHour = RTCHour & %00011111 ' Bits 4-0 = Hours 0-12
endif
BCDResult = RTCHour

gosub Bcd2Dec


if hourmode = 1 then '12Hr Convert to 24Hr
hourmode = 0 ' change to 24Hr
if rtcAMPM = 1 then 'PM
BCDResult = BCDResult + 12 'PM
endif
else '24Hr Convert to 12Hr
hourmode = 1
if BCDResult > 12 then
BCDResult = BCDResult - 12
rtcAMPM = 1
else
rtcAMPM = 0
endif
endif
gosub Dec2Bcd
RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
pause 10
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour] ' Need to write twice because you changed the mode bit
pause 10

endif
return


Bcd2Dec:
' Subroutine to convert BCD (2 hex digits) to Decimal
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult >> 4) * 10) + (BCDResult & $0f))

return

Dec2Bcd:
' Subroutine to convert Decimal to BCD (2 hex digits)
' Make sure to set BCDResult with parameter value before calling this sub
' Result is stored in BCDResult

BCDResult = (((BCDResult / 10) << 4) | (BCDResult // 10))

return

ADDHour: 'increment hours
pause 200
if PortC.5=1 then return
if PortC.6=1 then
i2cREAD sdapin,sclpin,$D0,0,[str pkt \3 ]
RTCHour = pkt[2]
hourmode = RTCHour.6
rtcAMPM = RTCHour.5
'////////Selection Begins here
if hourmode = 0 then ' this is 24H mode 0H to 23H and bit 5 is used to calculate hours
RTCHour = RTCHour & $3F ' keeping the bit 5
BCDResult = RTCHour
gosub Bcd2Dec
BCDResult = BCDResult + 1
if BCDResult > 23 then
BCDResult = 0
' hourmode = 1
rtcAMPM=0
endif
if BCDResult > 19 then ' bit 5 is needed for the hours 20h to 23h
rtcAMPM=1
endif
gosub Dec2Bcd
endif
RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM

I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
pause 10
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour] ' Need to write twice because you changed the mode bit
pause 10
endif
if hourmode = 1 then ' this is 12H mode 0H to 11H
pause 100
RTCHour = RTCHour & %00011111 ' keeping the bit 5
BCDResult = RTCHour

gosub Bcd2Dec
BCDResult = BCDResult + 1

if BCDResult > 12 then
BCDResult = 1
rtcAMPM = not rtcAMPM ' 0 is for the AM mode
endif
gosub Dec2Bcd

RTCHour = BCDResult
RTCHour.6 = hourmode
RTCHour.5 = rtcAMPM
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour]
pause 10
I2cwrite SDApin,SCLpin,$D0,$02,[RTCHour] ' Need to write twice because you changed the mode bit
pause 10
endif
return


ADDMin: ' increment a minutes
pause 200
if PortC.6=1 then return
if PortC.5=1 then

' I2CRead SDApin,SCLpin,$D0,$02,[RTCHour]
I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour]
BCDResult = RTCMin
gosub Bcd2Dec
BCDResult = BCDResult + 1
if BCDResult > 59 then BCDResult = 0
Pause 2
gosub Dec2Bcd
RTCMin = BCDResult
I2cwrite SDApin,SCLpin,$D0,$01,[RTCMin]

endif
return