Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Comparing bcd values

Status
Not open for further replies.

dr pepper

Well-Known Member
Most Helpful Member
I need to compare a 3 digit unpacked bcd value against another 3 digit unpacked value.
I always seem to struggle with an efficient way to do this.
Any advice or links welcome.
 
Pack 'em, then compare -

Code:
unsigned char dig1;

unsigned char dig2;

unsigned char dig3;

unsigned char dig4;

unsigned char dig5;

unsigned char dig6;

unsigned int bcdval1 = (100 * dig1) + (10 * dig2) + dig3;

unsigned int bcdval2 = (100 * dig4) + (10 * dig5) + dig6;

if(bcdval1 == bcdval2)
{
    doThis();
}
else
{
    doThat();
}
 
Last edited:
Sorry I should hve said I code in asm, however I could convert to hex, but that wouldnt be very efficient.
 
I could convert to hex, but that wouldnt be very efficient.
Sorry, I am a bit drunk because It is my birthday, but still, this does not make much sense.. Do you mean converting the BCD value to ASCII hex? .. yes that is inefficient. Actually not very inefficient, but you would not gain anything.
 
Last edited:
Compare equal probably would not be that difficult:

Pseudocode

Set EQUAL bit to TRUE; Assume TRUE
Compare MSD1a equal to MSD1b; AND result to EQUAL bit
Compare MSD2a equal to MSD2b; AND result to EQUAL bit
Compare LSD3a equal to LSD3b; AND result to EQUAL bit

If EQUAL bit = TRUE then they are equal.
Sometimes you can use the carry bit.
 
This is what I did,

Code:
;
fon        movf fastens,w
          subwf tens,w
          skpnc
          goto nx10
        goto    laps1
 
;    
nx10    movf fasones,w
          subwf ones,w
          skpnc
          goto nx20
        goto    laps1
 
;    
nx20     movf fastenths,w
          subwf tenths,w
          skpnc
          return
;

The code returns if tens,ones,tenths is > fatens,fasones,fastenths, carries on executing (to laps1) if the opposite.
The odd thing is that its erratic, sometimes is acts as though its less tha than when higher than, particularly when the values are less than 100.
 
When checking for < or > than, you have to check the MSD for <= and >=; Only the last test needs to check < and >.

Take 020 and 021

If 0<=0, you have to test 0<=2. The last test has to test 0<1. If any of the tests fail, your done.
 
At each step there are three possibilities (not two!):

A > B : you exit with ">" result
A < B : you exit with "<" result
A = B : only then you test the next digit or exit with "=" result if it's the last digit.
 
Thanks, I get I'm incorrect.
However I still dont quite get it, I'm not understanding how to implement the >= bit.

Edit: I think I might get it, your saying do tests for < > and = on each digit, starting with the 100's, if the outcome is > then thats your answer, if the outcome is = or < then test 10's and then 1's and if one of them turns out > then the answer is >, or if you get to 1's digit whatever the outcome <> or = is the answer.
 
Last edited:
If the first digit is greater (MSD) than the outcome is greater. If the first digit (MSD) is less, the outcome is less. If it's equal, you have more work to do. e.g 1xxx vs 2xxx

Sometimes you can use the stack for a temporary place to store something or a memory location, You can end up with 3 bits (condition codes) when your done. Less, Greater, Equal.

So, you could pass the three locations of the BCD digits, or the digits themselves on the stack and return the result on the stack. Just depends if you can afford the extra overhead.
 
Last edited:
... if the outcome is = or < then test 10's and then 1's.

Nope. If outcome is "=" you look at 10's. If outcome is "<" you don't look at 10's, but exit with "<" result.

Say 499 and 500. If you see 4 < 5, you stop right there and do not compare 9 to 0 as this will give you a wrong result.
 
Klunk - penny's dropped, I got it.

First check msd, if < or > thats the answer bomb out, if = then do again for msd-1 if < or > then thats the answer bomb out, if = then do again for lsd if < or > thats the answer bomb out, if = they are the same.

Looking back at my code I need to add some extra to detect < and bomb out if thats the case, the code does drop through to the next digit if one is = the other but doesnt look at one being < the other, this probably explains why it only messes up sometimes, ie when one digit is < the other.

I really want to get cracking with the code right now, but I just started a long nightshift and I have some large greasy bearings to pull and replace.
 
Heres my modded code, havent tried it yet, I just did this at work:

Code:
faslap        movf    fastens,w
        subwf    tens,w
        btfsc    status,z
        goto    nx10        ;tens are = so goto check ones
;   
        movf fastens,w
          subwf tens,w
          skpnc
          return            ;current laptime > fastest lap bomb out
        goto    laps1        ;current laptime < fastest lap beep & rec
;           
nx10        movf    fasones,w
        subwf    ones,w
        btfsc    status,z
        goto    nx20        ;ones are = so goto check tenths
;       
        movf fasones,w
          subwf ones,w
          skpnc
          return            ;current laptime > fastest lap bomb out
        goto    laps1        ;current laptime < fastest lap beep & rec

;       
nx20         movf fastenths,w
          subwf tenths,w
          skpnc
          return            ;current laptime > fastest lap bomb out
;
laps1        movlw    d'3'        ;beep for 5 1/10's of a sec on new record
        movwf    beeptime
        bsf    porta,1
;

I check for the tens, ones and tenths being equal first if they are the next lower digit is tested, if not I check for < & >, higher than just bombs out and lower than turns the o/p port bit on which activates a beeper for a set time.
 
You do not need to repeat movf/subwf twice. After you did it the first time, flags still will be there, so you can do skipnc without repeating movf/subwf.
 
Yes well spotted, I could also use skpnz.
That then gives me fast efficient code, exactly what I wanted.

Happy hangover Mr. T.

Just for clarity:

Code:
faslap        movf    fastens,w
        subwf    tens,w
        skpnz
        goto    nx10        ;tens are = so goto check ones
;   
          skpnc
          return            ;current laptime > fastest lap bomb out
        goto    laps1        ;current laptime < fastest lap beep & rec
;           
nx10        movf    fasones,w
        subwf    ones,w
        skpnz
        goto    nx20        ;ones are = so goto check tenths
;       
          skpnc
          return            ;current laptime > fastest lap bomb out
        goto    laps1        ;current laptime < fastest lap beep & rec

;       
nx20         movf fastenths,w
          subwf tenths,w
          skpnc
          return            ;current laptime > fastest lap bomb out
;
laps1        movlw    d'3'        ;beep for 5 1/10's of a sec on new record
        movwf    beeptime
        bsf    porta,1
;
 
Thanks for your help guys, now working as expected.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top