Discussion in "8051 Discussion Forum" started by    DavesGarage    Dec 4, 2009.
Fri Dec 04 2009, 05:18 PM
#1
A serial interface to the outside world is a fantastic way to speed development in your 8052 project. If you know your serial interface is working, you can use it to debug your code when other methods for debugging aren't available (like an ICE, or JTAG, etc... ).

Getting your first piece of code running on a new target system is always a challenge, and even the simplest program (Hello World) requires an output device.

The goal of this thread is to help you get your first program up and running, and get your microcontroller talking to your PC through the Hyperterminal emulator.

I'd like to personally thank Rickey's World member Abhinav.Chaurey for taking the time to verify/validate the software in this thread.

 Abhinav.Chaurey like this.
Fri Dec 04 2009, 05:34 PM
#2
So, where to start?

Firstly, we make a couple of assumptions about our target system:

The crystal frequency will be 11.0592Mhz, and the processor will be a 12-clock/instruction processor.

so, here is the first part of the software:

//=====================================================================
// simple example software for testing serial interface...             
//=====================================================================
#include "AT89X51.H"            
#include <stdio.h>


We include a header that has our special function registers defined for us. I'm using the Keil development environment, and this header came with it... We also include the stdio.h header, since that's where our printf(...) function is declared...

Next, we make a few definitions:
#define BUF_SIZE           16          // buffer size for both Rx   
                                       // and Tx buffers            
#define MICRO_FREQUENCY    11059200.0  // frequency of micro...     

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

#define UART0_VECTOR       4           //0x23 Serial Port 0         

volatile BYTE TxBuffer[ BUF_SIZE ];   
volatile BYTE RxBuffer[ BUF_SIZE ];   
volatile BYTE RxInChar;
volatile BYTE RxOutChar;
volatile BYTE TxInChar;
volatile BYTE TxOutChar;
volatile BYTE TxEnabled;


The first thing declared is the size of our buffer - this is an 8-bit value, so it should be somewhere between 1 and 255 - I chose 16 bytes as an example, but you can increase this depending on your memory size.

Next, we define the crystal frequency we're using - 11.059Mhz on an 8052 can get you up to 56k baud - a 22.059Mhz crystal can get you 115.2k baud - for this example, I'm using 11.059Mhz as an example.

Next, we define the vector number for the UART - this is pretty much the same for all basic 8052 micros.

And finally, we define our variables:

TxBuffer and RxBuffer are the transmit and receive buffers.
RxInChar and RxOutChar are pointers into the receive buffer.
TxInChar and TxOutChar are pointers into the transmit buffer.
TxEnabled is a flag for transmitting characters that are waiting in the transmit buffer...



[ Edited Fri Dec 04 2009, 06:16 PM ]
Fri Dec 04 2009, 05:39 PM
#3
Next, we define a function to initialize our serial interface interrupt:

//=====================================================================
// init routine for ISR handler...                                     
//=====================================================================
void SER_init()
   {
   /* disable interrupts...       */
   EA          = 0;
   
   /* clear com buffer indexes... */
   TxInChar    = 0;
   TxOutChar   = 0;
   TxEnabled   = 0;
   RxInChar    = 0;
   RxOutChar   = 0;
   
   /* Setup serial port registers */
   SM0         = 0; 
   SM1         = 1;           // serial port MODE 1 
   SM2         = 0;
   REN         = 1;           // 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 
   }



The process is outlined in the comments above. When your comments are complete, there is no need to expound on what you are trying to accomplish.

Fri Dec 04 2009, 05:52 PM
#4
Now we need to define the actual interrupt service routine...

//=====================================================================
//=====================================================================
void SER_ISR() interrupt UART0_VECTOR using 2
   {
   /* Received value interrupt    */
   if( RI )
      {
      RI = 0;

      /* get byte if there's room in the buffer */
      if( ((RxInChar + 1)%BUF_SIZE) != RxOutChar )
         {
         RxBuffer[ RxInChar++ ] = SBUF;
         RxInChar %= BUF_SIZE;
         }
      }

   /* Transmitted value interrupt */
   if( TxEnabled )
      {
      /* if previous byte is finished transmitting */
      if( TI )
         {
         TI = 0;

         /* adjust queue and transmit character... */
         if (TxOutChar != TxInChar)
            {
            SBUF = TxBuffer [TxOutChar++];
            TxOutChar %= BUF_SIZE;
            }
         else
            /* nothing else to transmit, so disable function... */
            TxEnabled = 0;
         }
      }
   }


This routine gets executed every time the UART interrupt flags get set: either the RI or TI flag.

The routine is identified as "interrupt 4", which is the proper interrupt for the UART0, and is defined as using register set 2. For more information on register sets, you can read the "8052 bible" documents, listed at the end of this thread.

Here is the basic flow of the function:

1. if the receive flag was set, reset it, and if there's room in the receive buffer, get the byte and add it to the buffer, otherwise, ignore the byte - it will be lost
2. if the transmit flag was set, and our transmit process is enabled, reset the flag, and if there's another byte in the transmit buffer, grab it and send it. If there isn't another byte to send, the transmit process is over.


Fri Dec 04 2009, 05:57 PM
#5
We're almost done now...

We need a routine to set the baud rate:

//=====================================================================
//=====================================================================
void SER_setbaud( ULONG BaudRate )
   {
   /* disable interrupts */
   ES           = 0;
   
   /* Clear interrupt flag and buffer */
   TI           = 0;
   TxInChar     = 0;
   TxOutChar    = 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;
   }


Again, the comments speak for themselves, but the basic idea here is whenever we change the baud rate, we disable the interrupts, delete whatever is in the transmit buffer, reprogram the timer that generates the baud rate, and re-enable the interrupts.
Fri Dec 04 2009, 06:00 PM
#6
The last thing we'll need is a putchar(), getchar(), and kbhit() function to round out this example:

//=====================================================================
//=====================================================================
char putchar( char ThisChar )
   {
   /* wait if buffer is full... */
   while( ( (TxInChar+1) % BUF_SIZE) == TxOutChar );
   
   /* add this character to the transmit buffer */
   ES = 0;
   TxBuffer[ TxInChar++ ] = ThisChar;
   TxInChar %= BUF_SIZE;

   /* if transmitter is disabled enable it */
   if( !TxEnabled )           
      {
      TxEnabled = 1;
      TI = 1;
      }
   
   ES = 1;

   /* return character as default value */
   return( ThisChar );
   }

//=====================================================================
//=====================================================================
char getchar()
   {
   volatile char c;
   
   while(RxInChar == RxOutChar);
   ES = 0;                         /* Disable Interrupts */
   c = RxBuffer[ RxOutChar++ ];
   RxOutChar %= BUF_SIZE;
   ES = 1;                         /* Enable Interrupts */
   
   return( c );
   }

//=====================================================================
//=====================================================================
BYTE kbhit()
   {
   /* nothing to get? */
   if( RxInChar == RxOutChar )
      {   
      return (0);
      }

   /* something in buffer... */
   return( 1 );
   }


The putchar() function adds a byte to the transmit buffer (if there is room), the getchar() function grabs a byte from the receive buffer (if there is any), and the kbhit() function ( sounds like "keyboard hit?") checks the receive buffer to see if there is anything to grab. ac

Fri Dec 04 2009, 06:04 PM
#7
Finally, we need the main() function. I've written a simple main() that will utilize all of our functions, and echo characters back to Hyperterminal when you type.

//=====================================================================
//=====================================================================
void main()
   {
   char ThisChar;

   // initialize serial interface...
   SER_init();
   SER_setbaud( 19200 );

   printf("Keyboard Echo active\r\n");
   
   // loop forever...
   while(1)
      {
      // if the keyboard is hit, handle the incoming character...
      if( kbhit() )
         {
         ThisChar = getchar();
         putchar( ThisChar );
         
         // add line feed to all returns...
         if( ThisChar == 0x0D )
            putchar( 0x0A );
         }
      }
   }


Just make sure Hyperterminal is set to the same baud rate that your software is set for - in this example, I chose 19200, but you can choose whatever best fits (up to the limitations of your processor crystal, of course).

Have fun with this, and feel free to comment on your experiences...
Thu Mar 29 2012, 02:35 PM
#8
Thank you sir,

It is very informative article. I have used this code in my design & is working very well. Can you please describe how can I get a string instead of a single character from the serial port? The characters should get accumulated in the receive buffer until a carriage return is detected. In my main routine I will check for the string.

Thanks.

Thu Mar 29 2012, 07:08 PM
#9


Thank you sir,

It is very informative article. I have used this code in my design & is working very well. Can you please describe how can I get a string instead of a single character from the serial port? The characters should get accumulated in the receive buffer until a carriage return is detected. In my main routine I will check for the string.

Thanks.

vbdev


Dave's been busy recently so may not visit anytime soon.
Have a look through 8051 forum threads for examples of serial buffering.
Create a new thread if you can't find an answer.

Get Social

Information

Powered by e107 Forum System

Conversation

Mon Oct 21 2019, 08:46 AM
charmdatemru
cooking
Sun Oct 13 2019, 02:02 AM
Aline Hutchinson
Hey there,
ExperimenterUK
Sat Oct 12 2019, 10:23 PM
Log in.. then post your code in the 8051 forum
Sat Oct 12 2019, 10:18 AM
Bhadra Sajikumar
i am doing a countdown timer with 8051 for my project, unfortunately our professor had to take a leave of absence before he could teach us most of it.. can someone explain the .asm code of it for me?
Mon Sep 23 2019, 07:37 AM
Nathaniel
I am doing a project for my schools wireless security system with cameras,sensors and spot lights using 8051 micro controller, could you help me out with the design and its source code.
Wed Sep 18 2019, 08:48 PM
Caryn Kover
Thank you for your time,
ExperimenterUK
Mon Aug 05 2019, 07:09 PM
@Ismail ..post in forum, give details
Mon Aug 05 2019, 04:33 PM
Ismail balghmi
Hello. Please I won't download
ExperimenterUK
Wed Jul 24 2019, 12:47 AM
@BUSTER123 Please post in the forum
Tue Jul 23 2019, 06:13 PM
BUSTER123
hello! newbie here. i am kind of a guy who hates using ready - made existing libraries, so this helped a lot as i was trying to control and write to a character lcd display. however, i can't figure out how to set the cursor position. for example, i want to set it to the 5th column in the first row, so position 5. so according to the table, i am sending 10000101 on the 8 data lines of the lcd (register select pulled low). the cursor does not move there however. and i cant move the cursor left or right too. is it something wrong that i am doing? thank you.

Downloads

Comments

ilylily07
Tue Oct 15 2019, 04:32 PM
hientran123
Tue Oct 15 2019, 02:27 AM
Sat Oct 05 2019, 02:38 PM
zexalo
Thu Oct 03 2019, 09:53 AM
thanhle12345
Thu Oct 03 2019, 07:37 AM
ramon_vsc
Fri Sep 20 2019, 04:53 PM
youssoufba
Thu Sep 19 2019, 11:57 AM
Taiphan000
Tue Sep 17 2019, 04:21 AM

Online

Guests: 42, Members: 0 ...

most ever online: 182184
(Members: , Guests: 182184) on 06 Aug 2010: 05:37 AM

Members: 38097
Newest member: ilylily07
Forum Activity
wimac Avatar
Posted By wimac
Mon Oct 21 2019, 09:18 AM
I’ve been following this thread and looking at the...
s_dinesh40@yahoo.com Avatar
Posted By [email protected]
Sun Oct 20 2019, 03:09 PM
s_dinesh40@yahoo.com Avatar
Posted By [email protected]
Sun Oct 20 2019, 03:02 PM
sir, when i on display ,sometime 3rd display is no...
s_dinesh40@yahoo.com Avatar
Posted By [email protected]
Sun Oct 20 2019, 02:53 PM
sir, when i on display ,sometime 3rd display is no...
ExperimenterUK Avatar
Posted By ExperimenterUK
Sun Oct 20 2019, 12:21 AM
Your code seems okay on my simulationTry my code o...
ExperimenterUK Avatar
Posted By ExperimenterUK
Sun Oct 20 2019, 12:21 AM
Your code seems okay on my simulationTry my code o...
s_dinesh40@yahoo.com Avatar
Posted By [email protected]
Sat Oct 19 2019, 07:13 PM
please find video attachment. 3rd & 4th displa...
s_dinesh40@yahoo.com Avatar
Posted By [email protected]
Sat Oct 19 2019, 07:05 PM
sir, 3rd and 4th dot matrix display flickering, ...
ExperimenterUK Avatar
Posted By ExperimenterUK
Fri Oct 18 2019, 09:18 PM
Hopefully you understand some of the program.Which...
s_dinesh40@yahoo.com Avatar
Posted By [email protected]
Thu Oct 17 2019, 09:38 PM