9-Embedded C Serial Port Program-12-08-2024
9-Embedded C Serial Port Program-12-08-2024
• How to program SCON SFR to configure serial interface in different modes of operation
• Setting the Serial Port Modes
Pseudo code
• Writing a byte to the serial port
• Reading a byte from the serial port
• Hands on
o Transfer letter 'A' serially at 4800 baud rate continuously using 8b data and 1 stop and
start bits
o Transfer message “YES' serially at 9600 baud rate continuously, 8b data, 1 stop bit and
start bit
o Echo back the user input using serial port (use polling) (Receive and transmit back)
o Using printf() from standard io libraries
o Writing ISR for serial interrupt
• Why serial data communication
o Cost
o Noise
o Availability of suitable media
o Inherent device characteristics
o Small connector
o Distributed computing
o sensor networks
• How to program SCON SFR to configure serial interface in different modes of operation
o Mode 0 – shift register 8b – 12MHz – 1Mbps – higher rate
o Mode 1 – 8b UART – normal usage – variable and programmable baud rate
o Mode 2 and 3 – 9b UART – multi processor communication
Higher baud rates (divide by 32 or 64) or variable
o RB8
8 th bit received in 9b serial mode that goes into this RB8 bit
o TI
used for interrupting the processor after the completion of tx of 1
byte of data
Automatically set by hw after tx of a byte of data
Can be reset by programming or whenever the processor jumpts to
ISR of serial interrupt for TI
o RI
for rx of 1 byte data
Used in the receive mode of data tx whenever we are receiving the
data
After 1 byte of data is received or 9b of data in other modes of
operation – so after 7th or 8th bit is received – hw sets this bit and it
can interrupt the processor
It can be reset from programming or whenever the processor jumps
to IRQ of serial interrupt then this RI bit is resetted automatically
The Synchronous method transfers a block of data at a time, while the asynchronous method transfers a
single byte at a time.
In Synchronous Communication the data get transferred based on a common clock signal.
But in Asynchronous communication, in addition to the data bit, one start bit and one stop bit is added.
These start and stop bits are the parity bits to identify the data present between the start and stop bits.
The 8051 has two pins that are used specifically for transferring and receiving data serially. These two pins
are called TXD and RXD and are part of the Port-3 group (Port-3.0 and Port-3.1). Pin 11 of the 8051 is
assigned to TXD and pin 10 is designated as RXD. These pins are TTL compatible; therefore they require a
line driver to make them RS232 compatible. The line driver chip is MAX232. The MAX232 uses +5v
power source, which is same as the source voltage for 8051.
The 8051 transfers and receives data serially at different baud rates. The baud rate of the 8051 is
programmed into the timers.
Generally Null Modem Connections are used for Data transfer between two devices serially.
Serial Port (UART)
The 8051 includes a standard RS-232 compatible serial port you may use with your application
programs.
One of the 8051s many powerful features is its integrated UART, otherwise known as a serial port.
The fact that the 8051 has an integrated serial port means that you may very easily read and write
values to the serial port.
If it were not for the integrated serial port, writing a byte to a serial line would be a rather tedious
process requiring turning on and off one of the I/O lines in rapid succession to properly "clock
out" each individual bit, including start bits, stop bits, and parity bits.
However, we do not have to do this. Instead, we simply need to configure the serial ports
operation mode and baud rate.
Once configured, all we have to do is write to an SFR to write a value to the serial port or read the
same SFR to read a value from the serial port.
The 8051 will automatically let us know when it has finished sending the character we wrote and
will also let us know whenever it has received a byte so that we can process it.
We do not have to worry about transmission at the bit level--which saves us quite a bit of coding
and processing time.
The 8051 uses port pins P3.1 and P3.0 for transmit and receive respectively.
There are several SFRs that you must properly configure before the serial port will function.
The serial interface is configured with the SFR registers SBUF, SCON and PCON.
In addition, you must also configure Timer 1 or Timer 2 as the baud rate generator.
The 8051 provides full interrupt control for the serial port transmits and receive operations.
You may poll the serial port control registers to determine when a character has been received
(Or)
When the next character may be sent or you may create interrupt routines to handle these
operations
Setting the Serial Port Mode
The first things we must do when using the 8051s integrated serial port is, obviously, configure it.
This lets us tell the 8051 how many data bits we want, the baud rate we will be using, and how the
baud rate will be determined.
First, let’s present the "Serial Control" (SCON) SFR and define what each bit of the SFR
represents:
(*) Note: The baud rate indicated in this table is doubled if PCON.7 (SMOD) is set.
As you can see, selecting the Serial Mode selects the mode of operation (8-bit/9-bit, UART or
Shift register) and also determines how the baud rate will be calculated.
In modes 0 and 2 the baud rate is fixed based on the oscillators frequency.
In modes 1 and 3 the baud rate is variable based on how often Timer 1 overflows.
Generally, whenever a byte has been received the 8051 will set the "RI" (Receive Interrupt) flag.
This lets the program know that a byte has been received and that it needs to be processed.
However, when SM2 is set the "RI" flag will only be triggered if the 9th bit received was a "1".
That is to say, if SM2 is set and a byte is received whose 9th bit is clear, the RI flag will never be
set.
For now it is safe to say that you will almost always want to clear this bit so that the flag is set
upon reception of any character.
REN
The next bit, REN, is "Receiver Enable."
This bit is very straightforward: If you want to receive data via the serial port, set this bit.
They are used when actually sending and receiving data--they are not used to configure the serial
port.
TD8
The TB8 bit is used in modes 2 and 3.
The first 8 data bits are the 8 bits of the main value, and the ninth bit is taken from TB8.
If TB8 is set and a value is written to the serial port, the datas bits will be written to the serial line
followed
by a "set" ninth bit. If TB8 is clear the ninth bit will be "clear."
RD8
The RB8 also operates in modes 2 and 3 and functions essentially the same way as TB8, but on
the reception side.
In this case, the first eight bits received are the data of the serial byte received and the value of the
ninth bit received will be placed in RB8.
TI
TI means "Transmit Interrupt."
When a program writes a value to the serial port, a certain amount of time will pass before the
individual bits of the byte are "clocked out" the serial port.
If the program were to write another byte to the serial port before the first byte was completely
output, the data being sent would be garbled.
Thus, the 8051 lets the program know that it has "clocked out" the last byte by setting the TI bit.
When the TI bit is set, the program may assume that the serial port is "free" and ready to send the
next byte.
RI
Finally, the RI bit means "Receive Interrupt."
It functions similarly to the "TI" bit, but it indicates that a byte has been received.
That is to say, whenever the 8051 has received a complete byte it will trigger the RI bit to let the
program know that it needs to read the value quickly, before another byte is read.
SCON Register
SM0 / SM1 / SM2 / REN / TB8 / RB8 / TI / RI
The Baud Rate is determined based on the oscillator’s frequency when in mode 0 and 2.
o In mode 0, the baud rate is always the oscillator frequency divided by 12.
o This means if your crystal is 11.059 MHz, mode 0 baud rate will always be 921,583
baud.
o In mode 2 the baud rate is always the oscillator frequency divided by 64, so a 11.059Mhz
crystal speed will yield a baud rate of 172,797.
In modes 1 and 3, the baud rate is determined by how frequently timer 1 overflows.
o The more frequently timer 1 overflows, the higher the baud rate.
There are many ways one can cause timer 1 to overflow at a rate that determines a baud rate, but
the most common method is to put timer 1 in 8-bit auto-reload mode (timer mode 2) and set a
reload value (TH1) that causes Timer 1 to overflow at a frequency appropriate to generate a baud
rate.
To determine the value that must be placed in TH1 to generate a given baud rate, we may use the
following equation (assuming PCON.7 is clear).
o TH1 = 256 - ((Crystal / 384) / Baud)
If PCON.7 is set then the baud rate is effectively doubled, thus the equation becomes:
TH1 = 256 - ((Crystal / 192) / Baud)
For example, if we have an 11.059 MHz crystal and we want to configure the serial port to 19,200
baud we try plugging it in the first equation:
TH1 = 256 - ((Crystal / 384) / Baud)
TH1 = 256 - ((11059000 / 384) / 19200 )
TH1 = 256 - ((28,799) / 19200)
TH1 = 256 - 1.5 = 254.5
As you can see, to obtain 19,200 baud on a 11.059Mhz crystal wed have to set TH1 to 254.5.
If we set it to 254 we will have achieved 14,400 baud and if we set it to 255 we will have achieved
28,800 baud.
But not quite... to achieve 19,200 baud we simply need to set PCON.7 (SMOD).
When we do this we double the baud rate and utilize the second equation mentioned above.
Thus we have:
TH1 = 256 - ((Crystal / 192) / Baud)
TH1 = 256 - ((11059000 / 192) / 19200)
TH1 = 256 - ((57699) / 19200)
TH1 = 256 - 3 = 253
Baud Rate
• XTAL frequency = 11.0592
• Machine cycle frequency = 11.0592 / 12 => 921.6 kHz
As we know that 8051 microcontrollers takes 12 clock cycles to complete one machine cycle.
So our effective Instruction execution frequency is Fosc/12. If we are using a crystal of 11.0592MHz; our
efeective frequency is somewhere around Feffective= 11.0592/12 MHz => 921.6 KHz.
8051 UART or serial communication block further divide this frequency (921.6 KHz) by 32 to generate its
baud rate.
Therefore Effective frequency available to generate Baud rates is 921.6 KHz/32 = 28800 Hz.
For a byte to to be transferred via TxD line, it must be placed in the SBUF register.
Similarly SBUF holds the byte of data when it is received by 8051's receive line.
SBUF can be accessed similar to any other register in 8051, but it is not bit addressable.
Hardware Connections
As explained above We need a RS232-TTL level converter to enable 8051 communicate serially with other
RS232 compatible devices. Here is the connection schematic...
If you thought that configuring the serial port was simple, using the serial port will be a breeze.
To write a byte to the serial port one must simply write the value to the SBUF (99h) SFR.
For example, if you wanted to send the letter "A" to the serial port, it could be accomplished as
easily as:
o MOV SBUF,#A
Upon execution of the above instruction the 8051 will begin transmitting the character via the
serial port.
And since the 8051 does not have a serial output buffer we need to be sure that a character is
completely transmitted before we try to transmit the next character.
The 8051 lets us know when it is done transmitting a character by setting the TI bit in SCON.
When this bit is set we know that the last character has been transmitted and that we may send the
next character, if any.
The above three instructions will successfully transmit a character and wait for the TI bit to be set
before continuing.
The last instruction says "Jump if the TI bit is not set to $"--$, in most assemblers, means "the
same address of the current instruction."
Thus the 8051 will pause on the JNB instruction until the TI bit is set by the 8051 upon successful
transmission of the character.
Reading the Serial Port
Reading data received by the serial port is equally easy.
To read a byte from the serial port one just needs to read the value stored in the SBUF (99h) SFR
after the
8051 has automatically set the RI flag in SCON.
For example, if your program wants to wait for a character to be received and subsequently read it
into the
Accumulator, the following code segment may be used:
o JNB RI,$ ;Wait for the 8051 to set the RI flag
MOV A,SBUF ;Read the character from the serial port
The first line of the above code segment waits for the 8051 to set the RI flag; again, the 8051 sets
the RI flag automatically when it receives a character via the serial port.
So as long as the bit is not set the program repeats the "JNB" instruction continuously.
Once the RI bit is set upon character reception the above condition automatically fails and
program flow falls through to the "MOV" instruction which reads the value.
Pseudo code
Transfer letter 'A' serially at 4800 baud rate continuously using 8b data and 1 stop and start bits
Transfer message “YES' serially at 9600 baud rate continuously, 8b data, 1 stop bit and start bit
Echo back the user input using serial port (use polling)
o Configure timer 1 in mode 2 (8b auto reload mode)
o Load the timer 1 TH1 8b register with initial value for given baud rate
(FA for 4800 baud rate)
o Run the timer 1
o Configure the serial port mode to 8b UART with baud rate given by timer 1
Set the receive enable bit
(SCON => SM0 SM1 - REN - - - - = 0101 0000 => 0x50)
o Do infinitely
Poll on RI flag continuously
receive the byte from SBUF //receive the user input char from serial port
reset the RI flag
Send the received byte to SBUF //echo back the received input char back to
serial
Poll on TI flag continuously
Reset the TI flag
Using printf() from standard io libraries – stdio.h
o Include target header file - special function register declarations for the intended 8051
derivative
o Include standard io header filel for prototype declarations of io functions
o Configure timer 1 in mode 2 (8b auto reload mode)
o Load the timer 1 TH1 8b register with initial value for given baud rate
(FA for 4800 baud rate)
o Run the timer 1
o Configure the serial port mode to 8b UART with baud rate given by timer 1
Set the receive enable bit
(SCON => SM0 SM1 - REN - - - - = 0101 0000 => 0x50)
o Do infinitely
Use Printf() to display any message on serial port
Echo back the user input using serial port (use ISR)
o Configure timer 1 in mode 2 (8b auto reload mode)
o Load the timer 1 TH1 8b register with initial value for given baud rate
(FA for 4800 baud rate)
o Run the timer 1
o Configure the serial port mode to 8b UART with baud rate given by timer 1
Set the receive enable bit
(SCON => SM0 SM1 - REN - - - - = 0101 0000 => 0x50)
o Enable global interrupt
o Enable Serial Interrupt (Interrupt source of interest)
o Write an ISR for serial interrupt (irq# 4)
Check for transmit interrupt flag (TI)
• Reset the TI interrupt flag if it is set
Check for receive interrupt flag (RI)
• Read the byte from SBUF
• Reset the RI interrupt flag
• Echo back the received byte to serial port (SBUF)
Transfer letter 'A' serially at 4800 baud rate continuously using 8b data and 1 stop and start bits
SCON = 0x40;
while(1)
{
SBUF = 'A';
while(TI == 0);
TI=0;
}
}
Transfer message “YES' serially at 9600 baud rate continuously, 8b data, 1 stop bit and start bit
#include <at89c51xd2.h>
void main(void)
{
TMOD = 0x20; // Timer 1, 8b auto reload mode
TH1 = 0xFD; //9600 baud rate
TR1 = 1;
SCON = 0x40;
while(1)
{
SerTx('Y');
SerTx('E');
SerTx('S');
}
}
#include <at89c51xd2.h>
void main(void)
{
unsigned char rx_byte;
SCON = 0x50;
while(1)
{
while(RI == 0);
rx_byte = SBUF;
P1 = rx_byte;
RI=0;
SBUF = rx_byte;
while(TI == 0);
TI = 0;
}
}
Using printf() from standard io libraries – stdio.h
#include <REG52.H> /* special function register declarations */
/* for the intended 8051 derivative */
/*------------------------------------------------
The main C function. Program execution starts
here after stack initialization.
------------------------------------------------*/
void main (void)
{
/*------------------------------------------------
Note that an embedded program never exits (because
there is no operating system to return to). It
must loop and execute forever.
------------------------------------------------*/
while (1)
{
TI=1;
P1 ^= 0x01; /* Toggle P1.0 each time we print */
printf ("Hello World\n"); /* Print "Hello World" */
}
}
Echo back the user input using serial port (use ISR)
//Transfer letter 'A' serially at 4800 baud rate continuously.
//USe 8b data and 1 start and stop bit
#include <at89c51xd2.h>
void main(void)
{
/* UART Initialization for 9600 Baud Rate */
SCON = 0x50; // 8 bit mode, receiver enabled
TMOD |= 0x20; // Timer-1 selected as Auto reload mode
TH1 = 0xfd; // 0xfd for 11MHz, oxb2 for 24MHz
TR1 = 1; // Start Timer-1
//enable the interrupts - global access to interrupts and interrupt from serial
//EA - - ES ET1 EX1 ET0 EX0
//1 0 0 1 0 0 0 0
//0x90
//IEN0 = 0x90 or do it using individual bit registers as shown below
#include<at89x52.h>
void main(void)
{
TMOD=0x20; // Timer1 Mode2 8 bit auto reload
TH1=0xFD; // 9600 bps
while(1==1)
{
SBUF='S';
while(TI==0); // Pole TI flag for complete transmission
TI=0;
SBUF='A';
while(TI==0);
TI=0;
SBUF='M';
while(TI==0);
TI=0;
}
}
/********************************************************************
>Example program to send a string serially at 9600 bps.
>Make all connection according to the schematic given above.
>Serial port Mode 1 is used with 8bit data, 1 stop bit, 1 start bit
>One important thing is that all calculations for baud rate generation using Timer1 are made for Timer1 8
bit auto reload mode
********************************************************************/
#include<at89x52.h>
void main(void)
{
TMOD=0x20; // Timer1 Mode2 8 bit auto reload
TH1=0xFD; // 9600 bps
TR1=1; // Timer1 ON
while(1==1)
{
rs_puts("www.electrroons.com\n\r");
}
}