# 8051 microcontroller reading data from serial port

#### godatguitar

##### New Member
HI All

I am very new(ish) to 8051's as I have completed some basic work with them in assembler and c, but I am stuck on something now...

I need to receive some data from the serial port on the 8051. I would prefer to write in C if possible.

I want to receive some x and y integer (coordinates) from the serial and then move motors to those coordinates. Moving the motors is relatively simple.

Basically, I do not know if I have to do it character at a time then put them into two seperate variables, like xcoord, ycoord for example.

main()
{

SCON = 0x50; /* mode 1, 8-bit uart, enable receiver */
TMOD = 0x20; /* timer 1, mode 2, 8-bit reload */
TH1 = 0xFE; /* reload value for 2400 baud */
ET0 = 0;
TR1 = 1; /* start the timer */
TI = 1; /* clear the buffer */

ES = 1; /* allow serial interrupts */
EA = 1; /* enable interrupts */

P1 = 0; //This is the port for the motors.

while (1==1)
{
int i;
int j;

for(i=0; i<xcoord;i++)
P1 = .......;
for(j=0;j<ycoord;j++)
P1 = .......;

P1 = 0;
P2 = 0;
TI = 1; //then transmit a complete signal out of serial
}

The code above shows bits of what i have so far (in C). Basically it should set up the 8051 properly.

Does anyone have any ideas how to read in 2 integers, say 0 to 350, and a end-of-transmission char?

Please post. or email me at:

godatguitar@hotmail.com
Please forgive me if this is totally wrong etc, I am new and learning....

#### godatguitar

##### New Member
Ignore post above!

Hey guys,
My prog now looks like this:

#include <reg51.h>

char getCharacter (void);
void sendCharacter (char);

main()
{
char input; /* variable to hold characters in */

SCON = 0x50; /* mode 1, 8-bit uart, enable receiver */
TMOD = 0x20; /* timer 1, mode 2, 8-bit reload */
TH1 = 0xFE; /* reload value for 2400 baud */
TR1 = 1;
TI = 1;

while (1 == 1) // Do this loop forever.
{

input = getCharacter ();
//Move motors here......
sendCharacter ('~'); //send complete signal.
}
}

//*********************************
char getCharacter (void)
{
char chr;
while (RI != 1) {;}

while(SBUF != '~')
{
chr = chr + SBUF;
}
RI = 0;
return(chr);
}
//**********************************

void sendCharacter (char complete)
{
while (TI != 1) {;}
TI = 0;
SBUF = complete;
return;
}

The bit I am not sure about is the line:

chr = chr + SBUF;

Basically, I want to read in an integer that could be up to 3 digits long.
I am really dumb! (hehe) and not sure how to do this. At the mo I am using char, but should be using int i think, just unsure of how!
Please help!
Many thanks

Paul

#### StupidDum

##### New Member
what is the use of "while (TI != 1) {;} "
in your code, i don't see any change in T1

#### Exo

##### Active Member
A byte (unsigned char) can hold a value between 0 and 255. If these values are good enough for you then you just need to receive 1 byte per coordinate...

If you need bigger numbers, 16 bit for example (0 - 65535) then you must receive 2 bytes from pc per coordinate and "stick them togheter" again.

#### godatguitar

##### New Member
How do you "stick them back together"?

If I had two bytes etc, how do i make them one?

Perhaps (byte1*10) + byte2 ?

cheers

#### Nigel Goodwin

##### Super Moderator
Most Helpful Member
godatguitar said:
How do you "stick them back together"?

If I had two bytes etc, how do i make them one?

Perhaps (byte1*10) + byte2 ?

cheers
If you're sending them as bytes, you would use ByteHigh*256+ByteLow at the PC end to reconstruct the 16 bit value.

Depending on what you are doing (and how fast it needs to be), it's often easier to send the data as a string of ASCII characters - this way you can simply read it with Hyperterminal and save it to a file, import it directly into a spreadsheet, or anything you want.

#### godatguitar

##### New Member
Ok, I am still having trouble...

Lets assume I want to read some ascii characters from the serial port, say 4, and convert them into 2 integers where the first 2 received make up the 1st integer, and the 2nd two make up the 2nd integer.
How do I do that?

I am reading from SBUF and placing into variables called xcoord1 and xcoord2 (and the same for the y)

At the moment I just do:

xcoord1 = SBUF;
xcoord1 = xcoord1 - 48;

where 48 from the value in xcoord1 makes the char into the value?

Is this correct, or am I thinking about it the wrong way.

many thanks for your help guys...

Paul

#### Nigel Goodwin

##### Super Moderator
Most Helpful Member
I can't help you in C, but in Delphi you would use the Val() procedure, simply join the ASCII characters together to make a string and use Val() to convert it to a number. Here's a section of the Delphi helpfile.

procedure Val(S; var V; var Code: Integer);

Description

Val converts the string value S to its numeric representation, as if it were read from a text file with Read.

S is a string-type expression; it must be a sequence of characters that form a signed real number.

V is an integer-type or real-type variable. If V is an integer-type variable, S must form a whole number.

Code is a variable of type Integer.

#### godatguitar

##### New Member
Hey guys....

Can anyone help me here?

I am trying to read from SBUF on the 8051 and put it into an integer, so converting ascii to int i suppose...?

Here is the code that doesnt work atm...

xcoord1 = (int)SBUF;
xcoord1 = xcoord1 - 48;

Am I doing this wrong?
Cheers

#### Nigel Goodwin

##### Super Moderator
Most Helpful Member
godatguitar said:
Hey guys....

Can anyone help me here?

I am trying to read from SBUF on the 8051 and put it into an integer, so converting ascii to int i suppose...?

Here is the code that doesnt work atm...

xcoord1 = (int)SBUF;
xcoord1 = xcoord1 - 48;

Am I doing this wrong?
Cheers
I would have thought so!.

I've told you how to do it in Delphi, surely C has similar string handling facilities?. As I mentioned before, I can't help you with C - but Delphi, Pascal, and BASIC all have this facility - I can't believe C doesn't!.

How about something like this?, which I just downloaded off a C tutorial, it reads a string then a number from a file directly into the relevent variables - as I understand it you can read the serial port in the same way?.

Code:
    /* Open file for input */
ifp = fopen(ifilename,"r");

/* Read data */
fscanf(ifp,"%s %d",name,&idNum);

#### bmcculla

##### New Member
C does have functions for working with strings (string.h or something similar. function is called atoi I beleive) but its probably better to just write a small section of code to do this yourself.

Are you sure the value in SBUF is being recieved correctly? Try just echoing the character back through RS232.

What value ends up in xcoord1? Try using unsiged ints; the 8051 doesn't have any instructions that deal with signed ints so the compiler has to add a bunch of code. This looks like a type issue.

Try:

xcoord1 = (unsigned int)(SBUF - 'a');

You could also try casting the 48: xcoord = xcoord - ((int) 48 ); This will force the compiler to treat the 48 as an int and not as its default.

You could also try scanf. I have been avoiding it because it wastes a lot of time.

Brent

#### godatguitar

##### New Member
Cheers!

Thanks guys...

I was right with what I was doing, but the keil software simulation wasnt working correctly for some reason.
I changed the software for a version i was familiar with, and ran the program and it worked!

Cheers for all your help...

Now all i gotta do is try and control some stepper motors! I am going to need a buffer circuit/motor driver for this, if anyone has any good pointers let me know!

Loading