PDA

View Full Version : Binary Coded Decimal



-Dan-
- 19th May 2009, 14:10
How do i convert bcd values to decimal, and decimal to bcd.

eg bcd :0010 0011 = 23

how would i convert that to 23 in decimal

sinoteq
- 19th May 2009, 14:29
Shift right is one way.


DEC_Out Var Byte
BCD_In Var Byte


DEC_Out=(BCD_In>>4*10)+(BCD_In & %00001111)

This should in theory take the 4 Highbits and shift them right 4 times. Then multiply this result with 10 and add the 4 low bits putting the result in DEC_Out.


To do the DEC to BCD you can use the DIG command it is really good for this.

-Dan-
- 20th May 2009, 20:10
HI thanks that works great

i'm using a real time clock and the only issue i have now is that when seconds reaches 40 the hours increments to 40

the hour register is only 6 bits long bits 6 and 7 are not used, would i have to shift by less than 4 compared to the other registers



Shift right is one way.


DEC_Out Var Byte
BCD_In Var Byte


DEC_Out=(BCD_In>>4*10)+(BCD_In & %00001111)

This should in theory take the 4 Highbits and shift them right 4 times. Then multiply this result with 10 and add the 4 low bits putting the result in DEC_Out.


To do the DEC to BCD you can use the DIG command it is really good for this.

sinoteq
- 21st May 2009, 02:07
Real Time Clock, show us the code and we can advice. Or search the forum because most RTC has code examples or parts of examples that you can reuse in an easy way.

Many RTC has mixed registers so you have to do some woodoo activities to sort out the information you want from it :)

-Dan-
- 21st May 2009, 14:16
Real Time Clock, show us the code and we can advice. Or search the forum because most RTC has code examples or parts of examples that you can reuse in an easy way.

Many RTC has mixed registers so you have to do some woodoo activities to sort out the information you want from it :)



@ device pic16f870,WDT_OFF 'Watch Dog Timer Disabled
@ device pic16f870,PROTECT_OFF 'Code Protect Off
@ device pic16f870,XT_OSC 'Using External Oscillator
@ device pic16f870,BOD_OFF 'Brown Out Timer Disabled
@ device pic16f870,PWRT_OFF 'Power On Timer Disabled
@ device pic16f870,LVP_OFF 'Low Voltage Programmed Disabled

DEFINE OSC 4
ADCON0.0=0
ADCON1=7 ' ALL PINS SET TO DIGITAL
TRISB = %00000000
TRISA = %00000000
TRISC.0=0




'rtc pins

clk_pin var portc.5
data_pin var portc.6

number var word
display VAR PORTB
segment var PORTA
seg_number var byte
digit var byte
delay var word




'register address's

reg_seconds CON $02
reg_minutes con $03
reg_hours con $04
reg_days con $05
reg_weekdays con $06
reg_months_century con $07
reg_years con $08
reg_minute_alarm con $09
reg_hour_alarm con $0A
reg_day_alarm con $0B
reg_weekday_alarm con $0C

rtc_write var byte
rtc_read var byte

rtc_write=$a2
rtc_read=$a3



'time variables

bcdseconds var BYTE
bcdminutes var BYTE
bcdhours var BYTE
bcddays var BYTE
bcdyears var BYTE


seconds var BYTE
minutes var BYTE
hours var BYTE
days var BYTE
years var BYTE



'-----------------------------------------------------
'initial time variable values

seconds=01
minutes=23
hours=22
'days=23
'years=7

' -------------------------------------------------------

'write intial variable's to the relevant rtc registers

init:

bcd_encode:

bcdseconds=seconds dig 1
bcdseconds=bcdseconds<<4
bcdseconds=bcdseconds+seconds dig 0

bcdminutes=minutes dig 1
bcdminutes=bcdminutes<<4
bcdminutes=bcdminutes+minutes dig 0

bcdhours=hours dig 1
bcdhours=bcdhours<<3
bcdhours=bcdhours+hours dig 0



pause 10

I2CWrite data_pin,clk_pin,$A2,reg_seconds,[bcdseconds,bcdminutes,bcdhours]
pause 100


clock_read:


I2CRead data_pin,clk_pin,$A3,reg_seconds,[bcdseconds,bcdminutes,bcdhours]
pause 10

bcd_decode: 'decodes bcd to decimal

seconds=(bcdseconds>>4)*10+(bcdseconds & %00001111)

minutes=(bcdminutes>>4)*10+(bcdminutes & %00001111)

hours=(bcdhours>>3)*10+(bcdhours & %00000111)




OUT:
pause 20
serout2 portc.1,16780,[" ",#hours,":", #minutes,":",#seconds]
PORTC.0=1
PAUSE 100
PORTC.0=0


goto clock_read

-Dan-
- 23rd May 2009, 03:24
does anyone have any ideas?


when the seconds register is equal to 40, the "tens" of the hours register becomes 4 (e.g 09 then changed to 49 when seconds becomes 40) the hours "tens" then returns to its correct value once seconds is smaller than 40 again.

here is an example, i am debugging using hyperterminal:

hours:minutes:seconds

9(9):22(22):38(38)

9(9):22(22):39(39)

49(49):22(22):40(40)

the values in the brackets are the bcd values straight from the registers without being ran through any conversion routines, i then output them using the HEX modifier.

sinoteq
- 23rd May 2009, 06:53
What kind of RTC do you use? Part number please :)

-Dan-
- 23rd May 2009, 07:05
What kind of RTC do you use? Part number please :)

Its a PCF8563P

sinoteq
- 23rd May 2009, 11:59
I am sorry I don't have that RTC here so I can test code for you yet.

There are some things in your code that are inconsistent with the datasheet so you should start with fixing this.

Please look at http://www.datasheetcatalog.org/datasheet/philips/PCF8563P.pdf Table 5. As you see the Seconds register is only 7 bits wide and not 8, the 8th bit is VL. So start by making sure that bit is not included in you conversion and setting of the RTC.

Are you sure you chip is healty? Have you tested this on more than one RTC?
Please forgive me for asking, but is this related to this previous 2007 posting?http://www.picbasic.co.uk/forum/archive/index.php/t-7567.html
In that case I can only say you have had this problem for some time and then it is really time to solve this.

I will swing by the market some day and pick up a chip so I can help you better.

-Dan-
- 23rd May 2009, 12:43
hey,

yer that is an old topic i kinda give up some time ago on the rtc.

But i tought i would pick it back up and finally get my head around it

when i posted that topic i didn't even no what bcd was... so as you can imagine i didn't get any were near as far as i have now.


i am watching the value of the seconds register and it is incrementing correctly from 0-59 and the minutes are incrementing when the seconds reaches 0

i'll look in to the voltage low bit in the seconds register and see if that is the cause of my problem, i'll let you know how i get on.

and yes ive tried another one of these rtc and get the same error

thanks for taking the time to help me




I am sorry I don't have that RTC here so I can test code for you yet.

There are some things in your code that are inconsistent with the datasheet so you should start with fixing this.

Please look at http://www.datasheetcatalog.org/datasheet/philips/PCF8563P.pdf Table 5. As you see the Seconds register is only 7 bits wide and not 8, the 8th bit is VL. So start by making sure that bit is not included in you conversion and setting of the RTC.

Are you sure you chip is healty? Have you tested this on more than one RTC?
Please forgive me for asking, but is this related to this previous 2007 posting?http://www.picbasic.co.uk/forum/archive/index.php/t-7567.html
In that case I can only say you have had this problem for some time and then it is really time to solve this.

I will swing by the market some day and pick up a chip so I can help you better.

-Dan-
- 25th May 2009, 06:01
I've directly given the registers the bcd values and monitored the bcd value of the register as it changes but it still increase's the tens of the hours by 4 when seconds=40, i have not addressed the unused bits in the registers, so i cannot see it being that.

i am lost for ideas





@ device pic16f870,WDT_OFF 'Watch Dog Timer Disabled
@ device pic16f870,PROTECT_OFF 'Code Protect Off
@ device pic16f870,XT_OSC 'Using External Oscillator
@ device pic16f870,BOD_OFF 'Brown Out Timer Disabled
@ device pic16f870,PWRT_OFF 'Power On Timer Disabled
@ device pic16f870,LVP_OFF 'Low Voltage Programmed Disabled

DEFINE OSC 4
ADCON0.0=0
ADCON1=7 ' ALL PINS SET TO DIGITAL
TRISB = %00000000
TRISA = %00000000
TRISC.0=0




'rtc pins

clk_pin var portc.5
data_pin var portc.6

number var word
display VAR PORTB
segment var PORTA
seg_number var byte
digit var byte
delay var word




'register address's

reg_seconds CON $02
reg_minutes con $03
reg_hours con $04
reg_days con $05
reg_weekdays con $06
reg_months_century con $07
reg_years con $08
reg_minute_alarm con $09
reg_hour_alarm con $0A
reg_day_alarm con $0B
reg_weekday_alarm con $0C

rtc_write var byte
rtc_read var byte

rtc_write=$a2
rtc_read=$a3



'time variables

bcdseconds var BYTE
bcdminutes var BYTE
bcdhours var BYTE
bcddays var BYTE
bcdyears var BYTE


seconds var BYTE
minutes var BYTE
hours var BYTE
days var BYTE
years var BYTE



'-----------------------------------------------------
'initial time variable values

seconds=%0100011
minutes=%0100011
hours=%100011
'days=23
'years=7

' -------------------------------------------------------

'write intial variable's to the relevant rtc registers

init:

'bcd_encode:

'bcdseconds=seconds dig 1
'bcdseconds=bcdseconds<<4
'bcdseconds=bcdseconds+seconds dig 0

'bcdminutes=minutes dig 1
'bcdminutes=bcdminutes <<4
'bcdminutes=bcdminutes+minutes dig 0

'bcdhours=hours dig 1
'bcdhours=bcdhours<<4
'bcdhours=bcdhours+hours dig 0



pause 10

I2CWrite data_pin,clk_pin,$A2,reg_seconds,[seconds,minutes,hours]
pause 100


clock_read:


I2CRead data_pin,clk_pin,$A2,reg_seconds,[bcdseconds,bcdminutes,bcdhours]
pause 10

'bcd_decode: 'decodes bcd to decimal

'seconds=(bcdseconds>>4)*10+(bcdseconds & %00001111)

'minutes=(bcdminutes>>4)*10+(bcdminutes & %00001111)

'hours=(bcdhours>>4)*10+(bcdhours & %00001111)




OUT:
pause 20
serout2 portc.1,16780,["(",HEX bcdhours,")","(",HEX bcdminutes,")","(",HEX bcdseconds,")"]
PORTC.0=1
PAUSE 100
PORTC.0=0


goto clock_read

sinoteq
- 25th May 2009, 09:23
OK this is a declaration of war :) I will go to the market tomorrow and get me a few of these RTC chips. Really, it has to be something simple because it almost always is but this has to be solved.

Please post a picture of your connections so I can connect in a similar way.