1

This question is derived from my previous SO question's commends.

I am confused with PLC's interpretation of BCD and decimal. In a PLC documentation, it somehow implies BCD = decimal:

enter image description here

The instruction reads the content of D300, 0100, as BCD. Referring to Cyber Slueth Omega's answer and online BCD-Hex converter, 0100 (BCD) = 4 (Decimal) = 4 (Hex), but the documentation indicates 0100 (BCD) = 100 (Decimal).

Why?

Community
  • 1
  • 1
KMC
  • 19,548
  • 58
  • 164
  • 253
  • 0100 becomes 4 if interpreted as *bits*. 0100 becomes 100 if interpreted as *nibbles*, same as 0000 0001 0000 0000 in bits. – Hans Passant Feb 21 '12 at 13:25

2 Answers2

2

Binary-coded decimal is encoded as hex digits that have a limited range of 0-9. This means that 0x0100 should be read as 100 when BCD is meant. Numbers with hexadecimal digits from A to F are not valid BCD numbers.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • This was my question: First, 0100 (Hex) = 256 (decimal) = 000100000000 (binary). Converting 256 (Decimal) back to BCD gets me 0010 0101 0110. Second, the pointer to the content 0100 is of type BCD, so I should take 0100 as BCD directly instead of hex, and 0100 BCD = 4 (decimal) – KMC Feb 21 '12 at 10:51
  • But 0100 (hex) = 256 (decimal). And 256 (decimal) != 100 (BCD). My brain hurts – KMC Feb 21 '12 at 10:55
2
  • BCD is HEX
  • BCD is not binary
  • HEX is not binary
  • BCD and HEX are representations of binary information.

The only difference is in how you decide to interpret the numbers. Some PLC instructions will take a piece of word memory and will tell you that "I, the TIM instruction, promise to treat the raw data in D300 as BCD data". It is still HEX data, but it interprets it differently.

If D300 = [x2486] --> the timer (as example) will wait 248.6 seconds. This even though HEX 2486 = 9350 decimal. You can treat hex data as anything. If you treat hex data as encoded BCD you get one answer. If you treat it as a plain unsigned binary number you get another, etc.

If D300 = [x1A3D] --> TIM will throw an error flag because D300 contains non-BCD hex digits

Further, the above example is showing HEX digits - not BINARY digits. It is confusing because they chose [x0100] as their example - only zeroes and ones. When you are plugging this into your online converter you are doing it wrong - you are converting binary 0100 to decimal 4. Hexadecimal is not binary - hex is a base16 representation of binary.

Anatomy of a D-memory location is this

16 Bits     | xxxx | xxxx | xxxx | xxxx |  /BINARY/
   --->        |      |      |      |
4 bits/digit   D4     D3     D2     D1     /HEX/

example 
D300 = 1234 | 0001 | 0010 | 0011 | 0100 |
   ---->       1      2      3       4

example 
D300 = 2F6B | 0010 | 1111 | 0110 | 1011 |
   ---->       2      F      6       B

example (OP!)
D300 = 0100 | 0000 | 0001 | 0000 | 0000 |
   ---->       0      1      0       0

A D-memory location can store values from x0000 -> xFFFF (decimal 0-65535). A D-memory location which is used to store BCD values, however, can only use decimal digits. A->F are not allowed. This reduces the range of a 16-bit memory location to 0000->9999.

Counting up you would go :

Decimal    BCD      HEX
1         0001      0001
2         0002      0002     
3         0003      0003
4         0004      0004
5         0005      0005
6         0006      0006
7         0007      0007
8         0008      0008
9         0009      0009
10        0010      000A
11        0011      000B
12        0012      000C
13        0013      000D
14        0014      000E
15        0015      000F
16        0016      0010
17        0017      0011
18        0018      0012
19        0019      0013
20        0020      0014
...etc

Going the other way, if you wish to pass a decimal value to a memory location and have it stored as pure hex (not BCD hex!) you use the '&' symbol.

For example -> [MOV #123 D300]

This moves HEX value x0123 to memory location D300. If you use D300 in a future operation which interprets this as a hexadecimal number then it will have a decimal value of 291. If you use it in an instruction which interprets it as a BCD value then it will have a decimal value of 123.

If instead you do [MOV &123 D300]

This moves the decimal value 123 to D300 and stores it as a hexadecimal number -> [x007B]! If you use D300 now in a future operation which interprets this as a hexadecimal number it will have a decimal value of 123. If you try to use it in an instruction which interprets it as a BCD value you will get an ERROR because [x007B] contains the hex digit 'B' which is not a valid BCD digit.

J...
  • 30,968
  • 6
  • 66
  • 143
  • Word address in PLC are decimal. The 300 in D300 is decimal, so is 100 in D100. How did 0100 (BCD) end up to be the same 100 (decimal)? Is BCD also is decimal? So BCD = Hex = decimal? – KMC Feb 21 '12 at 11:21
  • Yes. BCD is 'binary coded decimal' - a way of using bin/hex numbers to represent binary numbers. The only, only, only purpose of BCD is to make hex numbers more human-readable. Instead of the decimal number 100 being encoded to pure hex as [x0064] it gets encoded as [x0100]. That way, when you stare at the number in a register you can instantly recognize its value as 100 instead of having to calculate it. If you want a timer for 3 seconds, you pop [x0030] into a 100ms BCD timer and save having to calculate it into [x001E] for a hex based timer. – J... Feb 21 '12 at 11:54
  • ^ sorry - first line edit: "...to represent *decimal* numbers" – J... Feb 21 '12 at 12:20