CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

16 bit binary to bcd C++ conversion program
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
w2drz



Joined: 27 Dec 2006
Posts: 55
Location: Western New York - USA

View user's profile Send private message Visit poster's website

16 bit binary to bcd C++ conversion program
PostPosted: Wed Dec 27, 2006 5:01 am     Reply with quote

Wink

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

View user's profile Send private message

PostPosted: Wed Dec 27, 2006 12:56 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

16 bit binary to bcd C++ conversion or 16 bin to 5 bcd
PostPosted: Wed Dec 27, 2006 3:00 pm     Reply with quote

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.


Confused

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

View user's profile Send private message

PostPosted: Wed Dec 27, 2006 3:24 pm     Reply with quote

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:

00126

32768

65535


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

View user's profile Send private message Visit poster's website

PostPosted: Wed Dec 27, 2006 3:38 pm     Reply with quote

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:

00126

32768

65535


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 Embarassed
w2drz



Joined: 27 Dec 2006
Posts: 55
Location: Western New York - USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Dec 29, 2006 5:40 am     Reply with quote

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));

}

Very Happy Very Happy
Ttelmah
Guest







PostPosted: Fri Dec 29, 2006 8:52 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri Dec 29, 2006 5:36 pm     Reply with quote

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 Confused
w2drz



Joined: 27 Dec 2006
Posts: 55
Location: Western New York - USA

View user's profile Send private message Visit poster's website

PostPosted: Sat Dec 30, 2006 3:46 am     Reply with quote

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));
Smile

tom
w2drz



Joined: 27 Dec 2006
Posts: 55
Location: Western New York - USA

View user's profile Send private message Visit poster's website

16 bit BCD BYTE output "normal" this is the correc
PostPosted: Sat Dec 30, 2006 3:54 am     Reply with quote

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));
Smile

tom Embarassed
Ttelmah
Guest







PostPosted: Sun Dec 31, 2006 10:25 am     Reply with quote

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 Confused

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

View user's profile Send private message Visit poster's website

16 bit binary to BCD, and a thank you
PostPosted: Sun Dec 31, 2006 11:53 am     Reply with quote

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 ???
Crying or Very sad


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

View user's profile Send private message Visit poster's website

16 bit to BCD the paste is still messed up 2nd post
PostPosted: Sun Dec 31, 2006 12:24 pm     Reply with quote

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 Embarassed


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

View user's profile Send private message Visit poster's website

16 bit and this is the right code for your pgm end
PostPosted: Sun Dec 31, 2006 12:44 pm     Reply with quote

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 Embarassed
haqamar



Joined: 26 Dec 2011
Posts: 3

View user's profile Send private message

PostPosted: Sat Apr 13, 2013 2:33 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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