Would you like to react to this message? Create an account in a few clicks or log in to continue.

You are not connected. Please login or register

8051 - The CNJE instruction with Registers make the simulation stop

2 posters

Go to page : 1, 2, 3  Next

Go down  Message [Page 1 of 3]

diego_souza



Hi all,

If I have a program with, for example:

CJNE R1,#10, label

And upload the hex file to SIMULIDE, the simulation stops when reaching this instruction.

If I change to

MOV A, R1
CJNE A,#10, label

Then it works!

Strange, isn't it?

Thanks,
Diego



Last edited by arcachofo on Fri Mar 25, 2022 2:48 pm; edited 1 time in total (Reason for editing : Mark as unsolved (red color))

arcachofo

arcachofo

Hi.
Nice to see someone testing the 8051, it's much needed.

It's not possible to find the problem with just that information.
We need a complete program.
Better the asm code and hex generated in your compiler to run it, but at least the complete asm.

Because there are some unknowns:

What does mean "the simulation stops"?
Which Register Bank is selected?
What is in R1 (of that Bank)?
What is in A?

diego_souza



Hello arcachofo,

Please fin the asm program below. I'm multiplexing two 7-segment displays.

Code:
; This program multiplexes a 00 to 99 counter
; on two 7-segment displays with an specific
; time interval.
; Note: a logic 0 lights a display segment.

ORG 0000H     ; Assembly starts from 0000H.

Mov DPTR,#LUT ; DPTR points to the start of the lookup table
MOV R0,#00H     ; Init the tens
MOV R1,#00H     ; Init the ones
Mov R3,#00H     ; Init our time reference

main:

back:
    CLR P3.3      ; Enable display 1
    SETB P3.4     ; Disable display 2

    MOV A,R0      ; Digit to show on display 1
    ACALL DISPLAY ; Show the digit

    MOV R7,#5     ; 5 ms interval
    ACALL Delay   ; Call the delay subroutine

    SETB P3.3     ; Disable display 1
    CLR P3.4      ; Enable display 2

    MOV A,R1      ; Digit to show on display 2
    ACALL DISPLAY ; Show the digit

    MOV R7,#5      ; 5 ms interval
    ACALL Delay    ; Call the delay subroutine

    INC R3              ; Increment R3 (our time reference)
    MOV A, R3           ; Pass R3 to A (for some reason CJNE with R doesn't work on SIMULIDE)
    CJNE A,#100, back   ; If R3 is not equal to 100 (100 x 2 x 5 ms = 1s), jump to back
    Mov R3,#0           ; If R3 is equal to 100, reset our time reference
    INC R1              ; and increment R1 (ones)
    MOV A, R1           ; Pass R1 to A (for some reason CJNE with R doesn't work on SIMULIDE))
    CJNE A,#10, back    ; If R1 (ones) is not equal to 10, jump to back
    MOV R1,#0           ; If R1 (ones) is equal to 10, zero the ones
    INC R0              ; and increment R0 (tens)
    MOV A, R0           ; Pass R0 to A (for some reason CJNE with R doesn't work on SIMULIDE)
 CJNE A,#10, back    ; If R0 (tens) is not equal to 10, jump to back
    MOV R0,#0           ; If R0 (tens) is equal to 10, zero the tens
    
    SJMP main           ; Jump back to the start

DISPLAY: MOVC A,@A+DPTR ; Gets digit drive pattern for the current value from LUT
         MOV P1,A       ; Puts corresponding digit drive pattern into P1
         RET            ; Return from subroutine

delay:  MOV R2,#230     ; 2 cycles
delay1: NOP             ; 1 cycles
        NOP             ; 1 cycles
        DJNZ R2, delay1 ; 2 cycles consume 230x4 + 2 instr cycles = 922 cycles
        DJNZ R7, delay  ; 922 cycles (which is equal to 1 ms) * number of counts in R7  
        RET             ; Return from subroutine

ORG 0200h
LUT:    DB 0C0h, 0F9h, 0A4h, 0B0h, 99h, 92h, 82h, 0F8h, 80h, 90h, 0
END ; End of Program

And this is the circuit I'm using:

8051 - The CNJE instruction with Registers make the simulation stop Circui10

The problem is that, when I use the CJNE instruction with a register, like this:

Code:
INC R3              ; Increment R3 (our time reference)
CJNE R3,#100, back  ; If R3 is not equal to 100 (100 x 2 x 5 ms = 1s), jump to back

This works in a real circuit but doesn't work in SimuIDE (the display n° 1 doesn't show anything and the display n°2 keeps showing a 0. Also, P3.3 and P3.4 doesn't toogle and thus the displays are not multiplexed). In fact, they toogle a single time and stop.

However, if I change the code to:

Code:
INC R3              ; Increment R3 (our time reference)
MOV A, R3           ; Pass R3 to A (for some reason CJNE with R doesn't work on SIMULIDE)
CJNE A,#100, back   ; If R3 is not equal to 100 (100 x 2 x 5 ms = 1s), jump to back

Then, it works well.

Another problem I have with the 8051 simulation in SimulIDE is regarding the software delays (which I'm also using in the 7 seg multiplex example).

My millisecond delay subroutine looks like this (I'm using a 11.0592 MHz crystal, both in my real circuit and the simulation):

8051 - The CNJE instruction with Registers make the simulation stop Circui11

In this example, with R7 I select how many milliseconds I want the routine to delay.

Code:
; Crystal frequency: 11.0592 MHz
; The 8051 uses 1/12 of oscilator frequency. So the frequency is:
; 11.0592 / 12 = 921.6 kHz
; The cycle execution time becomes 1/f = 1/921.6kHz = 1.085uS per cycle. So the
; Desired time = Total Cycles * 1.085 us

; If we are using an 11.0592 MHz xtal, we will need to consume
; approx 921 instruction cycles per millisecond of delay.
; 921 * 1.085 us = 0.999285 ms
 
; We could write a routine to consume 92,100 cyc, but that would only
; generate a delay of 100mSec. The delay subroutine below consumes
; 922 cyc for each count in R7, so we have a subroutine that can delay
; between 1 and 255 mSec.

ORG 00H  ; Assembly Starts from 0000H.

Back:   Clr P1.0     ; Set Port1 bit 0 to zero
 mov R7,#250  ; 250 mSec (we may change this)
        acall delay  ; Call delay subroutine
        acall delay  ; Call delay subroutine
 acall delay  ; Call delay subroutine
        acall delay  ; Call delay subroutine
        Setb P1.0    ; Set Port1 bit 0 to one        
        mov R7,#250  ; 250 mSec (we may change this)
        acall delay  ; Call delay subroutine
        acall delay  ; Call delay subroutine
        acall delay  ; Call delay subroutine
        acall delay  ; Call delay subroutine
        Sjmp Back    ; Restart the loop

delay:  mov R2,#230     ; 2 cycles
delay1: nop             ; 1 cycles
        nop             ; 1 cycles
        djnz R2, delay1 ; 2 cycles consume 230x4 + 2 instr cycles = 922 cycles
        djnz R7, delay  ; 922 cycles (which is equal to 1 ms) * number of counts in R7  
        ret             ; Return from subroutine
        
        End ; End of program

However, when simulating with SimulIDE and cheking with the oscilloscope I see that the interval is approximatelly 2.3 times longer than expected (so the 1 s total delay from the example above takes 2.3 s aproximatelly).

In a real circuit I have 1 s exactly, and on the simulation I have 2.3 s aproximatelly.

For the simulation to match the exact milliseconds, in my subroutine I have to change R2 from 230 to 102, like this:

Code:
delay:  MOV R2,#102     ; 2 cycles
delay1: NOP             ; 1 cycles
        NOP             ; 1 cycles
        DJNZ R2, delay1 ; 2 cycles consume 230x4 + 2 instr cycles = 922 cycles
        DJNZ R7, delay  ; 922 cycles (which is equal to 1 ms) * number of counts in R7  
        RET             ; Return from subroutine

Then, I have the exact number of milliseconds defined on R7 in the simulation.

Any hints?

Thanks!

arcachofo

arcachofo

Thanks for the explanation and code, I will have a look.

It would be good to know exactly which 8051 model or variant are you using in the real hardware.
Probably is not the case, but some models have different clock cycles per intruction cycle.

diego_souza



Hi,

I'm using an AT89S8252 (not for a particular reason, it was the model I had lying around).

Thanks for developing this great free simulator!

Diego

diego_souza



Hi,

Just another comment on 8051, I wasn't able to simulate the UART.

This is a sample code, working in the real circuit:

Code:
        Org 0000H
        
         Mov TMOD,#20H ;Timer 1, mode 2
         Mov TH1,#0FAH ;baud rate: 9600
         Mov SCON,#50H ;8-bit, 1 stop bit, 1 start bit
         Setb TR1      ;Start timer
 
         Mov DPTR,#LUT
Back: Clr A
         Movc A,@A+DPTR
         Jz Finish
         Call Transmit
         Inc DPTR
         Jmp Back
Finish: Jmp $ ; Program ends and stays here
                  
         Org 0200h
LUT:   DB 'H','e','l','l','o',' ','W','o','r','l','d', 0
      
Transmit: Mov SBUF,A   ;Send char stored in reg A
Here:     Jnb TI,Here  ;Check for last char
          Clr TI ;Clear - prepare for next char
          Ret

          End

Diego

arcachofo

arcachofo

CJNE bug solved at Rev 1031.

I'm using an AT89S8252
Good to know because there are some differences (for example Flash size is not the same).
But could not find in AT89S8252 datasheet clock cycles per instruction cycle...

Currently there is no concrete model implemented, just a generic 8051.
I will start by adding AT89S8252.

Just another comment on 8051, I wasn't able to simulate the UART.
Ok, I will have a look to Uart and the delay issue.

Another thing:
Which compiler are you using?
It is possible to compile and debug 8051 asm code in simulide, but a compiler definition file is needed.

diego_souza



I use two editors to write and compile the code:

MIDE-51 Studio and MCU 8051 IDE, and both use ASEM-51: http://www.opcube.com/home.html
https://sourceforge.net/projects/mcu8051ide/

8051 - The CNJE instruction with Registers make the simulation stop Mide_c10

8051 - The CNJE instruction with Registers make the simulation stop Mcu80510

It would be great to compile and debug 8051 asm code in simulide, I'll try it!

Thanks!

Diego

arcachofo

arcachofo

both use ASEM-51
Nice, that's the one I'm using to compile and debug 8051 asm.
There are still some issues, but it's mostly working.

To use it, add a file with name "asem51.xml" to: data/codeeditor/compilers/assemblers
With this content:
Code:
<!DOCTYPE SimulIDE>

<compiler name="Asem-51" type="avrasm01">
    <step
        command="asem"
        arguments=" -v $buildPath$fileName.asm"
    />
</compiler>
The compiler "Asem-51" will appear in the compiler list.
Select it before compiling.
If the executable is not in path you must set "Tool Path" property in Compiler Settings.

You can also set the compiler automatically if you add this line at the begininig of the asm file (must be the absolute first line, line number 1).
Then the compiler will be loaded when you open the asm file:
Code:
; Compiler: Asem-51

diego_souza



I have tried the procedure, and got the following error:

8051 - The CNJE instruction with Registers make the simulation stop Asem_e10

What am I doing wrong?

I have downloaded the ASEM-51 compiler and put on C:\asem

arcachofo

arcachofo

I have tried the procedure, and got the following error:
There is a problem here in Windows.
I did't thint about this... I will try to solve it.

By now you can edit asem51.xml and change 'command="asem" ' by 'command="asem.exe" '

diego_souza



Hi, I have changed the XML and got the same error.

I have tried with uppercase ASEM.exe and lowercase asem.exe, just to be sure.

Another detail, if I choose "Compiler Settings" without previously opening a file, the software closes.

8051 - The CNJE instruction with Registers make the simulation stop Side_e10

diego_souza



Hi,

Another detail I have noticed, it seems the 8051 Interrupts / Timers are not working in the simulation (I'll post all the bugs I found on this thread OK?).

The following program starts with 80H in P1, and when an external interrupt occurs in P3.2, 01H is moved to P1, and a 50ms delay occurs using Timer 0. After that, we return to the main loop and 80H is moved to P1.

During the simulation, we start with 80H in P1 but when the external interrupt occurs in P3.2, nothing happens (checked with oscilloscope and / or lowering the simulation time step).

So it seems that the interruption is not being detect (I'm not sure about the timer yet).


Code:
Org 0000h

Ljmp Main

Org 0003h
Ljmp 0060h ; Location of ISR

;------------ Define ISR ----------------------
Org 0060h ; LSR located here

INTZero:
              Mov R0,#80h ; Set MSB high
              Mov P1,R0       ; Move R0 to Port 1
              Acall LongDelay ; Call the delay routine
              Reti ; Return from interrupt

;----------- Start of Main ---------------------
Main:      
              Mov IE,#81h ; Enable INT0 - 10000001b

Back:    
              Mov R1,#01h ; Set LSB high
              Mov P1,R1       ; Move R1 to Port 1
              Jmp Back        ; Jump to Back

;-------------- Long Delay ---------------------
LongDelay:  
              Mov R3,#001H ; How many times the delay will be called

Start:      
              Acall FiftyMSec ; Call the Delay routine using Timer 0

              Djnz R3,Start ; Decrement R3 and if it's not 0, go to Start
              Ret ; Return form subroutine

FiftyMSec:
              Mov TMOD,#01H ; Timer 0, Mode 1
              Clr ET0 ; ETO - Enable Timer0 interrupt

Here:      
             Mov TH0,#03CH ; TH0 = 03CH, high byte
             Mov TL0,#0B0H ; TL0 = 0B0H, low byte
             Clr TF0 ; Clear Timer 0 flag
             Setb TR0 ; Start Timer 0

Again:      
             Jnb TF0,Again ; Monitor Timer 0 flag until it rolls over. Jump to again if 0.
             Clr TR0 ; Stop Timer 0
             Ret ; Return from subroutine

             End

arcachofo

arcachofo

Another detail, if I choose "Compiler Settings" without previously opening a file, the software closes.
Thanks. This is already solved

Hi, I have changed the XML and got the same error.
Well... does C:/asem/asem.exe file exist?

diego_souza



Well... does C:/asem/asem.exe  file exist?

Yes, please find below. It is uppercase, but I have changed tried changing that on the XML.

8051 - The CNJE instruction with Registers make the simulation stop Side_e11

arcachofo

arcachofo

Another detail I have noticed, it seems the 8051 Interrupts / Timers are not working in the simulation (I'll post all the bugs I found on this thread OK?).
8051 have been mostly abandoned for several months, and many changes happened in this time, at this moment I have no idea what is working or not.
In adition there are several features that are not yet implemented, for example external memory.

But Ports, Uart, Timers and Interrupts are implemented.
So it helps a lot that you test and report, specially when you post some code to reproduce the issue.

To keep track:
- UART not working.
- External Interrupt not working.

arcachofo

arcachofo

Yes, please find below. It is uppercase, but I have changed tried changing that on the XML.
Not sure but what about ASEM32? maybe ASEM32.bat?

How do you launch asem from a terminal?

arcachofo

arcachofo

As per the manual: http://plit.de/asem-51/doscmd.htm

Manual wrote: ASEM-51 provides full support of command line operation and batch capability as the best commercial development tools.    (smile)
Nevertheless, it can be integrated into foreign development environments, if desired. The assembler is invoked by typing:

   ASEM <source> [<object> [<listing>]] [<options>]


So in the xml should be: command="ASEM"
But in windows lower case should also work...

In any case to find out, open a terminal and check which command works.
In my system asem is in path, so if I open a terminal and type asem I get this:
Code:
MCS-51 Family Macro Assembler ASEM-51 V1.3

usage:    asem [options] <source> [<object> [<listing>]]

options:  -i  --includes=path1:path2:path3
          -d  --define=symbol[:value[:type]]
          -o  --omf-51
          -c  --columns
          -v  --verbose

diego_souza



Now testing Timer 0 without Interrupts:

The program below just toggles P1.0 every second, by using Timer0 as a reference (activating a 50ms delay 20 times per toggle).

When the simulation is started, the software freezes right away, and needs to be restarted.

You may quickly test this, by adding the 8051, changing the frequency to 12 Mhz, putting a probe on P1.0, and loading the hex.


Code:
Org 0000h ; Assembly starts from 0000H.

;----------- Start of Main ---------------------
Main:
 SetB P1.0 ; Set P1.0 to 1
 ACall OneSec ; Call one sec delay
 Clr P1.0 ; Set P1.0 to 0
 ACall OneSec ; Call one sec delay
 Jmp Main ; Jump back to main

;-------------- Long Delay ---------------------
OneSec:
 Mov R3,#014H ; How many times the delay will be called (14H = 20)

Start:
 Acall FiftyMSec ; Call the delay subroutine
 Djnz R3,Start ; Decrement R3 and if it's not 0, go to Start
 Ret ; Return from  subroutine

FiftyMSec:
 Mov TMOD,#01H ; Timer 0, mode 1
 Mov TH0,#03CH ; TH0 = 3CH, high byte
 Mov TL0,#0B0H ; TL0 = B0H, low byte
 Setb TR0 ; Start Timer 0

Again:
 Jnb TF0,Again ; Monitor Timer 0 flag until it rolls over
 Clr TF0 ; Clear Timer 0 flag
 Clr TR0 ; Stop Timer 0
            Ret ; Return from subroutine

            End ; End program

diego_souza



In any case to find out, open a terminal and check which command works. wrote:

I'll check that.

To keep track:
- UART not working.
- External Interrupt not working. wrote:

Thanks! I also suggest checking the software delays, as mentioned in a previous reply.


arcachofo

arcachofo

External Interrupt problem solved at Rev 1045.

arcachofo

arcachofo

Delay solved at Rev 1046.

diego_souza



Great! Thanks!

Newbie question: when you say it is solved on Rev 104*, does that mean this will be corrected in the next SimulIDE release?

Another finding:

- The RESET is not working

To keep track:
- UART not working (sample program above)
- Timer freezes the simulation (sample program above)
- Reset not working

8051 - The CNJE instruction with Registers make the simulation stop Reset11

arcachofo

arcachofo

when you say it is solved on Rev 104*, does that mean this will be corrected in the next SimulIDE releas
Yes, I use the revision number to keep track of where bugs are fixed.

The RESET is not working
Ok, I will have a look.

diego_souza



Hi arcachofo,

an additional info:

I think the RESET issue is something that occurs with other MCUs also.

I'm testing a RESET circuit with a PIC16F877 in version 0.4.15 SR9 and it works.

In version 1.0.0 RC2 the RESET doesn't work and a message is displayed:

ERROR: Simulator::addEvent Repeated event "p16F877-92"

Thanks!

arcachofo likes this post

Sponsored content



Back to top  Message [Page 1 of 3]

Go to page : 1, 2, 3  Next

Permissions in this forum:
You cannot reply to topics in this forum