Binary to 8Bit dual BCD, AKA 0-99 decimal  - Page 1
Forum section: electronics / general

author: singlarrysong
author_rank: Contributor
timestamp: June 12, 2015, 06:54:54 pm
content: 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 resultwhen 0-7 its normal, then 8 and 9 make the fault value of BCD 88 and 89when 10-17 normal, then 18 to 19 make the fault value of BCD 98 and 99when 20-27 normal, then 28 to 29 give a fault 10101000 and 10101001 which the tents display nothing where because overflow in BCDthe rest I just random test value and get belowat 70s seems still over flow to the tents80 to 00, 85 to 05, 86 to 06 but 88 correct90s 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

author: hamster_nz
author_rank: Super Contributor
timestamp: June 12, 2015, 07:22:37 pm
content: Can you explain what is going here:Code:WriteBCD = tents;WriteBCD = WriteBCD | ((tents >> 1) & 0b01000000); // Surely this is zero?WriteBCD = WriteBCD & 0b01000111; // Mask only bits 6,3,2,1,0andCode:WriteBCD = unit <<3; // Multiply unit by 8WriteBCD = WriteBCD | (0b00000111 & unit); // OR back in the the original number & 0x7WriteBCD = WriteBCD & 0b01000111; // Mask only bits 3,2,1,0Because 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 likeCode: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

author: singlarrysong
author_rank: Contributor
timestamp: June 12, 2015, 08:29:14 pm
content: thanks a lot for your suggestion.first code you quotedWriteBCD = tents;WriteBCD = WriteBCD | ((tents >> 1) & 0b01000000); // Surely this is zero?WriteBCD = WriteBCD & 0b01000111; // Mask only bits 6,3,2,1,0line two--- I just saw the mistake, it should be same as the unitline three --- mask only bit 6, 2, 1, 0 that rightfor the code 2nd you quotedline 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, 8918, 19 to 98, 99starting 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 rightand at 90s, 90-97 to 10-17 and 98, 99 were right.Code: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!

author: hamster_nz
author_rank: Super Contributor
timestamp: June 12, 2015, 11:32:13 pm
content: 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: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 thisQuoteIt 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?

author: 22swg
author_rank: Frequent Contributor
timestamp: June 13, 2015, 08:50:50 am
content: For what its worth...Code: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 10BCD1 = (INT_val % 10);BCD1 = BCD1 << 4;BCD1 = (BCD1 | BCD0);return BCD1;}

author: singlarrysong
author_rank: Contributor
timestamp: June 13, 2015, 09:59:41 am
content: @hamster_nz, the port is correctly tie@22swg I improved the code by using %but what happen now areno matter what it stop at 8 and at 9 it display 89 19 29... 99 it just display 08 18 28... 88similar to 90s it just display 80 to 88 again where 99 become 88, as well as 89 displayed 88Code:char x = 0;void BCDout(char value){char tens = value/10;//get the tenschar units = value % 10;//get the remainder after divide by 10char WriteBCD = 0;if(x == 0xFF)//tens{PORTA = tens & 0b0111;//only write 3 LSB of the BCDif(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 BCDif(units >= 0b111)//if units is greather than 7{PORTA = PORTA | 0b01000000;//Set RA6 regardless other bits}RB1 = x;x = 0xFF;}}}

author: Andy Watson
author_rank: Super Contributor
timestamp: June 13, 2015, 10:30:39 am
content: Surely it has reached the point where a table would be more economic (unless you like bit wrangling). Something like:Code:char BCD_Map = { 0b01000000, 0b01000001, 0b01000010, , etc }; // I'll let you fill in the detailsvoid BCDout(char value){char tents = value/10;char unit = value - (tent*10);x++;if(0x01 & x){PORTA = BCD_Map;RB1 = x;}else{PORTA = BCD_Map;RB1 = x;}}

author: hamster_nz
author_rank: Super Contributor
timestamp: June 13, 2015, 10:52:24 am
content: 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 whathttp://www.ti.com/lit/ds/symlink/cd4511b.pdfsays...

author: singlarrysong
author_rank: Contributor
timestamp: June 13, 2015, 11:56:29 am
content: Nope, all hardware connection is good.I had successfully debugged it!!hopefully when every system is up it wouldn't have any potential bug showingthanks everyone here, hopefully this forum help to other who need this as wellConvert binary 0000 0000 (decimal 0) to 0110 0011 (decimal 99) to 1 byte double BCDsCode:void BCDout(char value){char units = value % 10;//get the remainder after divide by 10char tens = (value-units)/10;//get the tenschar WriteBCD = 0;if(x == 1)//tens{WriteBCD = tens & 0b0111;//only write 3 LSB of the BCDif(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 BCDif(units > 7)//if units is greather than 7{WriteBCD = WriteBCD | 0b01000000;//Set RA6 regardless other bits}PORTA = WriteBCD;RB1 = x;x = 1;}}}