ME Labs, Inc.
  Developer Resources:

Programming Clues
    Sample Programs
Compiler Manual
    PICBASIC™ Compiler
    Serin2/Serout2 Modes
    ASCII Character Set
    Number Conversion
    Floating Point
    PBP Debug Monitor
    Articles and Tutorials

Hardware Clues
    Parts / Vendor List
    PICPROTO™ Boards
    LAB-X1 Docs
    LAB-X2 Docs
    LAB-X20 Docs
    LAB-X3 Docs
    LAB-X4 Docs
    LAB-XUSB Docs
    LAB-XT Docs

BCD (Binary Coded Decimal) Number System

You should now be familiar with the Binary, Decimal and Hexadecimal Number System. If we view single digit values for hex, the numbers 0 - F, they represent the values 0 - 15 in decimal, and occupy a nibble. Often, we wish to use a binary equivalent of the decimal system. This system is called Binary Coded Decimal or BCD which also occupies a nibble. In BCD, the binary patterns 1010 through 1111 do not represent valid BCD numbers, and cannot be used.

Conversion from Decimal to BCD is straightforward. You merely assign each digit of the decimal number to a byte and convert 0 through 9 to 00000000 through 00001001, but you cannot perform the repeated division by 2 as you did to convert decimal to binary.

Let us see how this works. Determine the BCD value for the decimal number 5,319. Since there are four digits in our decimal number, there are four bytes in our BCD number. They are:

Thousands Hundreds Tens Units
5 3 1 9
0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1

Since computer storage requires the minimum of 1 byte, you can see that the upper nibble of each BCD number is wasted storage. BCD is still a weighted position number system so you may perform mathematics, but we must use special techniques in order to obtain a correct answer.


Since storage in RAM is so valuable, we would like to eliminate this wasted storage. This may be accomplished by packing the BCD numbers. In a packed BCD number, each nibble has a weighted position starting from the decimal point. Therefore, instead of requiring 4 bytes to store the BCD number 5319, we would only require 2 bytes, half the storage. The upper nibble of the upper byte of our number would store the THOUSANDS value while the lower nibble of the upper byte would store the HUNDREDS value. Likewise, the lower byte would store the TENS value in the upper nibble and the UNITS digit in the lower nibble. Therefore, our previous example would be:

Thousands - Hundreds Tens - Units
53 19
0 1 0 1 0 0 1 1 0 0 0 1 1 0 0 1

Here is some PBP code to pack 4 digits of BCD data into 2 bytes of memory.  The 4 digits of BCD are stored in the byte variables: BCD1000, BCD100, BCD10, BCD1.  Use the following to pack into the byte variables: PACKED_HIGH and PACKED_LOW.

BCD1000 = $5

BCD100 = $3

BCD10 = $1

BCD1 = $9

PACKED_HIGH = (BCD1000<<4) + BCD100

PACKED_LOW = (BCD10<<4) + BCD1

Converting between Binary and BCD

If you are doing calculations with data that is sent or received in BCD format, you will have to convert to binary in order to get the correct results.  The following example starts with the packed BCD from above (PACKED_HIGH = $53, PACKED_LOW = $19).  The value is converted to binary and stored in the word variable W1, divided by 2, then converted to 4 bytes and stored back in the original BCD variables above.

Conversion with PICBASIC PRO

W1 = ((PACKED_HIGH & $F0)>>4*1000) + ((PACKED_HIGH & $0F)*100)_
    + ((PACKED_LOW & $F0)>>4*10) + (PACKED_LOW & $0F)

W1 = W1 / 2

BCD1000 = W1 DIG 3

BCD100 = W1 DIG 2

BCD10 = W1 DIG 1

BCD1 = W1 DIG 0