To implement software UART successfully one must understand the basics of UART first and understand its protocol. As mentioned in our UART Basics tutorial. For 8bit, no parity and 1 stop bit UART Transmission, 10 bits are transmitted (startbit, 8-data bits and stop bit). There is a formula to calculate the delay time for 1 bit which is needed between bits to get correct baudrate.

1 bit time = (((crystal/baud)/12) - 5) / 2

Where crystal is the frequency of crystal in Hz baud is the required baudrate we are doing divide by 12 as 8051 architecture single machine cycle is crystal freq/12

Below is a software implemented UART, which can be used in C as well as Assembly programs. It is written for Keil software. But with a little modification you can use it in your programs.

?SU?PUTC SEGMENT CODE
?SU?GETC SEGMENT CODE

PUBLIC _putc
PUBLIC getc

txd_pin	EQU	P3.1		;Transmit on this pin
rxd_pin	EQU	P3.0		;Receive on this pin

;Formula to calculate the bit time delay constant
;This constant is calculated as: (((crystal/baud)/12) - 5) / 2
;crystal is the frequency of crystal in Hz
;baud is required baudrate
;Please try to keep baudrate below 9600
;to get best results :)

BITTIM	EQU	45;		(((11059200/9600)/12) - 5) / 2

;--------------------------------------------
;To send data serially
;For C programs
;Protype definition:
;		void putc(unsigned char);
;Usage:
;		putc(data);
;Return:
;		This function returns nothing
;
;For Assembly Programs:
;
;Usage:
;	data to be send has to be moved to R7
;	for example:
;		mov R7,#'a'
;		lcall _putc
;--------------------------------------------
RSEG ?SU?PUTC
_putc:
	push ACC
	Push PSW
	mov a,r7
	CLR txd_pin			;Drop line for start bit
	MOV R0,#BITTIM		;Wait full bit-time
	DJNZ R0,$			;For START bit
	MOV R1,#8			;Send 8 bits
putc1:
	RRC A				;Move next bit into carry
	MOV txd_pin,C		;Write next bit
	MOV R0,#BITTIM		;Wait full bit-time
	DJNZ R0,$			;For DATA bit
	DJNZ R1,putc1		;write 8 bits
	SETB txd_pin		;Set line high
	RRC A				;Restore ACC contents
	MOV R0,#BITTIM		;Wait full bit-time
	DJNZ R0,$			;For STOP bit
	POP PSW
	pop ACC
	RET

;--------------------------------------------
;To receive data Serially
;If you want to use this routine in your
;C program then define function prototype
; as:
;	unsigned char getc(void);
;
;	Usage:
;		data = getc();
;	Return value:
;		Returns data received
;
;
;If you are using it in assembly program
;	Usage:
;		lcall getc
;	Return:
;		data received is stored in R7
;--------------------------------------------

RSEG ?SU?GETC
getc:	
	Push ACC
	Push PSW
	JB rxd_pin,$		;Wait for start bit
	MOV R0,#BITTIM/2	;Wait 1/2 bit-time
	DJNZ R0,$			;To sample in middle
	JB rxd_pin,getc		;Insure valid
	MOV R1,#8			;Read 8 bits
getc1:
	MOV R0,#BITTIM		;Wait full bit-time
	DJNZ R0,$			;For DATA bit
	MOV C,rxd_pin		;Read bit
	RRC A				;Shift it into ACC
	DJNZ R1,getc1		;read 8 bits
	mov r7,a
	POP PSW
	pop ACC
	RET					;go home

Now you can have two serial ports or even 3 :) on a normal 8051. Have a happy programming.

See Also

Help & Queries

If you have any queries, doubts or feedback on this tutorial please share in our discussion forum.

Powered by MediaWiki
This page was last modified on 3 March 2015, at 14:18.
ArrayContent is available under Creative Commons Attribution Non-Commercial Share Alike unless otherwise noted.