Converting decimal to BCD

MarineUTEP picture MarineUTEP · Feb 12, 2016 · Viewed 10.4k times · Source

I'm working on an assignment currently that uses a microcontroller and a circuit to display a decimal in binary, through LED's. I have to use three push buttons: one to increment, one to decrement, and the last to reset. I have my wiring and configuration complete. My code on the other hand has some glitches that I cannot fix with only an intro to C class under my belt. I am using Code Composer. Problem number one: My counter on the "Tens" section(MSB) does not stop at 9 but rather begins to display binary 10-15. The first four bits are the ones(right) and the second four bits, tens(left) ex: 1010 0001 but the max value is 1001 1001. Problem number two: starting from zero if I decrement the value, the counter displays 95 rather than 99. ex: starting from 0000 0000 decrement displays 1001 0101. I tried using an if statement to make a condition for MSB to stop if greater than ten but the code doesn't run. Pretty much any modification I did to my code prevents it from working properly.

#include <msp430.h>

unsigned int dec2bcd(unsigned int num);
void delay(void);

int main(void) {
WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

P1DIR = 0xFF;
P2DIR = 0xF0;
unsigned int c;
unsigned int count = 0x00;

while(1){
    if((P2IN & BIT0) == BIT0){
        count++;
        c = dec2bcd(count);
    }

    else if((P2IN&BIT1) == BIT1){
        count--;
        c = dec2bcd(count);
    }

    else if((P2IN&BIT2) == BIT2){
        count = 0x00;
        c = dec2bcd(count);
    }

    delay();
    P1OUT = c;

}

}

unsigned int dec2bcd(unsigned int num)
{
    unsigned int ones = 0;
    unsigned int tens = 0;
    unsigned int temp = 0;

    ones = num%10;
    temp = num/10;
    tens = temp<<4;
    return (tens + ones);
}

void delay(void)
{
    volatile unsigned int i, j;
    for(i=10000; i>0; i--)
    {
        for(j=3; j>0; j--){
    }
}
}

Answer

Weather Vane picture Weather Vane · Feb 12, 2016

I don't have a strip of LEDs handy right now, but this shows how to work within a decimal range, but only convert at the point of output. The actual value is kept in the range 0..99 (note how the modulus is done when I decrement). Then you split the value into BCD nibbles, and combine them for output.

#include <stdio.h>

void display(int num, char *msg)
{
    int lsnib = num % 10;                        // decimal value of each nibble
    int msnib = num / 10;
    int ledpatt = (msnib << 4) + lsnib;          // recombine as BCD
    printf("%02X Expected %s\n", ledpatt, msg);
}

int main(void){
    int value;

    value = 42;
    display (value, "forty two");       // display 42

    value = 0;
    display (value, "zero");            // display 0

    value = 99;
    display (value, "ninety nine");     // display 99

    value = (value + 1) % 100;          // increment from 99
    display (value, "zero");            // should display 0

    value = (value -1 + 100) % 100;     // decrement from 0
    display (value, "ninety nine");     // should display 99

    return 0;
}

Program output

42 Expected forty two
00 Expected zero
99 Expected ninety nine
00 Expected zero
99 Expected ninety nine