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 and Serial Communication with PC

Discussion in '8051/8951' started by maxchirag, Jun 15, 2010.

  1. maxchirag

    maxchirag New Member

    Joined:
    May 23, 2010
    Messages:
    21
    Likes:
    0
    Hello,

    I have AT89S52 controller and i m trying to establish communication between controller and my PC on serial line using MAX232N IC in between (see the picture attached for configuration). I have crystal of 12Mhz and trying to use baudrate 4800. in PC i have tried two tools one is hyper terminal and other is the tool i have written by myself (see the code attached) in hope that i can configure accurate baudrate (which is according to the calculation is 4464.28kbps) that is not supported by hyperterminal. and i am even not sure that 4464kbps which i have used in my tool is supported by windows API or not.

    what i have observed is, i get some junk characters on hyperterminal only when i connect the cable (its only once, but my controller is continuously sending the character to the PC). that is strange. why?

    another question is, as my caculated baudrate is 4464.28 (according the timer value i have loaded). is that okay to configure 4800 on hyperterminal and expect the correct charater on screen? or its too much diff to end up in junk character? and i have to change my crystal to some 11.059 or something else that can give me the accurate baudrate of 4800 or some other standard value?

    or any other solution?

    what should be the value of flow control in hyperterminal settings? hardware, None, or Xon/Off?

    my code running in microcontroller (written & compiled with keil)
    Code (text):

    #include <stdio.h>
    #include <REGX51.H>

    #define MICRO_FREQUENCY    12000000.0  // frequency of micro...    

    typedef unsigned char BYTE;
    typedef unsigned long ULONG;
    typedef unsigned int WORD;

    int waiting_for_ti = 1;

    #define UART0_VECTOR       4           //0x23 Serial Port 0        

    volatile BYTE TxBuffer[3];  
    volatile BYTE TxInChar;
    volatile BYTE TxEnabled;

    //=====================================================================
    // init routine for ISR handler...                                    
    //=====================================================================
    void SER_init()
    {
       /* disable interrupts...       */
       EA          = 0;
       
       /* clear com buffer indexes... */
       TxEnabled   = 0;
       
       /* Setup serial port registers */
       SM0         = 0;
       SM1         = 1;           // serial port MODE 1
       SM2         = 0;
       REN         = 0;           // enable serial receiver
       TI          = 0;           // clear transmit interrupt
       RI          = 0;           // clear receiver interrupt
       ES          = 1;           // enable serial interrupts
       PS          = 0;           // set to low priority
       EA          = 1;           // Enable Interrupts
    }
    //=====================================================================
    //=====================================================================
    void SER_setbaud( ULONG BaudRate )
    {
       /* disable interrupts */
       ES           = 0;
       
       /* Clear interrupt flag and buffer */
       TI           = 0;

       /* transmitter is disabled */
       TxEnabled    = 0;
       
       /* Set timer 1 up as a baud rate generator.  */
       TR1         = 0;           // stop timer 1
       ET1         = 0;           // disable timer 1 interrupt
       PCON       |= 0x80;        // 0x40=SMOD1: set serial baudrate doubler
       TMOD       &= 0x0F;        // clear timer 1 mode bits
       TMOD       |= 0x20;        // put timer 1 into MODE 2 : 8-bit, auto-reload
       TH1         = (BYTE) (256.0 - (MICRO_FREQUENCY / (192.0 * (float)(BaudRate))));
       TR1         = 1;           // start timer 1
       
       /* enable interrupts */
       ES           = 1;
    }
    //=====================================================================
    //=====================================================================
    void SER_ISR() interrupt UART0_VECTOR using 2
    {
       if( TI )
       {
            waiting_for_ti = 0;
       }
    }


    //=====================================================================
    //=====================================================================
    void putmychar( char ThisChar )
    {
       
       /* add this character to the transmit buffer */
       ES = 0;
       waiting_for_ti = 1;
       SBUF = ThisChar;
       ES = 1;
       while(waiting_for_ti != 0)
       {
       }
       
       
       /* return character as default value */
    }
         

    void main()
    {
       // initialize serial interface...
       SER_init();
       SER_setbaud( 4800 );
       // loop forever...
       while(1)
       {
            //wait willbe handle in Putmychar function
            putmychar( 'C' );
       }
    }
     
    The Code i m using in my PC tool,
    Code (text):

    // Hypertrm.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"

    #define TIMEOUT_CONSTANT    50
    #define ESC                 27


    int main(int argc, char* argv[])
    {
        int          key_pressed   = 0;
        char         outchar       = 0;
        char         inchar        = 0;
        DWORD        bytes_written = 0;    // Number of bytes written to port
        DWORD        bytes_read    = 0;    // Number of bytes read from port
        COMMTIMEOUTS tempComTimeouts;      // Our temporary time-outs for COM1
        COMMTIMEOUTS savedComTimeouts;     // Stores the original time-outs
        HANDLE       comport       = NULL; // Handle for COM port
        DCB          comSettings;          // Contains various port settings
        char port[10];
        long baudrate;
        int databits;
        char parity;
        double stopbits;
        char flowcontrol;

        //printf("Sample UART Loopback Terminal Program v1.00.\n");
        //printf("(c)Copyright Sealevel Systems, Inc., 1999.\n\n");
        if(argc < 7)
        {
            printf("\nInvalid number of argument\n");
            return 1;
        }

        strncpy(port, argv[1], 10);
        baudrate = atol(argv[2]);
        databits = atoi(argv[3]);
        parity = *argv[4];
        stopbits = atof(argv[5]);
        flowcontrol = *argv[6];

       
        // Open COM port
        if ((comport =
             CreateFile(port,
                        GENERIC_READ | GENERIC_WRITE, // for reading and writing
                        0,                            // exclusive access
                        NULL,                         // no security attributes
                        OPEN_EXISTING,              
                        FILE_ATTRIBUTE_NORMAL,
                        NULL)) == INVALID_HANDLE_VALUE)
        {
            printf("Unable to open COM1.\n\n");
            printf("Press any key to exit.");
            getch();
            return(1);
        }

        printf("%s opened.\n\n", port);

        // Save time-out parameters for COM1
        GetCommTimeouts(comport,&savedComTimeouts);
       
        // Set our time-outs
        tempComTimeouts.ReadIntervalTimeout         = TIMEOUT_CONSTANT;
        tempComTimeouts.ReadTotalTimeoutMultiplier  = TIMEOUT_CONSTANT;
        tempComTimeouts.ReadTotalTimeoutConstant    = TIMEOUT_CONSTANT;
        tempComTimeouts.WriteTotalTimeoutMultiplier = TIMEOUT_CONSTANT;
        tempComTimeouts.WriteTotalTimeoutConstant   = TIMEOUT_CONSTANT;
        SetCommTimeouts(comport,&tempComTimeouts);

        // Set Port parameters.
        // We make a call to GetCommState() first in order to fill
        // the comSettings structure with all the necessary values.
        // Then we change the ones we want and call SetCommState().
        GetCommState(comport, &comSettings);

        comSettings.BaudRate = baudrate;
        switch(parity) {
            case 'N':
                        comSettings.Parity      = NOPARITY;
                        comSettings.fParity     = FALSE;
                        break;
            case 'E':
                        comSettings.Parity      = EVENPARITY;
                        comSettings.fParity     = FALSE;
                        break;
            case 'O':
                        comSettings.Parity      = ODDPARITY;
                        comSettings.fParity     = FALSE;
                        break;
        }
        if(stopbits == 1)
            comSettings.StopBits  = ONESTOPBIT;
        else if(stopbits == 1.5)
            comSettings.StopBits  = ONE5STOPBITS;
        else if(stopbits == 2)
            comSettings.StopBits  = TWOSTOPBITS;
        comSettings.ByteSize  = databits;
       
        SetCommState(comport, &comSettings);
       
        printf("Ready to send/receive data. Hit ESC to exit.\n\n");
               
        while(key_pressed != ESC)
        {
            if (kbhit())
            {
                key_pressed = getch();
                outchar = (char)key_pressed;

                if (key_pressed != ESC)
                {
                    // Send data. if succesful, WriteFile() returns non-zero
                    WriteFile(comport,        // Handle
                              &outchar,       // Outgoing data
                              1,              // Number of bytes to write
                              &bytes_written, // Number of bytes written
                              NULL);
                }
            }
           
            // Read data. if succesful, ReadFile() returns non-zero
            ReadFile(comport,     // Handle
                     &inchar,     // Incoming data
                     1,           // Number of bytes to read
                     &bytes_read, // Number of bytes read
                     NULL);
               
            if (bytes_read == 1)
                if (inchar == 13);
                    //printf("\n");
                else
                    printf("%c", inchar);
        }

        // Restore time-out parameters
        SetCommTimeouts(comport,&savedComTimeouts);
        CloseHandle(comport);
       
        printf("\n");

        return(0);
    }
     
    any help would be greatly appreciated
     

    Attached Files:

  2. rushi53

    rushi53 Member

    Joined:
    May 8, 2009
    Messages:
    112
    Likes:
    6
    Location:
    Pune, India
    Hey maxchirag, hello again :)

    sorry dear, I am not using C for 89s51, so can't help you in code.

    But 2 suggestions from me
    1. Always use 11.0592MHz crystal from serial communication. It will give u exact baud rate
    2. For hyper terminal settings see the attached document.


    Here is the assembly language code which I use for serial communication, see if this could help you.

    Code (text):

    ;==========================================================
    serial_comm     mov scon,#50h
                    mov tmod,#21h
                    mov th1,#f4h
                    mov tl1,#f4h
                    setb tr1

                    mov a,#'A'
                    mov sbuf,a
                    jnb ti,$

                    clr ti
                    ret
    ;==========================================================
     

    Attached Files:

    Last edited: Jun 15, 2010
    • Like Like x 1
  3. maxchirag

    maxchirag New Member

    Joined:
    May 23, 2010
    Messages:
    21
    Likes:
    0
    Hello Rushi,

    Thanks again man,

    I will try to use the assembly you have mentioned on my controller today evening,

    but i think the main issue is baudrate and i have to switch to the crystal 11.059 for now and all future references.

    i have gone thru the document you have sent, but again it does not describe anything about flow control, it only says the value should be "hardware" but i believe the hardware control should be used when we have hardware which can generate inturrupt (like printers and so on) but in my circuit its just plane Tx and Rx. but still i am not sure of that. will check that later after i switch the crystal.

    Thanks Again!
     
  4. dave

    Dave New Member

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


     
  5. Ananthuargn

    Ananthuargn New Member

    Joined:
    Apr 21, 2013
    Messages:
    3
    Likes:
    0
    Location:
    India

    Hello rushi ..
    currently i am doing a project on Touch controlled wheelchair. In which i got the output of X,Y co ordinates of of the touch using PIC controller
    this x,y co ordinates comes as serial data in the following format..
    X:0062 Y:0090 Z:0026
    the serial data format is
    2.JPG

    so i need a coding on 89v51rd2 micro controller to receive the data coming from pic,process the data....and to perform the necessary action (to operate the motor)

    plz help.....
    Waiting for ur reply...
    Thank u......
    Waiting for ur reply..............
     
  6. Jon Wilder

    Jon Wilder Active Member

    Joined:
    Oct 22, 2010
    Messages:
    859
    Likes:
    82
    Location:
    Fresno, CA
    In looking at your schematic, there are some corrections you need to make in hardware first before dealing with software -

    1) Your LCD is connected to the P0 pins. These pins are open drain when 1's are written to the P0 register bits. You must have external pull up resistors on these pins in order for the LCD to work properly. You can use an RN8 bussed resistor network for this. Connect the common pin of the network to VCC, and the rest of the resistor network pins to the P0 pins. Individual resistors connected between each P0 pin and VCC will work also. Something like a 10K resistor on each pin should suffice.

    Then, before you attack the UART issue, verify that the LCD display works by sending it characters from within your main code. If you can send characters to the display from within code and they show up correctly on the display, then you know the display code works and you can then attack the UART portion.

    2) Verify that your charge pump capacitors are 1uF each.

    3) Your reset resistor on the 8051 should be a much lesser value. Use something in the 4.7K - 10K range.

    4) Now for setting the baud rate. There are two equations. One of them is used if PCON.7 is clear, and the other is used if PCON.7 is set (PCON.7 is the double baud rate bit) -

    Equation 1 (PCON.7 = 0) -

    TH1 Reload Value = 256 - ((Crystal MHZ / 384) / Baud)

    Equation 2 (PCON.7 = 1) -

    TH1 Reload Value = 256 - ((Crystal MHz / 192) / Baud)

    Since you are using a 12MHz crystal, I would set bit PCON.7 high (write the value 0x80 to register PCON), then use this reload value -

    256-((12000000 / 192) / 4800) = 242.98

    Round 242.98 to the nearest integer value, which would give you 243, which is hex 0xF3. Then load 0xF3 into TH1 and set timer 1 for 8-bit auto reload (write 0x20 to register TMOD, and 0x40 to register TCON). This will give you an actual baud rate of -

    Actual Baud Rate = Crystal MHz / 192(256 - TH1 Value)

    12000000 / 192(256 - 243) = 4807.69

    This baud value is much closer to actual 4800, and only results in an error percentage of -

    100 ((Actual Baud - Desired Baud) / Desired Baud)

    100((4807.69 - 4800) / 4800) = 0.16%

    This is a VERY small and VERY forgivable error percentage for 4800bps.

    Hope this helps.
     
    Last edited: Apr 22, 2013
  7. Ananthuargn

    Ananthuargn New Member

    Joined:
    Apr 21, 2013
    Messages:
    3
    Likes:
    0
    Location:
    India
    thank u sir ....
    but i got the 22 bytes serial data(image previously uploaded) from pic micro controller and i want to get that serial data in 89v51rd2 micro controller receiver to perform necessary action.
    so that i need the coding for 89v51rd2 sir.
    when i touch the touch screen in one point the data received as ms.jpg
    through serial port software..


    waiting for Ur reply..........
     
  8. Ananthuargn

    Ananthuargn New Member

    Joined:
    Apr 21, 2013
    Messages:
    3
    Likes:
    0
    Location:
    India
    hello sir i need the c program for 89c51 to receive the 22 bytes serial data, which comes from PIC.the received 22 bytes are in the format of 2.JPG .
    in this i need only x, y co-ordinates.at the same time i get lot of x,y value like this left.jpg ms.jpg in terminal software depending upon the range of x,y values, the program should be.
     
  9. Jon Wilder

    Jon Wilder Active Member

    Joined:
    Oct 22, 2010
    Messages:
    859
    Likes:
    82
    Location:
    Fresno, CA
    Try running this code. I just tested it in Keil uVision debug mode and the loop itself appears to be working. Code waits for bit tx_wait to be cleared (gets cleared in tx interrupt), then drops character in SBUF and sets tx_wait, then waits again for tx_wait to go low. As soon as TI goes high, it jumps to the serial interrupt, clears TI and tx_wait, then goes back to the main loop where 'C' is sent again and the cycle repeats. Should repeatedly send the character 'C' from the UART at 4800bps with a 12MHz crystal -

    Code (text):

    #include <REGX51.H>
    #include <stdio.h>

    #define MICRO_FREQ 12000000
    #define UART_BAUD 4800
    #define UART_BRG 256 - ((MICRO_FREQ / 192) / UART_BAUD)

    #define UART0_VECTOR 4

    volatile bit tx_wait = 0;

    void uart(void) interrupt UART0_VECTOR using 2
    {
        if(TI)
        {
            TI = 0;         //acknowledge interrupt by clearing tx interrupt flag
            tx_wait = 0;        //disable tx wait
        }
       
        if(RI)
        {
            RI = 0;
            //place rest of receive interrupt here (if applicable)
        }
    }
       
    void putmychar(unsigned char a)
    {
        while(tx_wait);     //wait for previous tx to complete
        SBUF = a;       //send character
        tx_wait = 1;        //set tx wait flag
    }

    void main(void)
    {
       
    //configure timer 1 as baud rate generator
       
        PCON = 0x80;        //disable baud rate / 2 divider
        TH1 = UART_BRG;     //set baud rate
        TL1 = UART_BRG;
        TMOD = 0x20;        //timer 1 mode 2 - 8-bit autoreload
        TCON = 0x40;        //timer 1 enable
       
    //configure serial port - 8-bit asynchronous UART (mode 1)
       
        SCON = 0x50;        //serial port mode 1, enable serial port
       
    //configure serial port interrupt
       
        IE = 0x90;      //enable serial port interrupt
       
    //main loop - repeatedly send character 'C'
       
        while(1)
        {
            putmychar('C');
        }
       

    }
     
    EDIT: I do not have any MAX232 chips handy, but I was able to use the UART tool function of my PICkit 2 programmer set up for 4800bps and read data directly from the TxD pin on the UART. It is fully functional and repeatedly sends the character 'C' from its UART TxD pin at 4800bps with 12MHz crystal. If my code above does not appear to work on your end, it's got to be a hardware bug of some sort.
     
    Last edited: Apr 23, 2013
  10. Jon Wilder

    Jon Wilder Active Member

    Joined:
    Oct 22, 2010
    Messages:
    859
    Likes:
    82
    Location:
    Fresno, CA
    And of course I write your code...and not only do you NOT let me know whether it worked or not, but not even so much as a "thank you". I see how it is.
     
  11. xainnasir

    xainnasir New Member

    Joined:
    Jan 7, 2012
    Messages:
    19
    Likes:
    0
    Location:
    Lahore Pakistan
    I think y0u should have a look at this tutorial, they have given in detail how to to do Serial communication with 8051 Microcontroller. They have done the two way communication , they are sending data as well as receving data from serial port with 8051 microcontroller.
     

Share This Page