Jump to content
43oh

Converting a 3-Digit Number to Characters for a LCD Display


Recommended Posts

I'm working on a project requiring a calculated 3-digit number to be updated periodically on a LCD display and came up with a simple solution to convert the number to characters. I'm posting it here on the chance that others might find it useful.

 

I first thought of sprintf, but it's way too big for a msp430g2452. I found and tried tfp_sprintf, but it was also too big. I tried sstream (apparently the preferred method) but it caused 100+ errors in CCS, somewhere in the TI include files.

 

I found this to convert a single digit to a character

character = (char)(((int)'0') + digit_to_convert);

I had a 3 digit number to convert; after a bit of thought I came up with this-

// All number variables are type int
// joules is the calculated 3-digit number- it is displayed with leading

joules = total_seconds/3.2;
joules100 = joules/100;   // joules100 is the 100's place digit 
joules10 = (joules/10)%10;   // joules10 is the 10's place digit
joules1 = joules%10;    // joules1 is the 1's place digit

// The complete message is in a 32 element array- these 3 digits are elements 22-24

message[22] = (char)(((int)'0')+joules100);
message[23] = (char)(((int)'0')+joules10);
message[24] = (char)(((int)'0')+joules1); 

Link to post
Share on other sites

Hi webster,

 

I've also found a useful int-to-char converter:

void tostr(int i,char *s) {	// Convert Integer to String
char *p;
p=s;
p[2]=i%10;
i-=p[2];
i/=10;
p[1]=i%10;
i-=p[1];
i/=10;
p[0]=i%10;
i-=p[0];
       p[3] = 0; // mark end of string
p[2]+=0x30;
p[1]+=0x30;
p[0]+=0x30;
}

I hope you don't mind me going into microscopic detail for others' benefit;

 

This will take an integer and a string[4], and perform modulo, division, and subtraction on the int, generating the answers in the string, and adds 0x30 to each element in the string to convert it to ASCII for an LCD to read.

 

So, when calling this, if we set the arguments to nVar and blah[4], it should look like this:

    int nVar = 0x7F; // give nVar a set value
       tostr(nVar, blah[4]);

The values of the elements in blah[4] would be as follows:

blah[0] = 0x31

blah[1] = 0x32

blah[2] = 0x37

blah[3] = 0x00

And, if printed on an HD44780 character display, it would appear as: 127

Link to post
Share on other sites

void tostr(int i,char *s) {	// Convert Integer to String

This will take an integer and a string[4]

 

Slightly uh, no. This will take a pointer to a char array; you probably mean the right thing, but string[4] is very bad parlance, because

 

So, when calling this, if we set the arguments to nVar and blah[4], it should look like this:

    int nVar = 0x7F; // give nVar a set value
       tostr(nVar, blah[4]);

 

Very uh, no :). blah[4] is one single char, the last element in something that was presumably declared as char blah[4]; basically, this passes literally one byte worth of storage to the function to work with; to the function that doesn't check its arguments (which might, might be explainable in a constrained environment but also means you have to be very, very, very careful not to make these kinds of mistakes) and will happily overwrite whatever is next to this in memory.

Link to post
Share on other sites

OOPS!!! :oops:

Sorry and thanks for pointing that out, as you can see I'm still learning... to type... or post... replies.

 

That should have been:

        char blah[4];
        int nVar = 0x7F; // give nVar a set value
        tostr(nVar, blah);

 

So, when calling this, if we set the arguments to nVar and blah[4], it should look like this:

    int nVar = 0x7F; // give nVar a set value
       tostr(nVar, blah[4]);

 

Very uh, no :). blah[4] is one single char, the last element in something that was presumably declared as char blah[4]; basically, this passes literally one byte worth of storage to the function to work with; to the function that doesn't check its arguments (which might, might be explainable in a constrained environment but also means you have to be very, very, very careful not to make these kinds of mistakes) and will happily overwrite whatever is next to this in memory.

 

My logic was right, but it didn't get to the computer intact... :)

In udah woids, dat wuz uh tiepoe! :P :wave:

Link to post
Share on other sites
  • 3 months later...

I'm trying to use your code with a seven segment display but I'm having trouble getting it to work.

 

post-7895-135135527927_thumb.jpg

 

#include 
#include 


void tostr(int i,char *s) {   // Convert Integer to String
char *p;
p=s;
p[2]=i%10;
i-=p[2];
i/=10;
p[1]=i%10;
i-=p[1];
i/=10;
p[0]=i%10;
i-=p[0];
p[3] = 0; // mark end of string
p[2]+=0x30;
p[1]+=0x30;
p[0]+=0x30;
}

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

P1DIR = 255;
P1OUT = 0;

const int seven_seg[] = { 64, 121, 36, 48, 25, 18, 2, 120, 0, 16};	//Bit patterns for the seven
int int_val = 12;													//segment display (common anode)
char chr_val[4];
int delay_var = 1;

tostr(int_val, chr_val);

while(1)
{
	P1OUT = seven_seg[chr_val[0]] | BIT7;				//BIT7 is used for the common anode on one segment and
	for(delay_var = 0; delay_var < 100; delay_var++)	//to a transistor for the other segment (toggling between)
	{
	}

	P1OUT = seven_seg[chr_val[1]];
	for(delay_var = 0; delay_var < 100; delay_var++)
	{
	}
}
}

 

The program works if I just replace chr_val[1] with a value.

 

post-7895-135135527935_thumb.jpg

 

#include 
#include 


void tostr(int i,char *s) {   // Convert Integer to String
char *p;
p=s;
p[2]=i%10;
i-=p[2];
i/=10;
p[1]=i%10;
i-=p[1];
i/=10;
p[0]=i%10;
i-=p[0];
p[3] = 0; // mark end of string
p[2]+=0x30;
p[1]+=0x30;
p[0]+=0x30;
}

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

P1DIR = 255;
P1OUT = 0;

const int seven_seg[] = { 64, 121, 36, 48, 25, 18, 2, 120, 0, 16};	//Bit patterns for the seven
int int_val = 12;													//segment display (common anode)
char chr_val[4];
int delay_var = 1;

tostr(int_val, chr_val);

while(1)
{
	P1OUT = seven_seg[1] | BIT7;				//BIT7 is used for the common anode on one segment and
	for(delay_var = 0; delay_var < 100; delay_var++)	//to a transistor for the other segment (toggling between)
	{
	}

	P1OUT = seven_seg[2];
	for(delay_var = 0; delay_var < 100; delay_var++)
	{
	}
}
}

Thanks for any help :)

Link to post
Share on other sites

It works :)

Thank you!

 

#include 
#include 


void tostr(int i,char *s) {   // Convert Integer to String
char *p;
p=s;
p[2]=i%10;
i-=p[2];
i/=10;
p[1]=i%10;
i-=p[1];
i/=10;
p[0]=i%10;
i-=p[0];
p[3] = 0; // mark end of string
}

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;

P1DIR = 255;
P1OUT = 0;

const int seven_seg[] = { 64, 121, 36, 48, 25, 18, 2, 120, 0, 16};	//Bit patterns for the seven
int int_val = 23;													//segment display (common anode)
char chr_val[4];
int delay_var = 1;

tostr(int_val, chr_val);

while(1)
{
	P1OUT = seven_seg[chr_val[1]] | BIT7;				//BIT7 is used for the common anode on one segment and
	for(delay_var = 0; delay_var < 100; delay_var++)	//to a transistor for the other segment (toggling between)
	{
	}

	P1OUT = seven_seg[chr_val[2]];
	for(delay_var = 0; delay_var < 100; delay_var++)
	{
	}
}
}

Link to post
Share on other sites

You are quite welcome, and thank YOU! In the process of asking for help, you inadvertently helped me as well, as these programs show:

 

Before looking at your code:

#include "MSP430G2252.h"

#define NUM0 0x3F
#define NUM1 0x06
#define NUM2 0x5B
#define NUM3 0x4F
#define NUM4 0x66
#define NUM5 0x6D
#define NUM6 0x7D
#define NUM7 0x07
#define NUM8 0x7F
#define NUM9 0x6F
#define NUMa 0x77
#define NUMb 0x7C
#define NUMc 0x39
#define NUMd 0x5E
#define NUMe 0x79
#define NUMf 0x71
#define NUMh 0x76
#define NUMj 0x1E
#define NUMl 0x38
#define NUMo 0x5C
#define NUMp 0x73
#define NUMu 0x1C
#define NUMI 0x30
#define NUMQ 0x53
#define NUMZ 0x00

int NUMBER=0;

char DIGI[7] = {NUMc,NUM0,NUMf,NUMf,NUMe,NUMe,NUMQ};
const char BIT[8] = {1,2,4,8,16,32,64,128};

int DIGIT=0;
int c = 0;

void updateDIGIT(void);
void updateNUMBER(void);

void main( void ){
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

 	P1OUT = 0x7F;
P1DIR = 0x7F;
P2SEL = 0x00;   	// allow 2.6-2.7 to output
P2OUT = 0x7F;
P2DIR = 0x7F;
P1IES = BIT7;
P1IFG = 0;
P1IE = BIT7;
P2IES = BIT7;
P2IFG = 0;
P2IE = BIT7;
DIGIT=NUMBER=0;
__enable_interrupt();
for(;{
	while(c < 7){
 		P1OUT = DIGI[c];
	P2OUT = ~BIT[c];
	__delay_cycles(5);
 		P2OUT = 0xFF;
	c++;
	}
c = 0;
}
}

#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void){
NUMBER++;
if(NUMBER > 10)
	NUMBER = 0;
updateNUMBER();
P1IFG &= ~BIT7;
}

#pragma vector=PORT2_VECTOR
__interrupt void PORT2_ISR(void){
DIGIT++;
if(DIGIT == 7)
	DIGIT = 0;
P2IFG &= ~BIT7;
}

void updateNUMBER(void){
switch (NUMBER){
case 0:
	DIGI[DIGIT] = NUM0;
	break;
case 1:
	DIGI[DIGIT] = NUM1;
	break;
case 2:
	DIGI[DIGIT] = NUM2;
	break;
case 3:
	DIGI[DIGIT] = NUM3;
	break;
case 4:
	DIGI[DIGIT] = NUM4;
	break;
case 5:
	DIGI[DIGIT] = NUM5;
	break;
case 6:
	DIGI[DIGIT] = NUM6;
	break;
case 7:
	DIGI[DIGIT] = NUM7;
	break;
case 8:
	DIGI[DIGIT] = NUM8;
	break;
case 9:
	DIGI[DIGIT] = NUM9;
	break;  
case 10:
	DIGI[DIGIT] = NUMa;
	break;
case 11:
	DIGI[DIGIT] = NUMb;
	break;
case 12:
	DIGI[DIGIT] = NUMc;
	break;
case 13:
	DIGI[DIGIT] = NUMd;
	break;
case 14:
	DIGI[DIGIT] = NUMe;
	break;
case 15:
	DIGI[DIGIT] = NUMf;
	break;
case 16:
	DIGI[DIGIT] = NUMh;
	break;
case 17:
	DIGI[DIGIT] = NUMj;
	break;
case 18:
	DIGI[DIGIT] = NUMl;
	break;
case 19:
	DIGI[DIGIT] = NUMo;
	break;
case 20:
	DIGI[DIGIT] = NUMp;
	break;
case 21:
	DIGI[DIGIT] = NUMu;
	break;
case 22:
	DIGI[DIGIT] = NUMI;
	break;
case 23:
	DIGI[DIGIT] = NUMQ;
	break;
case 24:
	DIGI[DIGIT] = NULL;
	break; 
}
}

 

After looking at your code:

#include "MSP430G2252.h"

const char CHAR[] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F, // 9
0x77, // a
0x7C, // b
0x39, // c
0x5E, // d
0x79, // E
0x71, // F
0x76, // h
0x1E, // j
0x38, // l
0x5C, // o
0x73, // P
0x1C, // u
0x60, // r
0x30, // I
0x53, // ?
0x00, // BLANK
};
const char BIT[8] = {1,2,4,8,16,32,64,128};
char DIGI[7] = {CHAR[12],CHAR[0],CHAR[15],CHAR[15],CHAR[14],CHAR[14],CHAR[24]};
int NUMBER=0;
int DIGIT=0;
int c = 0;

void main( void ){
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

 	P1OUT = 0x7F;
P1DIR = 0x7F;
   P2SEL = 0x00;   	// allow 2.6-2.7 to output
P2OUT = 0x7F;
P2DIR = 0x7F;
P1IES = BIT7;
   P1IFG = 0;
   P1IE = BIT7;
P2IES = BIT7;
   P2IFG = 0;
   P2IE = BIT7;
DIGIT=NUMBER=0;
__enable_interrupt();
for(;{
	while(c < 7){
 		P1OUT = DIGI[c];
	P2OUT = ~BIT[c];
	__delay_cycles(5);
 		P2OUT = 0xFF;
	c++;
	}
c = 0;
}
}

#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void){
NUMBER++;
if(NUMBER > 10) NUMBER = 0;
DIGI[DIGIT] = CHAR[NUMBER];
P1IFG &= ~BIT7;
}

#pragma vector=PORT2_VECTOR
__interrupt void PORT2_ISR(void){
DIGIT++;
if(DIGIT == 7)
	DIGIT = 0;
P2IFG &= ~BIT7;
}

Here is the common-cathode display: (sorry abt quality, camera wouldn't focus on the flashing...)file.php?id=1205

Link to post
Share on other sites

It's a 7-digit 7-seg display, so it has 14 pins to control all 49 LEDs. (7x7=49)

I'm using a 'G2252 (has 16 GPIO) to drive it: lower 7 bits of port 1 for the segments, lower 7 bits of port 2 for the digits.

Both of the BIT7 pins have buttons on them: one controls which digit is selected, and the other makes that digit scroll through the available characters.

I know it's a bit expensive on I/O, but it works... and I could probably make it better and save six pins by using an HEF4017 for the digits.

file.php?id=1207

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...