|
|
View previous topic :: View next topic |
Author |
Message |
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
16 bit binary to bcd C++ conversion program |
Posted: Wed Dec 27, 2006 5:01 am |
|
|
After a week of not haveing a working program so I ask here.
Need a C++ pgm for the CCS compiler of a 16bit binary to 5 BCD routine.
I am using a 18F4580 20 MHz, have 50% pgm. mem left.
As in 7th decade don't need to spend more time in frustration trying.
Thank You
Tom |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 27, 2006 12:56 pm |
|
|
The answer is in the forum archives. Go to the search page, here:
http://www.ccsinfo.com/forum/search.php
Type in these keywords: binary BCD
Then set it to "Search for all terms" and click the Search button.
Also search for this keyword: bin2bcd
-------
The CCS compiler is not C++. It's just C. |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
16 bit binary to bcd C++ conversion or 16 bin to 5 bcd |
Posted: Wed Dec 27, 2006 3:00 pm |
|
|
PCM programmer wrote: | The answer is in the forum archives. Go to the search page, here:
http://www.ccsinfo.com/forum/search.php
Type in these keywords: binary BCD
Then set it to "Search for all terms" and click the Search button.
Also search for this keyword: bin2bcd
-------
The CCS compiler is not C++. It's just C. |
Thanks for the answer, BUT have tried that routine, it is 8 bit binary conversion to 2 byts BCD, resule is not what is needed,
what am asking for is a routine that use a LONG (16) bit binary to produce the result of 5 bytes BCD.
I am not that great of a programmer and it eludes me how to do the 16 binary to 5 byte BCD.
Here is a sample of what I now need to do Also bin to BCD of x .
void NEWbinary_MATH (float az, float el)
{
long bin, x;
// VK3UM is "0" to "F" or HEX DATA 12/26/06
x = bin = tobinary (az); // do binary math
AZCountMSB = bin >> 8; // make ready to send out
AZCountLSB = bin & 0xff; // make ready to
Thanks for some help
tom |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 27, 2006 3:24 pm |
|
|
But if you did the first search that I suggested, you will find Humberto's
code in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=25835&highlight=binary+bcd
He doesn't pack the results. Each BCD digit is stored in a 16-bit
global variable. But it does work, as the test program below shows.
Code: | #include <18F452.h>
#fuses XT, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
long Dig_0, Dig_1, Dig_2, Dig_3, Dig_4;
void bin_to_Dig(long bin_inp)
{
long temp;
temp = bin_inp;
Dig_4 = temp/10000;
temp = temp - (Dig_4 * 10000);
Dig_3 = temp/1000;
temp = temp - (Dig_3 * 1000);
Dig_2 = temp/100;
temp = temp - (Dig_2 * 100);
Dig_1 = temp/10;
temp = temp - (Dig_1 * 10);
Dig_0 = temp;
}
//============================
void main()
{
bin_to_dig(0x7E);
printf("%ld%ld%ld%ld%ld\n\r", Dig_4, Dig_3, Dig_2, Dig_1, Dig_0);
bin_to_dig(0x8000);
printf("%ld%ld%ld%ld%ld\n\r", Dig_4, Dig_3, Dig_2, Dig_1, Dig_0);
bin_to_dig(0xFFFF);
printf("%ld%ld%ld%ld%ld\n\r", Dig_4, Dig_3, Dig_2, Dig_1, Dig_0);
while(1);
} |
|
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
|
Posted: Wed Dec 27, 2006 3:38 pm |
|
|
PCM programmer wrote: | But if you did the first search that I suggested, you will find Humberto's
code in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=25835&highlight=binary+bcd
He doesn't pack the results. Each BCD digit is stored in a 16-bit
global variable. But it does work, as the test program below shows.
Code: | #include <18F452.h>
#fuses XT, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
long Dig_0, Dig_1, Dig_2, Dig_3, Dig_4;
void bin_to_Dig(long bin_inp)
{
long temp;
temp = bin_inp;
Dig_4 = temp/10000;
temp = temp - (Dig_4 * 10000);
Dig_3 = temp/1000;
temp = temp - (Dig_3 * 1000);
Dig_2 = temp/100;
temp = temp - (Dig_2 * 100);
Dig_1 = temp/10;
temp = temp - (Dig_1 * 10);
Dig_0 = temp;
}
//============================
void main()
{
bin_to_dig(0x7E);
printf("%ld%ld%ld%ld%ld\n\r", Dig_4, Dig_3, Dig_2, Dig_1, Dig_0);
bin_to_dig(0x8000);
printf("%ld%ld%ld%ld%ld\n\r", Dig_4, Dig_3, Dig_2, Dig_1, Dig_0);
bin_to_dig(0xFFFF);
printf("%ld%ld%ld%ld%ld\n\r", Dig_4, Dig_3, Dig_2, Dig_1, Dig_0);
while(1);
} |
|
Hmmmm,
I had looked at that code several days ago but did not try it??? wo be me....
Thanks, hope this is the answer to the problem.
Will add that routine and see how all works when finished.
Thank You much,
tom |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
|
Posted: Fri Dec 29, 2006 5:40 am |
|
|
Hi,
Wish to thank for the help here.
It was of great help.
So I am posting the code results if it would be of help to others.
Thank You
tom
Code: |
long Dig_0, Dig_1, Dig_2, Dig_3, Dig_4;
void bin_to_Dig(long bin_inp)
{ // This is for VK3UM program
long temp; // 16 bit binary to BCD 5 byte
int nibh;
int nibl;
temp = bin_inp / 18.2041667; // make into binary degrees value
Dig_4 = temp/10000;
temp = temp - (Dig_4 * 10000);
Dig_3 = temp/1000;
temp = temp - (Dig_3 * 1000);
Dig_2 = temp/100;
temp = temp - (Dig_2 * 100);
nibh = Dig_3;
nibl = Dig_2;
CountMSB = (nibl|(nibh<<4));
Dig_1 = temp/10;
temp = temp - (Dig_1 * 10);
Dig_0 = temp;
nibh = Dig_1; // MSB BYTE make ready to send out This is the 2nd digit
nibl = Dig_2; // LSB BYTE make ready to send out This is the 1st digit
CountMSB = (nibl|(nibh<<4));
nibh = Dig_3; // MSB BYTE make ready to send out This is the 3rd digit
nibl = Dig_0; // LSB BYTE make ready to send out is .1 value
CountLSB = (nibl|(nibh<<4));
} |
|
|
|
Ttelmah Guest
|
|
Posted: Fri Dec 29, 2006 8:52 am |
|
|
As an 'aside', to anyone looking at this, there is a much more efficient algorithm available. The problem is that division, takes a lot of work. Performing the five divisions, and five multiplications involved in the simple algorithm posted, uses perhaps the best part of 2000 instruction cycles, even on a PIC18. On chips without the hardware multiplier, the time goes up by perhaps another 500 cycles. the alternative, produces 'packed' BCD (where the digits are returned 2 to the byte), and just for information, a simple version is posted here:
Code: |
void toBCD(int16 val,int8 * buff) {
//converts 16bit value, to five BCD digits. Tries to do it fairly
//efficiently, both in size, and speed.
int1 temp_bit;
int8 nibctr;
buff[0]=buff[1]=buff[2]=0;
do {
if ((buff[0] & 0xF)>=5) buff[0]+=3;
if ((buff[0] & 0xF0)>=0x50) buff[0]+=0X30;
if ((buff[1] & 0xF)>=5) buff[1]+=3;
if ((buff[1] & 0xF0)>=0x50) buff[1]+=0X30;
if ((buff[2] & 0xF)>=5) buff[2]+=3;
temp_bit=shift_left(&val,2,0);
shift_left(buff,3,temp_bit);
} while (val!=0);
}
void main() {
int16 val;
//three bytes for packed BCD result
int8 buff[3];
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
val=12345;
toBCD(val,buff);
//At this point, the three bytes will contain:
// 45
// 23
// 01
while (true);
}
|
This approach produces the 'packed' bytes, required b many devices, and only uses about 100 instructions (depends on the processor), executing in about 1000 cycles.
Best Wishes |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
|
Posted: Fri Dec 29, 2006 5:36 pm |
|
|
Hi to whom ever on the fast BCD program posted,
The progam posted as "better",
I can not make it run witout crashing the PICC
after it does several new conversions.
As I said in the earler post on this subject of BCD,
Im not the most swift programmer going.
At this time in life don't expect to become much better,
but I'll try with a bit of help.
So a bit of explaining in the remarks as to what is occuring in the programm would be nice.
the 3 buffers being used, I understand that the result shoud be:
buffer 0 is least nibble #1 on the right, left nibble is #2
buffer 1 is #3 right, #4 is left
buffer is most signifant #5 nibble to the right.
Thank You,
tom |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
|
Posted: Sat Dec 30, 2006 3:46 am |
|
|
Hi,
Just realized that the I/O rtn is not normal results for the byte output!!
This is do a requirement of the outside software program.
Here is the "special" output of the low 4 digits in the special mode I use:
Code: |
nibh = Dig_1; // MSB BYTE make ready to send out This is the 2nd digit
nibl = Dig_2; // LSB BYTE make ready to send out This is the 1st digit
CountMSB = (nibl|(nibh<<4));
nibh = Dig_3; // MSB BYTE make ready to send out This is the 3rd digit
nibl = Dig_0; // LSB BYTE make ready to send out is .1 value
CountLSB = (nibl|(nibh<<4)); |
Here is the "normal" output of the low 4 digits in the normal mode:
Code: |
nibh = Dig_1; // MSB BYTE make ready to send out This is the 2nd digit
nibl = Dig_0; // LSB BYTE make ready to send out This is the 1st digit
CountMSB = (nibl|(nibh<<4));
nibh = Dig_3; // MSB BYTE make ready to send out This is the 3rd digit
nibl = Dig_2; // LSB BYTE make ready to send out is .1 value
CountLSB = (nibl|(nibh<<4)); |
tom |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
16 bit BCD BYTE output "normal" this is the correc |
Posted: Sat Dec 30, 2006 3:54 am |
|
|
Hi,
Messed that post up as to be correct,
here is the correct output for the 2 bytes, think I need sleep!!!!
Here is the "normal" output of the low 4 digits in the normal mode:
Code: |
nibh = Dig_1; // MSB BYTE make ready to send out This is the 2nd digit
nibl = Dig_0; // LSB BYTE make ready to send out This is the 1st digit
CountLSB = (nibl|(nibh<<4));
nibh = Dig_3; // MSB BYTE make ready to send out This is the 3rd digit
nibl = Dig_2; // LSB BYTE make ready to send out is .1 value
CountMSB = (nibl|(nibh<<4)); |
tom |
|
|
Ttelmah Guest
|
|
Posted: Sun Dec 31, 2006 10:25 am |
|
|
tom wrote: | Hi to whom ever on the fast BCD program posted,
The progam posted as "better",
I can not make it run witout crashing the PICC
after it does several new conversions.
As I said in the earler post on this subject of BCD,
Im not the most swift programmer going.
At this time in life don't expect to become much better,
but I'll try with a bit of help.
So a bit of explaining in the remarks as to what is occuring in the programm would be nice.
the 3 buffers being used, I understand that the result shoud be:
buffer 0 is least nibble #1 on the right, left nibble is #2
buffer 1 is #3 right, #4 is left
buffer is most signifant #5 nibble to the right.
Thank You,
tom |
Have just run it through 3500 conversions, without a 'crash'. There is nothing in the code to cause a problem (think about what it is doing...). The only problems would be if it is not called as shown, or the buffer sizes were not right (when it could overwrite adjacent memory cells). The only fault as posted, is that I declare 'nibctr', and never use it. This was because I tried a version using a union to access the nibbles, and this was slower than using the multiple accesses shown.
Best Wishes |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
16 bit binary to BCD, and a thank you |
Posted: Sun Dec 31, 2006 11:53 am |
|
|
Hi,
What the conversion as I coded it was not true BCD in what I finally found.
The results in my use of your program had the conversion to be 0-F.
As I need the results to be 0-9 for each nibble.
As I found in the debug was memory over write as sending data back to the rest of my program.
I am not that swift of programmer here as a self learned C code,
a (old, 70 yrs) person that have only been using "C" for 4 years.
So I need much help for this type of problem.
If there is a answer to use your program with a conversion of the BUFF's to 2 byte's, would greatly thank you.
Only need the 4 low nibbles, as the 5th high in buff 2 will always be zero as I devide the incoming binary 16 bit with:
temp = bin_inp / 18.2041667; // make into binary degrees value
This is 16 bit in to binary 360 degrees of a compleat circle.
Then with the new code interface to outside tracking program requires:
0000 - 3600 decimal out put to it.
here is the program that works fine in my program,
would much prefer to be able to use the one you provided if possilble.
"MY PROGRM" next and yours at the bottom.
Also note that part of the problem is that the output nibbles are mixed in the values of each byte with also the MSB byte and the LSB byte's are not normal as to the decimal value in each.
Thank you for your time and effort.
tom
........
Code: |
long Dig_0, Dig_1, Dig_2, Dig_3, Dig_4;
void bin_to_Dig(long bin_inp)
{ // This is for VK3UM program
long temp; // 16 bit binary to BCD 5 byte
int nibh;
int nibl;
temp = bin_inp / 18.2041667; // make into binary degrees value
//Dig_4 = temp/10000; // This is not needed as just 4 digits
//temp = temp - (Dig_4 * 10000); // this will always be zero
Dig_3 = temp/1000;
temp = temp - (Dig_3 * 1000);
Dig_2 = temp/100;
temp = temp - (Dig_2 * 100);
Dig_1 = temp/10;
temp = temp - (Dig_1 * 10);
Dig_0 = temp;
nibh = Dig_1; // MSB BYTE This is the 2nd digit
nibl = Dig_2; // LSB BYTE This is the 1st digit
CountMSB = (nibl|(nibh<<4));
nibh = Dig_3; // MSB BYTE This is the 3rd digit
nibl = Dig_0; // LSB BYTEs This is the 0rd digit, .1 value
CountLSB = (nibl|(nibh<<4));
|
what are the values in each buff ???
Last edited by w2drz on Sun Dec 31, 2006 4:00 pm; edited 2 times in total |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
16 bit to BCD the paste is still messed up 2nd post |
Posted: Sun Dec 31, 2006 12:24 pm |
|
|
here is what I coded using your pgm.
Code: |
void bin_to_Dig(int16 bin_inp,int8 * buff){
//converts 16bit value, to five BCD digits. Tries to do it fairly
//efficiently, both in size, and speed.
int8 nibh;
int8 nibl;
int1 temp_bit;
int8 nibctr;
buff[0]=buff[1]=buff[2]=0;
do {
if ((buff[0] & 0xF)>=5) buff[0]+=3;
if ((buff[0] & 0xF0)>=0x50) buff[0]+=0X30;
if ((buff[1] & 0xF)>=5) buff[1]+=3;
if ((buff[1] & 0xF0)>=0x50) buff[1]+=0X30;
if ((buff[2] & 0xF)>=5) buff[2]+=3;
temp_bit=shift_left(&bin_inp,2,0);
shift_left(buff,3,temp_bit);
} while (bin_inp!=0);
nibh = 0; //buff[0] >> 4; // buff 0 (1) msnibble = 2nd digit
nibl = 0; //buff[1] & 0x04; // buff 1 (2) lsnibble = 1st digit
CountMSB = (nibl|(nibh<<4; // buff 1 (1) msnibble = 3nd digit
nibl = 0; //buff[0] & 0x04; // buff 0 (0) lsnibble = 0 digit
CountLSB = (nibl|(nibh<<4));
|
The output shown only does the one nibble out as a test,
this did up to "F" out in my interface to the outside tracking program
tom
Last edited by w2drz on Sun Dec 31, 2006 5:01 pm; edited 4 times in total |
|
|
w2drz
Joined: 27 Dec 2006 Posts: 55 Location: Western New York - USA
|
16 bit and this is the right code for your pgm end |
Posted: Sun Dec 31, 2006 12:44 pm |
|
|
Hi.
This is the correct code to your program end.
I had a test to determine what the value's were and did not correct the code I sent prior of your program
Code: |
nibh = buff[0] >> 4;
nibl = buff[1] & 0x04;
CountMSB = (nibl|(nibh<<4>> 4;
nibl = buff[0] & 0x04;
CountLSB = (nibl|(nibh<<4));
} |
tom |
|
|
haqamar
Joined: 26 Dec 2011 Posts: 3
|
|
Posted: Sat Apr 13, 2013 2:33 pm |
|
|
Hi Ttelmah,
I tested your earlier posted code but with strange results.
if int16 = 12345, output 01 23 45
if int16 = 1234, output 00 06 17
if int16 = 10, output 00 00 05
if int16 = 2, output 00 00 01
Why its so ?
hammad |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|