Continue to Site

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.

  • 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.

8051 and Serial Communication with PC

Status
Not open for further replies.

maxchirag

New Member
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:
#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:
// 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
 

Attachments

  • MAX232.JPG
    MAX232.JPG
    49.9 KB · Views: 2,644
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:
;==========================================================
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
;==========================================================
 

Attachments

  • Hyper_Terminal_to_Receive data.doc
    192 KB · Views: 834
Last edited:
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!
 
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..............
 
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:
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 asms.jpg
through serial port software..


waiting for Ur reply..........
 
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.jpgms.jpg in terminal software depending upon the range of x,y values, the program should be.
 
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:
#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:
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.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top