Go Back   PCMech Forums > Help & Discussion > Web Design / Development

Need Some Help? Type Your Keywords Here:

Reply
 
LinkBack Thread Tools Search this Thread Rate Thread Display Modes
Old 04-19-2003, 10:38 AM   #1
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
Converting int to char

I'm writing a program in C for a pic16f84. I need to convert a 12-bit input to bcd and then output to 4 7-segment displays.

So far I've got the input value converted to decimal as an int. Now I need to take each individual digit and convert it to bcd. I can't think of any way to do this other than to convert the decimal value to a char. Of course I cant remember how to do this and I'm having lots of trouble finding it in my textbook or on the web.

Any help is appreciated. Thanks.
Fraughton is offline   Reply With Quote
Old 04-19-2003, 03:56 PM   #2
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
anybody?
Fraughton is offline   Reply With Quote
Old 04-19-2003, 08:39 PM   #3
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
Here's a stupid question. Can I do math operations on a char?
Say I've got:

unsigned char n, v;
n = '300';
v = n +2;

Can this be done?
If not can an integer value broken up into the individual digits that make it up?
Fraughton is offline   Reply With Quote
Old 04-19-2003, 10:35 PM   #4
Member (10 bit)
 
Join Date: Jul 2002
Location: University of California, Santa Barbara
Posts: 800
I don't remember what bcd is, if you could tell me maybe I can help you with that.


You can do operations like that on char's in c++, I don't know about C though. Try it and find out.

An integer can be broken up into the digits that make it up. it involves dividing by 10, 100, 1000, etc and using modulus division. If you don't know modulus division, it's the % operator in c++. I don't know if C has one, but if it doesn't you can make one. x % y would be the equivalent to the remainder when x is divided by y. I don't remember how to do the whole thing, so I'll get working on it and post back when I figure it out.
mattg2k4 is offline   Reply With Quote
Old 04-19-2003, 10:49 PM   #5
Member (10 bit)
 
Join Date: Jul 2002
Location: University of California, Santa Barbara
Posts: 800
I figured out the digits thing. I don't remember if this is the cleanest way to do it, but it works. This particular code is for a three digit integer. You can make the code work for any length integer by means of a loop which divides by different numbers each loop.. or something. I don't really remember, you might have to change things around a bit. Nobody in my class managed to figure this one out, our teacher had to give us the code

Code:
i = 3 digit integer

first digit:      (i/100)
second digit: (i%100)/10
third digit:     (i%100)%10
mattg2k4 is offline   Reply With Quote
Old 04-19-2003, 11:14 PM   #6
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
The easiest way to do this would be:

Code:
void UpdateDisplay(int input)
{
    // Do this for each digit, least significant first
   int temp;
   for (int i = 0; i < 4; i++)
   {
      temp = input % 10;
      input = input / 10;
      WriteByte(i, temp);
   }
}

void WriteByte(int digit, int number)
{
// Writes the given number (0-9) to the appropriate 7-seg LED,
// where digit 0 is the least significant and digit 3 the most.

}
Paul Victorey is offline   Reply With Quote
Old 04-20-2003, 07:59 AM   #7
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
bcd is binary coded decimal. Each digit in a decimal number would be converted to binary, so 11 in decimal would be 0001 0001 in bcd. I dont think I need to use bcd anyway. The decimal digit will work just as well in the switch statement needed to find the right output value.

I would test it out, but I cant get the C compiler we use at school to work here...it complains about being a demo when I try to build my program. So all the code I'm writing will have to be tested on tuesday.

This is what I've got so far:

main(void)
{
unsigned char inputLow, inputHigh, n, upper, lower;

for(;
{
TRISA = 0xff; //Set Port A to input
TRISB = 0xff; //Set Port B to input
inputLow = PORTB; //Take Port B input and save it to memory
lower = inputLow & 0x0f; //save low nibble
upper = inputLow & 0xf0 >> 4; //save upper nibble
inputHigh = PORTA; //Take Port A input and save it to memory

n = inputHigh * pow(16,2) + upper * 16 + lower;
//decimal value of input
}
}

the numbers are coming in as binary, but the compiler sees it as hex. So in order to get the right values for output I need to either convert to bcd or to decimal. The equation I've got there works as long as you know the decimal value of the digit in hex, but the compiler wont like it. Is there a better way to do the conversion?
The more I look at this stuff the more confused I get!
Fraughton is offline   Reply With Quote
Old 04-20-2003, 11:10 AM   #8
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
You don't need to convert to decimal, period. Inside the computer, you're always dealing with binary representations of the digits. All arithmetic is binary arithmetic, and binary arithmetic is exactly equivalent to decimal. All that changes is the specific way the numbers are stored, that is all.

Plus, BCD is useless for the numbers 0-9, it's the same as plain old binary.

Why not just do this:

Code:
main(void)
{
  unsigned short input;                        // 16-bit word
  unsigned char digit;
  while(1)
  {
    TRISA = 0xff; //Set Port A to input
    TRISB = 0xff; //Set Port B to input
    input = ((unsigned short)PORTA << 8) + (unsigned short)PORTB;  
    // Does it matter which order the ports are read?
    for (unsigned char i = 0; i < 4; i++)
    {
      digit = input%10;
      input = input/10;
      outputDigit(i,digit);
    }
  }
}

void outputDigit(unsigned char display, unsigned char digit){
// Displays digit (0-9) on the given numbered display (0=LSD, 3 = MSD)

}
Paul Victorey is offline   Reply With Quote
Old 04-20-2003, 12:22 PM   #9
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
That is so much simpler than what I was trying to do! Thanks for the help!
The order of the ports isnt all that important, its simply a matter of how I wire up the digital input.
I'm going to get to work finishing this program up. You probably havent seen the last of me yet!
Fraughton is offline   Reply With Quote
Old 04-20-2003, 01:02 PM   #10
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
Here's the final code:

Code:
main(void)
{
unsigned short input; //12-bit word
unsigned char digit;
for(;;)
{
TRISA = 0xff; //Set Port A to input
TRISB = 0xff; //Set Port B to input
input = ((unsigned short)PORTA << 8) + (unsigned short)PORTB;  
for (unsigned char i = 0; i < 4; i++)
{
	digit = input%10;
	input = input/10;
	outputDigit(i,digit);
}
}
}

	
void outputDigit(unsigned char display, unsigned char digit)
{
TRISA = 0x00;	//Set Port A to output
TRISB = 0x00;	//Set Port A to output

switch(display)
{
case 0:
	PORTA = 0x01;	//Activates Display 1
	break;
case 1:
	PORTA = 0x02;	//Activates Display 2
	break;
case 2:
	PORTA = 0x04;	//Activates Display 3
	break;
case 3:
	PORTA = 0x08;	//Activates Display 4
	break;
}

switch(digit)
{
case '0x00':			
	PortB = '0x7e';		//output 0 in bcd
	break;
case '0x01':
	PortB = '0x30';		//output 1 in bcd
	break;
case '0x02':
	PortB = '0x6d';		//output 2 in bcd
	break;
case '0x03':
	PortB = '0x79';		//output 3 in bcd
	break;
case '0x04':
	PortB = '0x33';		//output 4 in bcd
	break;
case '0x05':
	PortB = '0x5b';		//output 5 in bcd
	break;
case '0x06':
	PortB = '0x5f';		//output 6 in bcd
	break;
case '0x07':
	PortB = '0x70';		//output 7 in bcd
	break;
case '0x08':
                PortB = '0x7f';		//output 8 in bcd
	break;
case '0x09':
	PortB = '0x73';		//output 9 in bcd
	break;
}
}
Any obvious problems?

Last edited by Fraughton; 04-20-2003 at 01:07 PM.
Fraughton is offline   Reply With Quote
Old 04-20-2003, 03:06 PM   #11
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
Only problem I see is that you have 12 bit number that is stored in 16 bits, and, unless you have pulldowns on the upper 4 bits of PORTA in hardware (which is in general a good idea, it's bad to let inputs float) you should probably discard the upper 4 bits in code, e.g.:

input = ((unsigned short)(PORTA && 0x0F)<< 8) + (unsigned short)PORTB;

Otherwise,you can't guarantee that the upper 4 bits of PORTA aren't set. But it probably us a good idea to have pulldown resistors on those pins anyway, which would resolve that problem and let you use the code as is (because PORTA would always read 0000xxxx if the first 4 bits have pulldowns and aren't driven by anything else).
Paul Victorey is offline   Reply With Quote
Old 04-20-2003, 04:02 PM   #12
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
Oh sorry, I noticed you had put "16-bit word" in there. I meant to comment that PortA on this PIC has only four I/O pins, while PortB has 8. Sorry for the misunderstanding.
Fraughton is offline   Reply With Quote
Old 04-20-2003, 04:08 PM   #13
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
Thanks for all your help! I cant wait to test it out next time i'm in lab at school
Fraughton is offline   Reply With Quote
Old 04-20-2003, 05:01 PM   #14
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
Really? I thought all the midrange PICs had two 8-bit ports. My mistake, then. I'm used to working with the 16F628, in which PORTA is 8 bits (although depending on how you configure it, some are devoted to special functions like OSC1/OSC2, _MCLR, etc). The 628 is nice in that you can directly connect it to a PC's serial port with just a single IC to handle voltage level conversion.

Oh, if PORTA only has 4 bits, does a read from PORTA return 0000xxxx? A read has to return 8 bits, as the entire MCU is an 8-bit machine, so if you're not sure that the upper 4 bits are zero, you should zero them yourself.

A short integer will always be 16 bits, so you need to make sure all of them, including the upper 4, are correctly set. If you're not using the upper 4, set them to 0 or the math may not work.

Last edited by Paul Victorey; 04-20-2003 at 05:05 PM.
Paul Victorey is offline   Reply With Quote
Old 04-20-2003, 05:50 PM   #15
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
You know, I've never used Port A as an input before. I will ask my professor next week about that. In the meantime, its a simple chore to initialize the port to zero.
I really dont know very much about the various PICs. I wasnt even planning on using a PIC for this project originally. I had found a chip that was designed specifically for this function, then I found out that it costs over $200. A PIC suddenly seemed like the better option and we happen to be learning the 16F84 in class.
Thanks again!
Fraughton is offline   Reply With Quote
Old 04-20-2003, 06:02 PM   #16
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
I'm reasonably familiar with the PIC line, I use them in hobby applications, although I have never developed C code for them, I've only done the native assembly language. I am curious how division works as there is no native multiplication or division.

Just checked the datasheet, PORTA is actually 5 bits, but you don't care about the uppermost bit. You should probably keep that bit as an output all the time (having floating inputs is bad), so do:

TRISA = 0x0F; //Set Port A to input
TRISB = 0xFF; //Set Port B to input

You probably should still manually clear the uppermost 4 bits after you've done the read (so read in portA, then clear the upper bits). E.g. input = ((unsigned short)(PORTA && 0x0F)<< 8) + (unsigned short)PORTB;
Paul Victorey is offline   Reply With Quote
Old 04-20-2003, 06:42 PM   #17
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
You're right, I didnt notice RA4 there.
All of my short experience, up until a few weeks ago, has been with assembly as well. I remember reading that these PIC's don't handle division and multiplication. I was kind of hoping that the C compiler could make it work. The prof gave us an operator precedence chart which has division on it, so hopefully that means it is supported.
Fraughton is offline   Reply With Quote
Old 04-20-2003, 08:41 PM   #18
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
Yeah, it should work OK. You can always emulate division.

The option, if you were to use assembly, would be to convert the 12 bit number into 4 BCD digits (packed into 16 bits), which is easier with assembly but harder in C. The division and modulo should work if the compiler supports it.
Paul Victorey is offline   Reply With Quote
Old 04-20-2003, 08:53 PM   #19
Member (9 bit)
 
Join Date: Jan 2002
Location: Halifax, Canada
Posts: 267
I originally planned on converting the input to 4 BCD digits, but I couldnt figure it out in C. Hopefully the division works. Either way, I'm a whole lot closer to getting it working than I was before.
Fraughton is offline   Reply With Quote
Old 04-20-2003, 11:02 PM   #20
Member (12 bit)
 
Paul Victorey's Avatar
 
Join Date: Mar 1999
Location: MN or WI
Posts: 3,017
Division is one of two methods to convert to BCD (essentially, you're doing conversion to BCD one digit at a time). The other is harder to implement in C, actually, than in assembly. It uses shifts and additions, and is easy because of the PIC's "rotate through carry" instructions. It's probably better (less instructions, less CPU overhead) but harder to code in C, so the current code, assuming it runs fast enough, should be fine.
Paul Victorey is offline   Reply With Quote
Reply

Bookmarks

Still Need Help? Type Your Keywords Here:


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT -5. The time now is 07:57 AM.
Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2012, vBulletin Solutions, Inc.
SEO by vBSEO 3.6.0 PL2