How can I send a string serially from an 8051 only ONCE?

CodeConfused picture CodeConfused · Aug 1, 2009 · Viewed 9.5k times · Source

I am making an 8051 microcontroller communicate wirelessly with a computer. The microcontroller will send a string to its serial port (DB9) and the computer will receive this string and manipulate it.

My problem is that I do not know how to make the 8051 transmit the string just once. Since I need to manipulate the string at the PC end it has to be received only one time. Currently, even though in the C code I am sending the string once, on my computer I am receiving the same string continuously. I assume this is because whatever is in the SBUF is continuously transmitted. Is there any way that I can send my string only once? Is there a way to empty the SBUF?

I tried to use the RTS (Request to Send) pin (7th pin) on the DB9 because I read somewhere that if I negated the voltage on that pin it would stop the flow of data to the serial port. So what I did was programmed my microcontroller to send the string and then sent logic level 0 to an output pin that was connected to my DB9 RTS pin. However, that didn't work.

Does anyone have any suggestions? I'd really appreciate them.

EDIT

The software that I'm using on the PC is X-CTU for Xbee modules. This is the code on my microcontroller:

include reg51.h 
void SerTx(unsigned char);  
void main(void)  
{  
  TMOD = 0x20;  
  TH1 = 0xFD;  
  SCON = 0x50;  
  TR1 = 1;   

  SerTx('O');  
  SerTx('N');  
  SerTx('L');  
  SerTx('Y'); 

}

void SerTx(unsigned char x)  
{  
  SBUF = x;  
  while(TI==0);   
  TI = 0;   
}  

Could someone please verify that it is in fact only sending the string once?

EDIT

Looks like Steve, brookesmoses and Neil hit the nail on the head when they said that it was what was happening AFTER my main function that was causing the problem. I just tried the suggested code Steve put up (more specifically the for(;;); and defining serTX outside of main) and it worked perfectly. The controller is probably rebooted and hence the same code keeps repeating itself.

Thanks so much for the help! :)

Answer

Steve Melnikoff picture Steve Melnikoff · Aug 1, 2009

Can you confirm that the 8051 really is sending the data only once? One way to check would be to use a scope to see what is happening on the UART's TX pin.

What software are you using on the PC? I'd suggest using simple communications software like HyperTerminal or PuTTY. If they are showing the string being sent to the PC multiple times, then chances are the fault is in the software running on the 8051.

EDIT: To be honest, this sounds like the kind of debugging that engineers have to face on a regular basis, and so it's a good opportunity for you to practise good old-fashioned methodical problem-solving.

If I may be very blunt, I suggest you do the following:

  1. Debug. Try things out, but don't guess. Experiment. Make small changes in your code and see what happens. Try everything you can think of. Search the web for more information.
  2. If that doesn't produce a solution, then return here, and provide us with all the information we need. That includes relevant pieces of the code, full details of the hardware you're using, and information about what you tried in step 1.

EDIT: I don't have the rep to edit the question, so here's the code posted by the OP in the comment to her question:

#include<reg51.h>

void SerTx(unsigned char);

void main(void)
{
    TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1;
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y');

    void SerTx(unsigned char x)
        { SBUF = x; while(TI==0); TI = 0; } 
}

As Neil and Brooksmoses mention in their answers, in an embedded system, the main function is never allowed to terminate. So you either need to put your code in an infinite loop (which may be what is inadvertently happening), or add an infinite loop at the end, so the program effectively halts.

Also, the function SerTx should be defined outside main. This may be syntatically correct, but it keeps things simple not declaring functions within other functions.

So try this (I've also added some comments in an attempt to make the code easier to understand):

#include<reg51.h>

void SerTx(unsigned char);

void main(void)
{
    /* Initialise (need to add more explanation as to what
        each line means, perhaps by replacing these "magic
        numbers" with some #defines) */
    TMOD = 0x20;
    TH1  = 0xFD;
    SCON = 0x50;
    TR1  = 1;

    /* Transmit data */
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y');

    /* Stay here forever */
    for(;;) {}

}

void SerTx(unsigned char x)
{
    /* Transmit byte */
    SBUF = x;

    /* Wait for byte to be transmitted */
    while(TI==0) {}

    /* Clear transmit interrupt flag */
    TI = 0;
}