PDA

View Full Version : Bcd Fomat Help



Santana
- 7th November 2004, 15:11
Hello everyone
Could someone be kind enough to explain to me how i can subtract from a BCD format number.

Here is the problem, i designed a data logger which needs the user to select a logging interval between 1 minute and 24Hrs
my pic make s a measurement and store the result in a serial eeprom .
i am using a DS1307 RTC to stamp the data with date & Time.
the problem is my circuit now works ok but i have got a 4 seconds overhead as the measurement takes 4 seconds to complete so if the user selects a reading interval of 1 minute the reading would be taken every 1 minute & 4 secs example
(12:00:00,12:01:04,12:02:08)

What i would like to do is to minus 1 from the user entered minutes then default the seconds to 56 seconds so that
instead of the user 1 min it is now 56 seconds but do know how to do this with BCD format

This is how i take the user enters

HSerout [" Set Minutes Interval (00 - 59) Type S01 for 1min ,S13 for 13mins etc",10, 13]
IF A1minS =0 Then
HSerin[WAIT("S"),HEX2 A1minS ]
EndIF
HSerout [" Minutes Set to : ",HEX2 A1minS," Mins",10, 13]
HSerout [10, 13]
A1minS =A1minS-$01
write A1minS_flag,A1minS ' stored ALARM MINS in A1minS_flag
pause 10
A1sec =$56

But this don't work is there some thing i am doing wrong with BCD numbers

Santana
- 7th November 2004, 20:09
binhold = (( A1minS & $f0)>>4*10)+( A1minS & $0f) 'covert bcd to binary

binhold =binhold -1

How do i now convert back to bcd ?

Whould the result be correct?

Melanie
- 7th November 2004, 20:30
Convert BCD to decimal... assume variable RTCSeconds holds the seconds in BCD format...

First let's deal with the TENS value (Bits 4,5 and 6)...

DecimalSeconds=RTCSeconds & $70
DecimalSeconds=DecimalSeconds>>4
DecimalSeconds=DecimalSeconds*10

And finally add-in the UNITS value...

DecimalSeconds=DecimalSeconds+(RTCSeconds & $0F)

----

To convert Decimal back to BCD, reverse the Process...

RTCSeconds=DecimalSeconds DIG 1
RTCSeconds=RTCSeconds<<4
RTCSeconds=RTCSeconds+(DecimalSeconds DIG 0)

----

Incorporate the above into a General Purpose Subroutine and use the same single routine to convert Seconds, Minutes, Hours etc etc.


Melanie

Demon
- 23rd February 2005, 18:33
To convert Decimal back to BCD, reverse the Process...

RTCSeconds=DecimalSeconds DIG 1
RTCSeconds=RTCSeconds<<4
RTCSeconds=RTCSeconds+(DecimalSeconds DIG 0)

------------------------------------------------------------

Are you sure about that?

I'm trying to convert a 6 digit decimal number into binary and found this thread. If I take 32 for example and manually run it through your code, I get lost.

DECNUM = 32
BINNUM = DECNUM dig 1 : 0000 0011
BINNUM = BINNUM<<4 : 0011 0000
BUNNUM = BINNUM+(DECNUM dig 0) : 0011 0010

But if I use my calculator, 32 = 0010 0000.

I don't see how you can just split the decimal digits and concatenate theM to make a binary number. Or am I missing something in your formula?

Robert "Dazed 'n confused'
:)

Demon
- 23rd February 2005, 19:11
WOW!

Check out this guy's idea:

http://www.is.wayne.edu/olmt/binary/page3.htm

Robert
:)

ronjodu
- 23rd February 2005, 21:04
Don't know if this can help but this is what I use to go back and forth between a ds1302, a pic, a Siteplayer and an LCD.



k = rtcmin : gosub h2d : decmin = k 'or k = rtchr, rtcsec, etc...
'((((((((((((((((((((((((((((((((((((((()))))))))) )))))))))))))))))))))))))))))
'Subroutine to convert from Hex to Dec
'((((((((((((((((((((((((((((((((((((((()))))))))) )))))))))))))))))))))))))))))

h2d: ' Convert Hex coded time data -> decimal data
K = (K & $F )+((K>>4)*10)
Return



k = decmin : gosub d2h : rtcmin = k 'or k=dechr, decsec,etc..
'((((((((((((((((((((((((((((((((((((((()))))))))) )))))))))))))))))))))))))))))
'Subroutine to convert from Dec to Hex
'((((((((((((((((((((((((((((((((((((((()))))))))) )))))))))))))))))))))))))))))
d2h: ' Convert Decimal -> Hex coded time data
K = (K DIG 1) * $10 + (K DIG 0)
Return



Hope it helps.

Demon
- 23rd February 2005, 23:53
I found this nice Assembler routine here:

http://www.piclist.com/techref/microchip/math/radix/bu2b-5d16b-ph.htm

And best of all, he explains it all for people like me. :D He boasts it takes only 33 cycles in all to complete, which I consider fantastic compared to any of the alternatives I can possibly write in BASIC Pro (after it converts into Assembler).

He says it's free, I'm using it as an include and keeping all his credits; he deserves it. I don't like using someone else's free code, I like using my 'own stuff'', but this routine is just awesome. 5 bytes in, 2 bytes out, and no temporary variables, pretty sleek stuff.

And for those like me that don't know how to tie this into our BASIC programs, chapter 8.2 is where it's at.



; 5 digit decimal to 16 (17) bit binary. By Peter Hemsley, March 2003.
; Input decimal digits in D0 (LSD) to D4 (MSD)
; Output 16 bit binary in NUMHI and NUMLO
; No temporary variables required
; Code size: 33 instructions
; Execution time: 33 cycles (excluding Call and Return)
; Returns carry set if > 65535 (and NUMHI-LO MOD 65536)

dec2bin16
movf D1,W ; (D1 + D3) * 2
addwf D3,W
movwf NUMLO
rlf NUMLO,F

swapf D2,W ; + D2 * 16 + D2
addwf D2,W
addwf NUMLO,F

rlf D4,W ; + (D4 * 2 + D3) * 256
addwf D3,W
movwf NUMHI

rlf NUMLO,F ; * 2
rlf NUMHI,F

swapf D3,W ; - D3 * 16
subwf NUMLO,F
skpc
decf NUMHI,F

swapf D2,W ; + D2 * 16 + D1
addwf D1,W
addwf NUMLO,F
skpnc
incf NUMHI,F

swapf D4,W ; + D4 * 16 + D0
addwf D0,W

rlf NUMLO,F ; * 2
rlf NUMHI,F

addwf NUMLO,F
skpnc
incf NUMHI,F

movf D4,W ; - D4 * 256
subwf NUMHI,F

swapf D4,W ; + D4 * 16 * 256 * 2
addwf NUMHI,F
addwf NUMHI,F

return ; Q.E.D.

Luciano
- 23rd February 2005, 23:58
Definition:

BCD represents each of the digits of an unsigned decimal
as the 4-bit binary equivalents.


UNPACKED BCD:

Unpacked BCD representation contains only one decimal digit per byte.
The digit is stored in the least significant 4 bits; the most significant
4 bits are not relevant to the value of the represented number.


PACKED BCD:

Packed BCD representation packs two decimal digits into a single byte.


* * *

Example values:

Decimal------Binary---------Unpacked BCD----------Packed BCD

0-----------0000 0000---------------0000 0000-----0000 0000
1-----------0000 0001---------------0000 0001-----0000 0001
2-----------0000 0010---------------0000 0010-----0000 0010
3-----------0000 0011---------------0000 0011-----0000 0011
4-----------0000 0100---------------0000 0100-----0000 0100
5-----------0000 0101---------------0000 0101-----0000 0101
6-----------0000 0110---------------0000 0110-----0000 0110
7-----------0000 0111---------------0000 0111-----0000 0111
8-----------0000 1000---------------0000 1000-----0000 1000
9-----------0000 1001---------------0000 1001-----0000 1001
10----------0000 1010-----0000 0001 0000 0000-----0001 0000
11----------0000 1011-----0000 0001 0000 0001-----0001 0001
12----------0000 1100-----0000 0001 0000 0010-----0001 0010
13----------0000 1101-----0000 0001 0000 0011-----0001 0011
14----------0000 1110-----0000 0001 0000 0100-----0001 0100
15----------0000 1111-----0000 0001 0000 0101-----0001 0101
16----------0001 0000-----0000 0001 0000 0110-----0001 0110
17----------0001 0001-----0000 0001 0000 0111-----0001 0111
18----------0001 0010-----0000 0001 0000 1000-----0001 1000
19----------0001 0011-----0000 0001 0000 1001-----0001 1001
20----------0001 0100-----0000 0010 0000 0000-----0010 0000




==================================================
Decimal to Packed BCD:
==================================================
Example decimal 16 to Packed BCD

decVal= 16 decimal

Formula:
Packed_bcdVal = (decVal / 10) << 4 + (decVal // 10)

(decVal / 10)
00010000 / 00001010 = 00000001

Shifts the result left 4 places
00000001 << 4 = 00010000

(decVal // 10) modulus
00010000 // 10 = 00000110
(00000110 , Dec 6 is the remainder).

00010000 + 00000110 = 00010110

Result: 00010110
(00010110 represent the Packed BCD value for decimal 16)


==================================================
Packed BCD to Decimal:
==================================================
Example Packed BCD 00010110 to decimal

Packed_BCD = 00010110

Formula:
decVal = (Packed_BCD_high_nibble * 10) + Packed_BCD_low_nibble

Packed_BCD_high_nibble = 0001
Packed_BCD_low_nibble = 0110

(Packed_BCD_high_nibble * 10)
0001 * 1010 = 1010

1010 + 0110 = 00010000

Result: 00010000
(00010000 = decimal 16)

==================================================

Best regards,

Luciano

Demon
- 24th February 2005, 00:14
Packed, unpacked, I graduated from college in '83, let's see, that's 5 years ago?

I never used that in 20 years as programmer, forgot that basic stuff. I'm looking at your 2 digit conversion example and trying to figure how you'd go about converting 6 decimal digits to binary in 2 bytes. Now my brain hurts...

Robert
:D

Demon
- 24th February 2005, 00:36
Woah, the more I read about converting, the more confused I get. When I counted binary, it went like this:

09. 0000 1001
10. 0000 1010
11. 0000 1011
12. 0000 1100
13. 0000 1101
14. 0000 1110
15. 0000 1111

My problem is that this data will be used for addressing on external memory chips; 24C256.

Robert
?

financecatalyst
- 3rd January 2011, 17:02
Convert BCD to decimal... assume variable RTCSeconds holds the seconds in BCD format...

First let's deal with the TENS value (Bits 4,5 and 6)...

DecimalSeconds=RTCSeconds & $70
DecimalSeconds=DecimalSeconds>>4
DecimalSeconds=DecimalSeconds*10

And finally add-in the UNITS value...

DecimalSeconds=DecimalSeconds+(RTCSeconds & $0F)

----

To convert Decimal back to BCD, reverse the Process...

RTCSeconds=DecimalSeconds DIG 1
RTCSeconds=RTCSeconds<<4
RTCSeconds=RTCSeconds+(DecimalSeconds DIG 0)

----


Incorporate the above into a General Purpose Subroutine and use the same single routine to convert Seconds, Minutes, Hours etc etc.


Melanie
Thanks a lot. I was breaking my head from last few days to learn this. You have really explained it very nicely.

BUT

I am facing slight problem in my simulation (I am using proteus).
My code looks like this when program starts for the first time:


Rtcget var byte[8]
Rtcsec var Rtcget[0]
Rtcmin var Rtcget[1]
Rtchr var Rtcget[2]
Rtcday var Rtcget[3]

read 30,check
if check=0 then
pause 50
I2CWRITE SDA,SCL,$D0,$00,[$00,$00,$12,$01,$00,$00,$00,$90]
pause 50
write 30,1
endif

I2CREAD SDA,SCL,$D1,$00,[STR Rtcget\8]
pause 50
sec=Rtcsec & $70
sec = sec>>4
sec=sec*10
sec=sec +(Rtcsec & $0F)

minu=Rtcmin & $70
minu = minu>>4
minu=minu*10
minu=minu +(Rtcmin & $0F)

hrs=Rtchr & $30
hrs=hrs>>4
hrs=hrs*10
hrs=hrs+(Rtchr & $0F)

if Rtcday=$01 then days=1
if Rtcday=$02 then days=2
if Rtcday=$03 then days=3
if Rtcday=$04 then days=4
if Rtcday=$05 then days=5
if Rtcday=$06 then days=6
if Rtcday=$07 then days=7

& when user changes the time it looks like this


Rtcmin=minu DIG 1
Rtcmin=Rtcmin<<4
Rtcmin=Rtcmin+(minu DIG 0)

Rtchr=hrs DIG 1
Rtchr=Rtchr<<4
Rtchr=Rtchr+(hrs DIG 0)

if days=1 then Rtcday=$01
if days=2 then Rtcday=$02
if days=3 then Rtcday=$03
if days=4 then Rtcday=$04
if days=5 then Rtcday=$05
if days=6 then Rtcday=$06
if days=7 then Rtcday=$07
I2CWRITE SDA,SCL,$D0,$00,[$00,Rtcmin,Rtchr,Rtcday,$00,$00,$00,$90]
PAUSE 20

The problem is that during simulation, the frequency of the pulse changes once I set the time (coming from DS1307 - I want 1Hz)
Please point out the problem in my code if any, or is it the simulation software which is not correct (Proteus 6.9)

financecatalyst
- 4th January 2011, 21:53
Anyone there?

jayanthd
- 26th November 2012, 15:41
Hi! Melanie

Is this write to convert seconds to bcd from decimals so that it can be written to ds1307.


(((ssec & 0x70) >> 4) * 10) + (ssec & 0x0F)

What is the dec2bcd codes for minutes, hours, day, weekday, month, and year?

mackrackit
- 27th November 2012, 01:35
The Queen has not been here for awhile, but maybe this will help


READ_RTC:
I2CREAD DS_SDA, DS_SCL, RTC, SEC_REG, [sec,mins,hr,day,date,mon,yr]

SEC_T = sec & $70
SEC_T = SEC_T>>4
SEC_O = sec & $0F

MIN_T = mins & $70
MIN_T = MIN_T>>4
MIN_O = MINs & $0F

HR_T = hr & $70
HR_T = HR_T>>4
HR_O = hr & $0F

MON_T = mon & $70
MON_T = MON_T>>4
MON_O = mon & $0F

DATE_T = date & $70
DATE_T = DATE_T>>4
DATE_O = date & $0F

YR_T = yr & $70
YR_T = YR_T>>4
YR_O = yr & $0F

jayanthd
- 28th November 2012, 05:17
The Queen has not been here for awhile, but maybe this will help


READ_RTC:
I2CREAD DS_SDA, DS_SCL, RTC, SEC_REG, [sec,mins,hr,day,date,mon,yr]

SEC_T = sec & $70
SEC_T = SEC_T>>4
SEC_O = sec & $0F

MIN_T = mins & $70
MIN_T = MIN_T>>4
MIN_O = MINs & $0F

HR_T = hr & $70
HR_T = HR_T>>4
HR_O = hr & $0F

MON_T = mon & $70
MON_T = MON_T>>4
MON_O = mon & $0F

DATE_T = date & $70
DATE_T = DATE_T>>4
DATE_O = date & $0F

YR_T = yr & $70
YR_T = YR_T>>4
YR_O = yr & $0F



You have given RTC Read function. It used Bcd2Dec. I need Dec2Bcd for RTC Writing.

is this RTC Read code correct
ssec = ((sec & 0x70) >> 4) + (sec & 0x0F)

jayanthd
- 28th November 2012, 05:20
In the following code what is DIG, DIG 1, and DIG 0?

To convert Decimal back to BCD, reverse the Process...

RTCSeconds=DecimalSeconds DIG 1
RTCSeconds=RTCSeconds<<4
RTCSeconds=RTCSeconds+(DecimalSeconds DIG 0)

mackrackit
- 28th November 2012, 06:00
You have given RTC Read function. It used Bcd2Dec. I need Dec2Bcd for RTC Writing.

is this RTC Read code correct
ssec = ((sec & 0x70) >> 4) + (sec & 0x0F)
That will give you the ones place.

From the manual


4.17.7. DIG

DIG returns the value of a decimal digit. Simply tell it the digit number (0 - 4 with 0 being the rightmost digit) you would like the value of, and voila.

B0 = 123 ' Set B0 to 123
B1 = B0 DIG 1 ' Sets B1 to 2 (digit 1 of 123)