Author Topic: Binary to 8Bit dual BCD, AKA 0-99 decimal  (Read 3650 times)

0 Members and 1 Guest are viewing this topic.

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Binary to 8Bit dual BCD, AKA 0-99 decimal
« on: June 12, 2015, 06:54:54 pm »
Ignore the output pins assignment because I need multiplex it to a CMOS 4511 BCD to 7-seg chip.

I test it with putting value into the char value and below are some of the result
when 0-7 its normal, then 8 and 9 make the fault value of BCD 88 and 89
when 10-17 normal, then 18 to 19 make the fault value of BCD 98 and 99
when 20-27 normal, then 28 to 29 give a fault 10101000 and 10101001 which the tents display nothing where because overflow in BCD
the rest I just random test value and get below
at 70s seems still over flow to the tents
80 to 00, 85 to 05, 86 to 06 but 88 correct
90s number the tents become 1 and correct at unit, where only 98 is correct.

void BCDout(char value)
{
   char tents = value/10;
   char unit = value - (tents*10);
   char WriteBCD = 0;
   x++;
   if(0x01 & x)
   {   
      WriteBCD = tents;
      WriteBCD = WriteBCD | ((tents >> 1) & 0b01000000);
      WriteBCD = WriteBCD & 0b01000111;
      PORTA = PORTA | WriteBCD;
      RB1 = x;
   }
   else
   {
      WriteBCD = unit <<3;
      WriteBCD = WriteBCD | (0b00000111 & unit);
      WriteBCD = WriteBCD & 0b01000111;
      PORTA = PORTA | WriteBCD;
      RB1 = x;
   }
}

anyone have any idea? thanks
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #1 on: June 12, 2015, 07:22:37 pm »
Can you explain what is going here:
Code: [Select]
      WriteBCD = tents;
      WriteBCD = WriteBCD | ((tents >> 1) & 0b01000000); // Surely this is zero?
      WriteBCD = WriteBCD & 0b01000111; // Mask only bits 6,3,2,1,0

and

Code: [Select]
      WriteBCD = unit <<3;  // Multiply unit by 8
      WriteBCD = WriteBCD | (0b00000111 & unit);  // OR back in the the original number & 0x7
      WriteBCD = WriteBCD & 0b01000111;  // Mask only bits 3,2,1,0

Because I can't! And you never actually clear the bits, you just keep ORing new values in, never removing the old ones...

Oh! Are you using bits 6, 2,1 and 0 on port A?

In which case it should be something like
Code: [Select]
      WriteBCD = unit & 0b00000111;
      if(unit & 0b00001000)
          WriteBCD +=  0b01000000;
      PORTA = (PORTA & 0x10111000) | WriteBCD;

And the same for 'tents'

And of course I haven't tested the code :)
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #2 on: June 12, 2015, 08:29:14 pm »
thanks a lot for your suggestion.  :)

first code you quoted

      WriteBCD = tents;
      WriteBCD = WriteBCD | ((tents >> 1) & 0b01000000); // Surely this is zero?
      WriteBCD = WriteBCD & 0b01000111; // Mask only bits 6,3,2,1,0

line two--- I just saw the mistake, it should be same as the unit
line three --- mask only bit 6, 2, 1, 0 that right

for the code 2nd you quoted
line 2 ---  during the next loop when condition is false, it flow through this code, so the WriteBCD is cleared before the decision ask.

now here is the new thang, with your code.
8, 9 to 88, 89
18, 19 to 98, 99
starting 20s to 70s, when the units are 8 or 9 it overflow give the result,
-8 and -9 on 28 29 38 39 48 49 58 59 68 69 78 and 79
- means overflow(1010 to 1111)

but at 80s, 80-87 to 00-07 then 88, 89 were right
and at 90s, 90-97 to 10-17 and 98, 99 were right.

Code: [Select]
void BCDout(char value)
{
char tens = value/10;
char unit = value - (tens*10);

char WriteBCD = 0;
x = ~x;
if(x == 0xFF) //tens
{
WriteBCD = tens & 0b00000111;
if(unit & 0b00001000)
{
WriteBCD +=  0b01000000;
}
PORTA = (PORTA & 0x10111000) | WriteBCD;
RB1 = x;
}
else
{
WriteBCD = unit & 0b00000111;
if(unit & 0b00001000)
{
WriteBCD +=  0b01000000;
}
PORTA = (PORTA & 0x10111000) | WriteBCD;
RB1 = x;
}
}

I realize I spell tens wrongly so corrected!  ;D
« Last Edit: June 12, 2015, 08:33:50 pm by singlarrysong »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #3 on: June 12, 2015, 11:32:13 pm »
So it looks like your pins are not wired as I assumed. Try displaying just 0,1,2,4 and 8. That will shows anything sensible.

In the end you might be forced to rewrite it something like this, which allows you to put the bits of the BCD digit on any pin of the same port.

Code: [Select]
void BCDout(char value)
{
char tens = value/10;
char unit = value - (tens*10);
        char digit;
char WriteBCD = 0;

x = ~x;
if(x == 0xFF) {
            digit = tens;
        } else {
            digit = unit;
        };

        WriteBCD = 0;
if(digit & 0b00001000) WriteBCD +=  0b01000000; 
if(digit & 0b00000100) WriteBCD +=  0b00000100; 
if(digit & 0b00000010) WriteBCD +=  0b00000010; 
if(digit & 0b00000001) WriteBCD +=  0b00000001;

        PORTA = (PORTA & 0x10111000) | WriteBCD;
RB1 = x;
}

What would really help with the debugging would be a list of what input digits show what outputs, and also for initial debugging of the display only attempt to show the 'unit' digit....

And looking through this
Quote
8, 9 to 88, 89
18, 19 to 98, 99
starting 20s to 70s, when the units are 8 or 9 it overflow give the result,
-8 and -9 on 28 29 38 39 48 49 58 59 68 69 78 and 79
- means overflow(1010 to 1111)

It looks like your '8' line on your display driver is stuck high - is it really connected to pin 6 on the port A? Have you set the Port A data direction register correctly?
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline 22swg

  • Frequent Contributor
  • **
  • Posts: 274
  • Country: gb
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #4 on: June 13, 2015, 08:50:50 am »
For what its worth...
Code: [Select]
unsigned int HEX2BCD(unsigned int INT_val)   // CONVERTS int HEX to BCD
{
     unsigned int BCD0,BCD1;
     BCD0 = (INT_val % 10);
     INT_val = INT_val / 10;       // divide by 10
     BCD1 = (INT_val % 10);
     BCD1 = BCD1 << 4;
     BCD1 = (BCD1 | BCD0);
     return BCD1;
}
Check your tongue, your belly and your lust. Better to enjoy someone else’s madness.
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #5 on: June 13, 2015, 09:59:41 am »
@hamster_nz, the port is correctly tie  :)
@22swg I improved the code by using %
but what happen now are
no matter what it stop at 8 and at 9 it display 8
9 19 29... 99 it just display 08 18 28... 88
similar to 90s it just display 80 to 88 again where 99 become 88, as well as 89 displayed 88

Code: [Select]
char x = 0;
void BCDout(char value)
{
char tens = value/10; //get the tens
char units = value % 10; //get the remainder after divide by 10
char WriteBCD = 0;

if(x == 0xFF) //tens
{
PORTA = tens & 0b0111; //only write 3 LSB of the BCD
if(tens > 0b111) //if tens is greather than 7
{
PORTA = PORTA | 0b01000000; //Set RA6 regardless other bits
}

RB1 = x;
x = 0x00;
}
else //multiplex to another register
{
if(x == 0x00)
{
PORTA = units & 0b0111; //only write 3 LSB of the BCD
if(units >= 0b111) //if units is greather than 7
{
PORTA = PORTA | 0b01000000; //Set RA6 regardless other bits
}

RB1 = x;
x = 0xFF;
}
}
}
 

Offline Andy Watson

  • Super Contributor
  • ***
  • Posts: 2085
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #6 on: June 13, 2015, 10:30:39 am »
Surely it has reached the point where a table would be more economic (unless you like bit wrangling). Something like:

Code: [Select]

char BCD_Map[10] = { 0b01000000, 0b01000001, 0b01000010, , etc };  // I'll let you fill in the details

void BCDout(char value)
{
   char tents = value/10;
   char unit = value - (tent*10);
 
   x++;
   if(0x01 & x)
   {   
     PORTA = BCD_Map[tens];
      RB1 = x;
   }
   else
   {
       PORTA = BCD_Map[unit];
      RB1 = x;
   }
}
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #7 on: June 13, 2015, 10:52:24 am »
Are you really sure that the bit3 output is hooked only up to the 'D' input (pin 6) on the chip?

If it was accidentally hooked / or shorted to the Lamp test (pin 3) or Latch Enable (pin 5) it might display unexpected '8's - or at least that is what http://www.ti.com/lit/ds/symlink/cd4511b.pdf says...
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: Binary to 8Bit dual BCD, AKA 0-99 decimal
« Reply #8 on: June 13, 2015, 11:56:29 am »
Nope, all hardware connection is good.
I had successfully debugged it!!  :-+

hopefully when every system is up it wouldn't have any potential bug showing :)

thanks everyone here, hopefully this forum help to other who need this as well

Convert binary 0000 0000 (decimal 0) to 0110 0011 (decimal 99) to 1 byte double BCDs

Code: [Select]
void BCDout(char value)
{
char units = value % 10; //get the remainder after divide by 10
char tens = (value-units)/10; //get the tens
char WriteBCD = 0;

if(x == 1) //tens
{
WriteBCD = tens & 0b0111; //only write 3 LSB of the BCD
if(tens > 7) //if tens is greather than 7
{
WriteBCD = WriteBCD | 0b01000000; //Set RA6 regardless other bits
}
PORTA = WriteBCD;
RB1 = x;
x = 0;
}
else //multiplex to another register
{
if(x == 0)
{
WriteBCD = units & 0b0111; //only write 3 LSB of the BCD
if(units > 7) //if units is greather than 7
{
WriteBCD = WriteBCD | 0b01000000; //Set RA6 regardless other bits
}
PORTA = WriteBCD;
RB1 = x;
x = 1;
}
}
}
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf