1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

8051 microcontroller reading data from serial port

Discussion in '8051/8951' started by godatguitar, Feb 14, 2004.

  1. godatguitar

    godatguitar New Member

    Joined:
    Feb 14, 2004
    Messages:
    8
    Likes:
    0
    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.... :D
     
  2. godatguitar

    godatguitar New Member

    Joined:
    Feb 14, 2004
    Messages:
    8
    Likes:
    0
    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
     
  3. StupidDum

    StupidDum New Member

    Joined:
    Nov 3, 2003
    Messages:
    242
    Likes:
    0
    Location:
    Malaysia
    what is the use of "while (TI != 1) {;} "
    in your code, i don't see any change in T1
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Exo

    Exo Active Member

    Joined:
    Sep 18, 2003
    Messages:
    1,953
    Likes:
    1
    Location:
    Belgium

    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.
     
  6. godatguitar

    godatguitar New Member

    Joined:
    Feb 14, 2004
    Messages:
    8
    Likes:
    0
    How do you "stick them back together"?

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

    Perhaps (byte1*10) + byte2 ?


    cheers
     
  7. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,214
    Likes:
    640
    Location:
    Derbyshire, UK
    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.
     
  8. godatguitar

    godatguitar New Member

    Joined:
    Feb 14, 2004
    Messages:
    8
    Likes:
    0
    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
     
  9. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,214
    Likes:
    640
    Location:
    Derbyshire, UK
    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.
     
  10. godatguitar

    godatguitar New Member

    Joined:
    Feb 14, 2004
    Messages:
    8
    Likes:
    0
    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
     
  11. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,214
    Likes:
    640
    Location:
    Derbyshire, UK
    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 (text):
        /* Open file for input */
        ifp = fopen(ifilename,"r");

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

    bmcculla New Member

    Joined:
    Sep 5, 2003
    Messages:
    898
    Likes:
    0
    Location:
    California, USA
    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
     
  13. godatguitar

    godatguitar New Member

    Joined:
    Feb 14, 2004
    Messages:
    8
    Likes:
    0
    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!
     

Share This Page