Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Help implementing a 2way serial communication

Status
Not open for further replies.

labrat31

New Member
Attached is what i understand so far of serial communication, my code basically receives one byte then sends it back then jumps back to the start. but sometimes it won’t send back a full string. Is it because it misses receiving bytes when sending a bite?

I want to communicate between my computer and micro using strings of data

I have tried a lot of different ways and tried to modify some example programs I found but I seem to be very stuck and I don’t have any one like a teacher to help me.

I am not overly experienced with this code, if someone has any advice as to what my next step should be I would be so thankful
 
Try this code -

Code:
;*************************************************************************************************
;*************************************************************************************************
;**												**
;**				  RAM Location Name Labels					**
;**												**
;*************************************************************************************************
;*************************************************************************************************	
		
SerData		IDATA		0x30
		
;*************************************************************************************************
;*************************************************************************************************
;**												**
;**					Reset Vector						**
;**												**
;*************************************************************************************************
;*************************************************************************************************		
		
		org		00h		;reset vector
		ajmp		Start

;*************************************************************************************************
;*************************************************************************************************
;**												**
;**				   Interrupt Vector Space					**
;**												**
;*************************************************************************************************
;*************************************************************************************************

;*************************************************************************************************
;*************************************************************************************************
;**												**
;**				  MCU Initialization Routine					**
;**												**
;*************************************************************************************************
;*************************************************************************************************

Start:		mov		PCON,#0x80	;x2 serial baud rate
		mov		TH1,#0xFA	;reload value 250 for 9600bps w/11.059MHz xtal
		mov		TL1,#0xFA 
		mov 		TMOD,#0x20 	;timer 1,mode 2(auto reload)
		mov		TCON,#0x40	;start timer 1
		mov		SCON,#0x50 	;8-bit, 1 stop, REN enabled
				
;*************************************************************************************************
;*************************************************************************************************
;**												**
;**				  	Main Code						**
;**												**
;*************************************************************************************************
;*************************************************************************************************

Transfer:	acall		Rx		;receive data
		acall		Tx		;transmit received data
		ajmp		Transfer

;*************************************************************************************************
;*************************************************************************************************
;**												**
;**				      Serial Receive						**
;**												**
;*************************************************************************************************
;*************************************************************************************************

Rx:		jnb 		RI,Rx 		;wait here for data to be received
		clr		RI		;clear RI flag
		mov		SerData,SBUF	;transfer received data to data buffer			
		ret				;done

;*************************************************************************************************
;*************************************************************************************************
;**												**
;**				      Serial Transmit						**
;**												**
;*************************************************************************************************
;*************************************************************************************************

Tx:		jnb		TI,Tx		;wait here if transmit in progress
		clr		TI		;byte sent, clear tx flag
		mov		SBUF,SerData	;transfer received byte to UART buffer
		ret				;done, UART takes over from here

		end				;end of file

One thing that is nice about the 8051...it supports register to register data transfer without the need to pass it through the accumulator unlike a PIC uC.

Also, you did not set bit 7 in register PCON, which sets the UART up for baud rate x2 to allow you to achieve 9600bps bit rate. I added this instruction in for you.

I also did the serial port initialization as in line code as it only ever needs to be run one time, so not worth canning as a subroutine. Subroutines are for code segments which will be executed repeatedly throughout the main code execution. If you have a code segment that will only ever be executed once, you don't need to can it as a subroutine.

With ANY uC, always check the UART buffer BEFORE you load it with transmit data. This ensures you do not overwrite transmit bytes, allows you to send bytes back to back, and you don't have to keep the main code waiting until the byte is done transmitting once you send it. Just drop the data into the UART buffer to send it, then continue on. Check it before loading the buffer.

The other nice thing you can do is interrupt drive the entire routine, which will enable you to have the MCU doing other things and only servicing the serial data when data gets received.
 
Last edited:
Thank you so much for your input, the code didn’t work out of the box but it did give me a world of help. Seems I had been miss using the ACALL, AJMP and RET.
Also VERY good point with the” check the UART buffer BEFORE you load it with transmit data” thank you
I have had grate success with my code since your post.
Will post my success when I clean it up a bit.
Thank you
 
Ok so this is my working code so far. The UART transmit that u showed me doesn’t seem to be working in my code, have I done something wrong? I have commented it out and am using my original code for now to get it working. I know it don’t flow the best and will prevent me from sending and receiving strings at the same so I would like to know the proper way of doing it?

Also have I used ACALL, AJMP and RET. In the correct manner

Oh and did I start it off the right way using org 00h and org 30h reserving 00h-30h for data?

Thank you
Code:
		org 00h
		
		
		serTx	DATA	    1H
		serRx	DATA	    2H

		byte1	DATA	    3h
		byte2	DATA	    4h
		byte3	DATA	    5h
		byte4	DATA        6h


		org 30h


;#####   UART Initialization   ######

;		MOV TMOD,#20H 	;timer 1,mode 2(auto reload)
;		MOV TH1,#-6 		;4800 baud rate X 2 =9600 
;		MOV	SCON,#50H 	8-bit, 1 stop, REN enabled
;		SETB TR1 			;start timer 1


		mov	PCON,#0x80	;x2 serial baud rate
		mov	TH1,#0xFA 	;reload value 250 for 9600bps w/11.059MHz xtal
		mov	TL1,#0xFA 
		mov 	TMOD,#0x20 	;timer 1,mode 2(auto reload)
		mov	TCON,#0x40	;start timer 1
		mov	SCON,#0x50 	;8-bit, 1 stop, REN enabled

;#####	Main Code	#####

start:	acall Rx
		MOV byte1,serRx
		acall Rx
		MOV byte2,serRx
		acall Rx
		MOV byte3,serRx
		acall Rx
		MOV byte4,serRx


		MOV serTx,byte1
		acall Tx
		MOV serTx,byte2
		acall Tx
		MOV serTx,byte3
		acall Tx
		MOV serTx,byte4
		acall Tx

		ajmp start
		
;#####   UART Transmit And Ricive    #####


Rx:		JNB RI,Rx 			;wait for the last bit
		CLR RI				;clear RI flag
		MOV A,SBUF			
		MOV serRx,A			

		RET




Tx:		MOV A,serTx
 		MOV SBUF,A 			;saving incoming byte in A
TxH:	        JNB TI,TxH 			;wait for the last bit		
		CLR TI 				;get ready to receive next byte

;Tx:		jnb		TI,Tx		        ;wait here if transmit in progress
;		clr		TI			;byte sent, clear tx flag
;		mov		SBUF,serRx	;transfer received byte to UART buffer


		RET
		end
 
Last edited:
Because you were supposed to REPLACE your routines with my routines...not add then in line with your existing code like you did.

Also, your label equates go BEFORE the first org statement...not after. They're not for the chip...they're for the assembler only.

Try this -

Code:
serTx		IDATA	    	0x01
serRx		IDATA	    	0x02
 
byte1		IDATA	    	0x03
byte2		IDATA	    	0x04
byte3		IDATA	    	0x05
byte4		IDATA       	0x06

		org 		0x0000
		ajmp		Start
 
		org 30h
 
 
;#####   UART Initialization   ######
 
Start:		mov		PCON,#0x80		;x2 serial baud rate
		mov		TH1,#0xFA 		;reload value 250 for 9600bps w/11.059MHz xtal
		mov		TL1,#0xFA 
		mov 		TMOD,#0x20 		;timer 1,mode 2(auto reload)
		mov		TCON,#0x40		;start timer 1
		mov		SCON,#0x50 		;8-bit, 1 stop, REN enabled
 
;#####	Main Code	#####
 
Main:		acall		Rx
		mov 		byte1,serRx
		acall		Rx
		mov 		byte2,serRx
		acall		Rx
		mov 		byte3,serRx
		acall 		Rx
		mov 		byte4,serRx
 
 
		mov		serTx,byte1
		acall		Tx
		mov		serTx,byte2
		acall		Tx
		mov		serTx,byte3
		acall		Tx
		mov		serTx,byte4
		acall		Tx
 
		ajmp		Main
 
;#####   UART Transmit And Receive    #####
 
 
Rx:		jnb		RI,Rx 		;wait for the last bit
		clr		RI		;clear RI flag
		mov		serRx,SBUF	;transfer received data to buffer			
		ret
 
 
;Tx:		jnb		TI,Tx		;wait here if transmit in progress
;		clr		TI		;byte sent, clear tx flag
;		mov		SBUF,serTx	;transfer received byte to UART buffer
  		ret				;done

		end

Another thing...in your code when you initialize timer 1 registers TH1 and TL1, don't do "#-6". The proper equation for calculating the timer value for a given baud rate in UART x2 mode (PCON=#0x80) is -

Timer value = 256 - ((Crystal Frequency / 192) / Baud)

So...for 9600bps -

11059000 / 192 = 57599

57599 / 9600 = 6

256 - 6 = 250

Therefore, your timer reload value will be 250 (0xFA in hex), not "-6" like you keep doing. And you usually preload BOTH TH1 AND TL1 with 250 in the timer initialization.
 
Last edited:
Sorry I commented out my UART and used yours to achieve 9600, I should have deleted mine. I understand now what I was doing wrong with the label equates thank you.

The problem I am having now is when I assemble your code from you post it doesn’t assemble and I have to change “IDATA 0x03” to “data 03h” I assume that is what I should be doing(I’m using Keil assembler, A51 for a AT89S51/ AT89S52)

Also when I have assembled that and testing on the micro controller the program dose not send out date unless I change it back to my original “Tx:”

im now working on a loop to send serial data to ram but I would like to get the UART fully sorted first if I can
 
As a matter of fact, let's relocate that entire register set into the general purpose RAM space. Save the R register space for things like math operations and indirect addressing. And yes use DATA instead of IDATA.

Also, change the value loaded into SCON to 0x52. The complete code should read -

Code:
serTx		DATA	    	0x30
serRx		DATA	    	0x31
 
byte1		DATA	    	0x32
byte2		DATA	    	0x33
byte3		DATA	    	0x34
byte4		DATA       	0x35

		org 		0x0000
		ajmp		Start
 
		org 30h
 
 
;#####   UART Initialization   ######
 
Start:		mov		PCON,#0x80		;x2 serial baud rate
		mov		TH1,#0xFA 		;reload value 250 for 9600bps w/11.059MHz xtal
		mov		TL1,#0xFA 
		mov 		TMOD,#0x20 		;timer 1,mode 2(auto reload)
		mov		TCON,#0x40		;start timer 1
		mov		SCON,#0x52 		;8-bit, 1 stop, REN enabled
 
;#####	Main Code	#####
 
Main:		acall		Rx
		mov 		byte1,serRx
		acall		Rx
		mov 		byte2,serRx
		acall		Rx
		mov 		byte3,serRx
		acall 		Rx
		mov 		byte4,serRx
 
 
		mov		serTx,byte1
		acall		Tx
		mov		serTx,byte2
		acall		Tx
		mov		serTx,byte3
		acall		Tx
		mov		serTx,byte4
		acall		Tx
 
		ajmp		Main
 
;#####   UART Transmit And Receive    #####
 
 
Rx:		jnb		RI,Rx 		;wait for the last bit
		clr		RI		;clear RI flag
		mov		serRx,SBUF	;transfer received data to buffer			
		ret
 
 
Tx:		jnb		TI,Tx		;wait here if transmit in progress
		clr		TI		;byte sent, clear tx flag
		mov		SBUF,serTx	;transfer received byte to UART buffer
  		ret				;done
 
		end

Also keep in mind that you have to send 4 bytes of data to the uC before it will transmit the way your code is written.
 
Last edited:
Thank you again I was having lots of problems until I started using general purpose RAM now it runs good using loops to write to ram locations over 30H :) , still for some reason I am still unable to get the basic transmit I need to get full duplex communicating going. I know where the problem lies but its bugging me to much so I’m going to move on for now. And yes you are correct again my program will not transmit without receiving 4 bytes of data. Please see the 2 files I have attached com1.asm being my working program and com2.asm being my program that I attempted to integrate a string time out function, this is so if it is set to receive 4 bytes of data and it only receives 3 it will wait for the forth for a delay before returning to the beginning of the receive routine. but it seem not to work, can you offer me a suggestion as to how I can do this
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top