8051 - UART receive using Assembly language and simulation on Proteus problem

Status
Not open for further replies.

Ngo Trong Nghia

Newbie level 4
Joined
May 27, 2023
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
49
Hi everyone, I am doing the UART receive with 8051 microcontroller but I met some problems. Although my UART transmission worked well, the receive mechanism did not. I tried every basic thing as SCON #50H,.. but it looks like the RI flag did not even work ?? One more problem is that even I copied the code of some one who did the receive successful in his/her video but when I ran it on my Proteus file it did not work anymore. Is that because the version of my Keil C is not compatible to my Proteus ? I am hopeless these days and hope for your helps !

The code (asm) below is what I tried to run. When the data is received through UART then it will clear the port P3.5. ( I typed the data in virtual terminal )

ORG 00H;
LJMP MAIN;
TEST EQU P3.5;

MAIN:
MOV TMOD,#20H;
MOV TH1,#-3;
MOV SCON, #50H;
SETB TR1;

RECEIVE:
JNB RI,RECEIVE;
CLR RI;
CLR TEST;
RET
END
 

Code:
ORG 00H;
LJMP MAIN;
TEST EQU P3.5;           ; TEST equals PORT3 bit 5. WILL this code ever be run??? the program jumps over it

MAIN:
MOV TMOD,#20H;       ;    TMOD: timer 1, mode 2, 8-bit reload  
MOV TH1,#-3;              ;    TIMER 1 baud rate reload value
MOV SCON, #50H;      ;    MODE 1, 8 bits, enable receiver
SETB TR1;                   ;    TIMER1 run

RECEIVE:
JNB RI,RECEIVE;        ;  jump to RECEIVE  until RI = 1, when TI = 1 run code below
CLR RI;                        ; clear the RI flag
CLR TEST;                   ; clear TEST to 0  
RET                             ; return    RETURN from a call ??? 

END
 
I tested the the TEST variable and it worked, I can make sure that. About the RET, I tried to replace it with SJMP RECEIVE but nothing happened. One more thing as I mentioned above, I also tried to run the code and the sketch of other person who was successful in running the circuit with his code. But it did not work when I run in my laptop. Do you have any ideas about that ?
 

I ran the code on an 80C31 board with an LED connected to P3.5 and it worked when I ran it with the 80C31
connected through a USB to TTL adapter using a terminal program. The LED turned on when a key was pressed.
The program will just do this one time, because there is no loop to run. Not having Proteus to test the program I don't know why it doesn't work in Proteus. Regarding trying to get it to jump to receive at the end, to make a loop,
the LED would remain on all the time since TEST would not be set high to turn it off. Changing the receive part of the program to:
Code:
RECEIVE:
   JNB RI,RECEIVE  
   CLR RI          
   CPL TEST            ; change to compliment instead of clear
   AJMP RECEIVE
created a loop that toggled the LED with each keypress.
The assembler I used, as31, errored on the EQU statement in you code until I changed it to the format it liked,
but I assume your assembler is happy with it the way it is written.
 
Last edited:
gram will just do this one time, because there is no loop to run. Not having Proteus to test the program I don't know why it doesn't work in Proteus. Regarding trying to get it to jump to receive at the end, to make a loop,
I tried to replace CLR with CPL instruction and AJMP like your code but it still did not work... My circuit includes of a AT89C52 and a Virtual Terminal. TXD of terminal to RXD of 89C52. Still, I have no idea why my code did not work. I mean everything else about the instruction that I programmed for 8051 is fine and even the transmitter of UART. But it seem like the RI flag did not work ?? the SCON was set up in a right way to enable read.
 

I'm no expert in AT89C52 code but if I understand your program, "RECEIVE" is a subroutine and it ends with a RET instruction to return back to wherever it was call from. You seem to jump to it though instead of calling it. If you jump to a subroutine the return address is not held on the stack so it won't know where to resume from. I suspect your code appears to work in real life because it crashes and resets rather than doing as you intended.

Brian.
 
I fixed it by replacing it with a SJMP to make a loop. And I tried toggle the port as FenTrac mentioned above but it did not work too. The problem is that even if I run the sample code that works on the Youtube and worked with their circuit, it's still a no for my simulation on my laptop. The version of both Keil C and Proteus is not too old, I can make sure that. May be it's about my laptop. Thanks for your help!
 
Last edited:

I ran your code on an AT89C51ED2 board, and it works on it also. It may be a problem with the simulator.
You might try using the actual address of P3.5 which is 0x0085, instead of the EQU statement to define TEST.
Code:
cpl 0x85
You could post the .hex file from the assembler to check that the machine code is the same as the code that is working.
How does the simulator indicate that P3.5 is 0 after a serial receive ?
What baud rate and system clock speed is being used ?
I am testing the code obviously using the wrong baud rate and it is still works.
The code is using the 8051 baud rate generating method of using timer 1 as the baud rate
generator.
Below is a listing with the machine code from the .hex file in the comments, for the test code that works.
Code:
.ORG 0x0000

   LJMP MAIN;          ; 02 00 03
MAIN:   
   MOV TMOD,#20H       ; 75 89 20
   MOV TH1, #-3        ; 75 8D FD
   MOV SCON, #50H      ; 75 98 50
   SETB TR1            ; D2 8E
RECEIVE:
   JNB RI,RECEIVE      ; 30 98 FD
   CLR RI              ; C2 98
   CPL 0x85            ; B2 B5
   AJMP RECEIVE        ; 01 0E
;END:
 
Last edited:
I replace the port name with the address 0x85 as you gave above but nothing improved and the hex file looks like this:
:03000000020800F3
:0C080000787FE4F6D8FD75810702000047
:10000000020003758920758DFD759850D28E309849
:07001000FDC298B285010E4C
:00000001FF
 

The .hex file has the same code. It looks like there is a preamble that is probably there for the simulator at address 0800, that then jumps to code listed as being at 0000 for the simulator to run.

Code:
:03 0000 00  02 08 00    -crc-F3
:0C 0800 00  78 7F E4 F6 D8 FD 75 81 07 02 00 00    -crc-47
:10 0000 00  02 00 03 75 89 20 75 8D FD 75 98 50 D2 8E 30 98    -crc-49
:07 0010 00  FD C2 98 B2 85 01 0E     -crc-4C
:00000001FF

0000 LJMP 0800           ;02 08 00
 
0800 MOV RO #7FH     ;78 7F
     CLR A                     ;E4    
     MOV @RO,A           ;F6
     DJNZ FD                 ;D8 FD
     MOV 0X81, 07        ;75 81 07 (R0.1)
     LJMP 0000              ;02 0000
                                          ; heres where the examples code listing begins
0000 LJMP 0003           ;02 00 03
MAIN:
     MOV TMOD, #20H    ;75 89 20
     MOV TH1, #-3           ;75 8D FD
     MOV SCON, #50H    ;75 98 50
     SETB TR1                ;D2 8E
RECEIVE:  
     JNB RI, RECEIVE     ;30 98 FD
0011 CLR RI                  ;C2 98
     CPL 0X85                  ;B2 B5  (R3.5)
     AJMP RECEIVE        ;01 OE

To return to the serial baud rate. The baud rate is set in the exmple code by the TH1 reload value of FD.
What the actual baud rate was in the example code that you are using is unknown even though the value FD is known, because we don't know the system clock. When I ran the code it had to be at the wrong baud rate, but still worked because the terminal did send a keypress that triggered RI, even though it had to have been garbage.
Your simulator may need to know exactly what the baud rate is to work. If you know the system clock speed being
used for the AT89C52, you can use the formula in the datasheet to calculate the correct TH1 value.
Also check the datasheet for whether the AT89B52 uses timer1 for the baud rate generator. I think the
8052 has an additional timer. If timer 1 is not the correct one to use that could be the issue.
Just one idea of a possible issue.
 
Last edited:
Hi,

Maybe a hardware problem? Microcontroller clock frequency?

Klaus
The clock frequency that I modified for AT89C52 is 11.0592Mhz and baud rate in the code is 9600 which means 0% difference in reality. I think the problem is about my 8051 on Proteus because with all the possible way above (I think) are not worked.
 

I am having the same issue as you. When I simulate on my Keil u5 it work, but cannot in AT89c51 using proteus.
The clock frequency that I modified for AT89C52 is 11.0592Mhz and baud rate in the code is 9600 which means 0% difference in reality. I think the problem is about my 8051 on Proteus because with all the possible way above (I think) are not work.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…