EEVblog® Electronics Community Forum
Electronics => Microcontrollers => Topic started by: singlarrysong 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
-
Can you explain what is going here:
WriteBCD = tents;
WriteBCD = WriteBCD | ((tents >> 1) & 0b01000000); // Surely this is zero?
WriteBCD = WriteBCD & 0b01000111; // Mask only bits 6,3,2,1,0
and
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
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 :)
-
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.
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
-
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.
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
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?
-
For what its worth...
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;
}
-
@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
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;
}
}
}
-
Surely it has reached the point where a table would be more economic (unless you like bit wrangling). Something like:
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;
}
}
-
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 (http://www.ti.com/lit/ds/symlink/cd4511b.pdf) says...
-
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
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;
}
}
}