4
\$\begingroup\$

I will like to know if a baud-rate of 9600 is so fast for an 8051 MCU using an 11.0952Mhz crystal. Why? I have observed some inconsistency in the behavior of my MCU, in that when I send a set of characters looking for a particular character to perform certain operations, I discover that my MCU does not perform the required operation. Meaning that there was a misplacement along the line during receiving. Then I did some serial routine. I sent a "ABC" from terminal to the MCU, which should transmit back to the terminal an increment of each character sent, hence it should give "BCD". But this is what i got consistently - "BD" missing "C". Meaning that the MCU missed "B". I also send other set of characters and discovered that some characters get missed by the MCU. What could be the cause of this. Could it be the Baud-rate or in my code. How can I possibly rectify this.

Here is the code.

void initUART()
{
  SCON = 0x50;
  TMOD = 0x20;
  TH1 = TL1 =-3;
  TR1 = 1;
}

void sendCHAR()
{
  SBUF = uartBUFF[s];
  while(!TI);
  TI=0;
}

void serial_isr(void) interrupt 4  
{
  if (RI)
  {
    RI = 0;
    tmpBUFF = SBUF;
    charFLAG=1;
  }
}

main()
{
  IE= 0x91;
  initUART();
  while (1)
  {
    if(charFLAG)
    {
      SBUF = (tmpBUFF+1);
      while(!TI);
      TI=0;
      charFLAG = 0;
    }
  }
}

Thanks!

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you post your source code/assembly? \$\endgroup\$ – Toby Jaffey May 9 '11 at 19:54
  • \$\begingroup\$ Please view the source file below \$\endgroup\$ – Paul A. May 10 '11 at 8:26
  • \$\begingroup\$ I can't see any source? You could edit it into your question \$\endgroup\$ – Toby Jaffey May 10 '11 at 8:27
  • \$\begingroup\$ void initUART() { SCON = 0x50;TMOD = 0x20; TH1 = TL1 =-3;TR1 = 1; } void sendCHAR() { SBUF = uartBUFF[s]; while(!TI); TI=0; } void serial_isr(void) interrupt 4 { if (RI) {RI = 0; tmpBUFF = SBUF; charFLAG=1;} } main() { IE= 0x91; initUART(); while (1) { if(charFLAG) { SBUF = (tmpBUFF+1); while(!TI); TI=0; charFLAG = 0; } } } \$\endgroup\$ – Paul A. May 10 '11 at 8:36
3
\$\begingroup\$

How do you get the characters from the serial port buffer register? If you simply read them in a loop like

void main() {       
  char c;
  while (1) {
    c=SBUF;
    do_something(c);
  }
}

Then you will miss characters once the execution time of do_something() gets longer. Note that this includes time spend in intterrupts. The 8051 serial port has no hardware fifos, a character will be overwritten by the next one if it was not read in time.

Our solution was to read the characters into a Ringbuffer during the serial Intterupt, and to use the FIFO in the main loop. Works (with high priority interrupt) for 460800 Baud with 7,3728 MHz crystal on a Silabs 80C51FXXX.

Update

As we now see the source coude, the bug is now clear: You wait in the main loop for your character to be sent. But that means you wait a whole "character time" without being able to read your interrupt character buffer, and another few cyles to detect and read the next. This is too long if the sender sends characters fast, as a PC does.

\$\endgroup\$
  • \$\begingroup\$ void initUART() { SCON = 0x50;TMOD = 0x20; TH1 = TL1 =-3;TR1 = 1; } void sendCHAR() { SBUF = uartBUFF[s]; while(!TI); TI=0; } void serial_isr(void) interrupt 4 { if (RI) {RI = 0; tmpBUFF = SBUF; charFLAG=1;} } main() { IE= 0x91; initUART(); while (1) { if(charFLAG) { SBUF = (tmpBUFF+1); while(!TI); TI=0; charFLAG = 0; } } } \$\endgroup\$ – Paul A. May 10 '11 at 8:34
  • \$\begingroup\$ Looking at the original poster's code, you're right, he needs a ring buffer. Here's one google threw up 8052.com/codelib/files/efdUartDriver.zip \$\endgroup\$ – Toby Jaffey May 10 '11 at 9:37
  • \$\begingroup\$ Updated my answer as question now contains code. \$\endgroup\$ – Turbo J May 10 '11 at 13:54
  • \$\begingroup\$ I got it figured out. I simple applied "tubor J" sugggestions ( who contributed above) and it worked good. Just ensure that you save all information when serial communication is going on, in a buffer. Then after, make use of the variables in the buffer. This prevents characters from been lost. Thank to all! \$\endgroup\$ – Paul A. May 11 '11 at 14:31
  • \$\begingroup\$ It's worth noting that with many microcontroller UARTs, it might not be possible to send a byte for every byte that arrives in a continuous stream. If the original sender sends out an absolutely-continuous stream of data with exactly one stop bit per byte, but the controller's baud rate clock is 0.01% slow, then it will eventually lose data unless it has a means of sending out data with only 0.999 stop bits rather than a full stop bit. The difference between 1 stop bit and 0.999 may seem trivial, but it can add up. If a controller had more precise baud-rate control... \$\endgroup\$ – supercat Mar 25 '14 at 15:15
3
\$\begingroup\$

With a 11.0952 MHz crystal the maximum bitrate for the 8051 is 57600 bps, so that should not be the problem. Besides, you do seem to receive some characters OK. You may want to check the answers to your other question again if you're not sure about the bitrate.

\$\endgroup\$
  • \$\begingroup\$ You may have missed that Paul A. posted the question you linked... \$\endgroup\$ – Kevin Vermeer May 9 '11 at 17:56
  • \$\begingroup\$ Yes! I am using a baudrate 9600. And I am sure of the settings. And also I am recieving some characters but it appears that some characters get missing. Appearing like the transfer rate of the character is faster for the micro controller to recieve while it is still processing an earlier received character. \$\endgroup\$ – Paul A. May 9 '11 at 17:58
  • \$\begingroup\$ @reemrevnivek - Yes, I missed that :-) \$\endgroup\$ – stevenvh May 10 '11 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.