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 support@ccsinfo.com

How to extract single decimal digit from int16 number?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Futterama



Joined: 17 Oct 2005
Posts: 98

View user's profile Send private message

How to extract single decimal digit from int16 number?
PostPosted: Thu Oct 20, 2005 5:57 pm     Reply with quote

Hi,

I was wondering, how can I extract a single decimal digit from a int16 like the DIG function in PicBasic do it with 16bit words?

Thanks.


Regards,
Futterama
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 20, 2005 8:13 pm     Reply with quote

This is probably a student question, so may I suggest that you use
http://www.google.com
Just type a search string that is likely to find C source code, such as:
"extract digits" int char

In the first ten hits, there's sample code. Look in the one on "LED.C"
and the Daniweb one, where a forum discusses routines to do it.

Use Google. It's got your answers. The key to using Google
effectively is to search for quoted strings. To find C source code,
put in some common C keywords, such as int and char as I have
done above.
Futterama



Joined: 17 Oct 2005
Posts: 98

View user's profile Send private message

PostPosted: Fri Oct 21, 2005 2:36 am     Reply with quote

I don't get the examples...

I'm pretty new to C, and I don't see the point with printf in a microcontroller.

It would be more helpful if you posted the code I needed, cause I've tried google before posting this question, and it didn't help me.

Or you could at least paste the code you think I need from the web, and perhaps explain in a few words how it works.
Futterama



Joined: 17 Oct 2005
Posts: 98

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 4:31 am     Reply with quote

Well, since no one would bother posting some code, I have made my own function. Crude? Yes. Does it work? Yes. Do anyone in this forum have a better idea? No.

Code:
void SplitDigit(int16 data)
{
   int8 DigitValue[5];

   DigitValue[0] = 0;
   DigitValue[1] = 0;
   DigitValue[2] = 0;
   DigitValue[3] = 0;
   DigitValue[4] = 0;

   if(data>9999)
   {
      while(data>9999)
      {
         data = data - 10000;
         DigitValue[0]++;
      }
   }
   else
     DigitValue[0] = 0;

   if(data>999)
   {
      while(data>999)
      {
         data = data - 1000;
         DigitValue[1]++;
      }
   }
   else
     DigitValue[1] = 0;

   if(data>99)
   {
      while(data>99)
      {
         data = data - 100;
         DigitValue[2]++;
      }
   }
   else
      DigitValue[2] = 0;

   if(data>9)
   {
      while(data>9)
      {
         data = data - 10;
         DigitValue[3]++;
      }
   }
   else
      DigitValue[3] = 0;

   DigitValue[4] = data;
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 6:02 am     Reply with quote

Quote:
Well, since no one would bother posting some code, I have made my own function. Crude? Yes. Does it work? Yes. Do anyone in this forum have a better idea? No.

This sounds like you are a disappointed in the support you got here. What was wrong with the pointers PCM gave you? I had a look at the LED.C program he pointed you to and it looks like a good starting point.


Other alternatives:
- itoa()
- sprintf()


Last edited by ckielstra on Wed Oct 26, 2005 6:25 am; edited 1 time in total
dyeatman



Joined: 06 Sep 2003
Posts: 1912
Location: Norman, OK

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 6:07 am     Reply with quote

What don't you get about printf in a microcontroller? Printf is simply a means to output data from the PIC in a user defined format (hex, float etc.). If you use putc(x) the byte (x) is simply output as character without any "conversion"
Futterama



Joined: 17 Oct 2005
Posts: 98

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 6:50 am     Reply with quote

ckielstra wrote:
This sounds like you are a disappointed in the support you got here. What was wrong with the pointers PCM gave you? I had a look at the LED.C program he pointed you to and it looks like a good starting point.

I was a little disappointed, I came here to get help, not to be told "Use Google" (no offence, but it just didn't help me).
I looked at the file LED.C, and didn't understand what was going on, that's the problem.

Perhaps you could give an example on the use of the 2 functions you mentioned (I can't find itoa in the built in function list in CCS help).

dyeatman wrote:
What don't you get about printf in a microcontroller? Printf is simply a means to output data from the PIC in a user defined format (hex, float etc.). If you use putc(x) the byte (x) is simply output as character without any "conversion"

I don't understand where the output will go. Output data where to?

Regards,
Futterama
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 7:24 am     Reply with quote

Quote:
Perhaps you could give an example on the use of the 2 functions you mentioned (I can't find itoa in the built in function list in CCS help).
You can download the October 2005 PDF version of the manual from the CCS website.

Code:
#include <stdlib.h>
int8 String[10];
int16 Value = 12345;

// Method 1
sprintf(String, "%Lu", Value);

// Method 2
itoa(Value, 10, String);
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 7:43 am     Reply with quote

Futterama wrote:
Well, since no one would bother posting some code, I have made my own function. Crude? Yes. Does it work? Yes. Do anyone in this forum have a better idea? No.

Code:
void SplitDigit(int16 data)
{
   int8 DigitValue[5];

   DigitValue[0] = 0;
   DigitValue[1] = 0;
   DigitValue[2] = 0;
   DigitValue[3] = 0;
   DigitValue[4] = 0;

   if(data>9999)
<snip>
   else
      DigitValue[3] = 0;

   DigitValue[4] = data;
}


While I haven't tried to actually compile your code it looks like it should work. I would probably use the division and remainder operations instead of sucessive subtraction, but depending on the processor used your way might be faster. I know when converting a byte it is faster to subtract hundreds than to divide since you will only have to subtract at most only twice. Using printf is easier to program and to read, but will take much more code space unless you also use printf elsewhere anyway.
Your code puts the results in an array. Printf will print the results to either the standard C I/O port or to a function you provide.
_________________
The search for better is endless. Instead simply find very good and get the job done.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

where does the output go to?
PostPosted: Wed Oct 26, 2005 7:47 am     Reply with quote

If you look in the help file in CCS under 'printf' it clearly tells you where the output goes by default. You can also direct the output to one of your own functions, by putting it inside the printf brackets, also described in the help file.

Do you own a textbook on C? If not, I suggest you get yourself one. Please don't flame us for not helping you enough, most of us on here answer questions in our spare time, we aren't paid to do this! We can only help those who help themselves!

Now, about itoa() - That isn't in the CCS library, or not in my version at least. Here is a description of what it does. Bear in mind though, that this is just an example of how to use itoa and is designed for PC type computers. http://www.cplusplus.com/ref/cstdlib/itoa.html

Here is an example of the actual code behind itoa from my text book.
Code:
/*itoa: convert n characters in s*/
void itoa(int n, char s[]){
      int i, sign;
      if((sign=n) < 0) // Record sign
              n= -n;      // Make n positive
      i=0;
      do{   /* generate digits in reverse order */
              s[i++] = n % 10 + '0';   // Get next digit
       } while((n/=10) > 0;             // Delete it
      if(sign < 0)
              s[i++] = '-';
      s[i] = '\0';
      reverse(s);
}
// Copied from "The C programming language" by Kernighan & Ritchie


Now, some notes. This won't work as-is in CCS. For a start, this uses the PC default of signed int. In CCS ints are unsigned by default, so this would require re-writing to reflect this. If you don't want negative numbers, it will be a lot simpler than what I have copied out above. (No 'sign' testing)

reverse() does not exist in CCS, so you would need to write a routine to flip the string around yourself.

The reverse of this is in CCS (atoi() ). This converts an ASCII string into an integer. This is in stdlib.h.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 8:16 am     Reply with quote

Here's a version of that function that I've used many times.

Code:

void itos(char s[],signed int16 n) // convert an integer to a string
{
signed int8 i, c, j;
signed int16 sign;
  if((sign = n) < 0)
    n = -n;
  i = 0;
  do
  {
    s[i++] = n % 10 + '0';
  }while((n /= 10) > 0);
  if (sign < 0 )
    s[i++] = '-';
  s[i] = '\0';
  for(i = 0, j = strlen(s) - 1; i < j; i++, j--)
  { c = s[i];
    s[i] = s[j];
    s[j] = c;
  }
}


Ronald
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 8:37 am     Reply with quote

Quote:
Printf will print the results to either the standard C I/O port or to a function you provide.
Or use sprintf which writes the data to a string (buffer).

Quote:
Now, about itoa() - That isn't in the CCS library, or not in my version at least.
It's a new addition, it was not in v3.226 but it is in v3.234. I just had a look at it, it's very flexible but large.

v3.234, PIC18F458
Standard itoa, 32 bit version: 780 bytes.
Modified itoa, 16 bits version: 480 bytes
itos from rnielsen: 466 bytes
Good old 16 bit sprintf: 224 bytes


Last edited by ckielstra on Thu Oct 27, 2005 3:02 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 11:45 am     Reply with quote

The reason I said to use Google was because this looked like just
one more homework assignment.

I'm stunned (somewhat) that you didn't try my search string for Google.
I mentioned the Daniweb link, which is in the first few hits.
It's got an entire forum discussion thread on stripping digits, with code:
http://www.daniweb.com/techtalkforums/printthread.php?t=21658
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Oct 26, 2005 12:46 pm     Reply with quote

I was intrigued by how it was possible for sprintf to be more efficient than the hand coded routine from rnielsen. After some optimization rounds I discovered it has to do with the way sprintf accesses the string buffer, it uses the index registers efficiently.
I never before used the index registers and the feature of auto increment or decrement sounds very efficient. As an excercise I coded my own version of atoi which is a little more efficient than sprintf but not as flexible, only unsigned integers are accepted (I leave this to whoever needs this functionality).

Code:
#include <18f458.h>
#FUSES HS, NOPROTECT, NOPUT, NOBROWNOUT, NOWDT, NOLVP

// Register defines for the PIC18F458
unsigned int16 FSR0;
#locate FSR0=0x0FE9

unsigned char POSTDEC0;
#locate POSTDEC0=0x0FED

unsigned char POSTINC0;
#locate POSTINC0=0x0FEE

unsigned char INDF0;
#locate INDF0=0x0FEF

unsigned int16 FSR1;
#locate FSR1=0x0FE1

unsigned char POSTDEC1;
#locate POSTDEC1=0x0FE5

unsigned char POSTINC1;
#locate POSTINC1=0x0FE6

unsigned char INDF1;
#locate INDF1=0x0FE7


/////////////////////////////////////////////////////////////////////
// Converts a 16 bit unsigned integer to an ASCII string.
// This is a highly optimized verion of itoa() using the index registers
// of the PIC18 processor.
// Requires about 170 bytes on the PIC18 compared to about 224 bytes
// for sprintf("%Lu").
//
// Input:
//    num  The value to convert (only unsigned integer support)
//    s    Pointer to buffer for storing the result
// Returns:
//    none
//
//
// C. Kielstra, 2005
// Free for distribution.
/////////////////////////////////////////////////////////////////////
void int16_to_a(int16 num, char *s)
{
  char c;

  // Initialise pointers to start of string
  FSR0 = s;           // Set FSR0 index register to start of string buffer
  FSR1 = s;           // Set FSR1 index register to start of string buffer
 
  // Conversion
  do
  {
    POSTINC1 = (num%10) + '0';
  } while (num /= 10);

  POSTDEC1 = '\0';              // End the string
                                // Points now to last character in string

  // Reverse the string
  // p0 points to first character and p1 to last character,
  // finished when pointers meet in the middle of the string.
  do
  {
    c = INDF0;          // c = *p0
    POSTINC0 = INDF1;   // *p0++ = *p1
    POSTDEC1 = c;       // *p1-- = c
  } while (FSR0 < FSR1);
}


void main()
{
  int8 String[10];
  int16 Value = 1234;

  int16_to_a(Value, String);
 
  while(1);
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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