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.

Jump if greater than x....how do we do it in Assembly?

Status
Not open for further replies.

AceOfHearts

New Member
Peace to all,

How do we implement it in assembly?

Say I want to jump if Accumulator is greater than 27D?
Is there a fool-proof way of doing it?

At the moment I am checking the Accumalator say for 28D, and when it reaches it I jump, this is using CJNE.

But its not giving me a reliable result as it may not be passing 28D due to other cycles being spent before the accululator being checked using CJNE so the 28D value may not be there when the CJNE instruction is being executed (though I have tried to implement ways to ensure 28D is reached on the CJNE instruction).

So is there a proper way to do it? ie. where whatever the value of Accumulator is, as long as it is greater than 28D, it will jump. Suppose it is 35D, it will jump...

Many thanks for your help.

This message board has been a great help!
 
Last edited:
Nigel Goodwin said:
Perhaps you might try mentioning the processor you're using? - if it was a PIC (which it isn't) the PICList has plenty of details.


Appologies, it is an 8051.

Many thanks.
 
Are you using this method of comparison?
Code:
		CJNE A, #27, NOT_EQ

EQ:		;A=27
		SJMP END_CMP

NOT_EQ:		JC A_LESS

A_GREATER:	;A > 27
		SJMP END_CMP

A_LESS:		;A < 27

END_CMP:	;Finished
 
Last edited:
AceOfHearts said:
Appologies, it is an 8051.

Many thanks.
You dont have to use the CJNE instruction at all. You can do a subtraction and check the carry flag, which for subtraction is actually a borrow. the following instruction set reference from Atmel has examples in it for this kind of stuff.
https://www.electro-tech-online.com/custompdfs/2007/07/doc0509.pdf

Good Hunting

PS I knew which processor you were talking about. CJNE is kinda unique, and some of us are fortunate to know more than one processor family.
 
Last edited:
kinjalgp, I was not monitoring the carry flag at all.

papabravo, thanks for this method.

This sounds like it will work!

Many thanks.
 
Small detail, don't forget to clear the carry flag before your subb instruction otherwise you will end up with a bug.

Sometimes it work because the carry was cleared by previous instructions :)
Sometimes it won't work because the carry was set by previous instructions :(
 
Many thanks.

I am actually programming an 8051 for an ultrasonic rangefinder (SRF05) and trying to use this method to ascertain if the signal from the device has been on for a certain period of time (the length of this signal tells us the range).

Basically above a certain time period, object is out of range. And when within this time period, it is within range.

So far, I have not got it to work as I want!
 
AceOfHearts said:
Many thanks.

I am actually programming an 8051 for an ultrasonic rangefinder (SRF05) and trying to use this method to ascertain if the signal from the device has been on for a certain period of time (the length of this signal tells us the range).

Basically above a certain time period, object is out of range. And when within this time period, it is within range.

So far, I have not got it to work as I want!
How are you measuring pulse duration? Show your complete code because without that it is difficult to pin-point whats going wrong in it.
 
AceOfHearts said:
Many thanks.

I am actually programming an 8051 for an ultrasonic rangefinder (SRF05) and trying to use this method to ascertain if the signal from the device has been on for a certain period of time (the length of this signal tells us the range).

Basically above a certain time period, object is out of range. And when within this time period, it is within range.

So far, I have not got it to work as I want!
Did you read this one: **broken link removed**
or this one: https://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2007/jjl49_mar97/jjl49_mar97/

Should be the starting point of every US porject :D

How do you generate the US burst?
 
mcs51mc,

SRF05 sends out 8 cycles of U.S. bursts upon a trigger. So all I do is triffer the relevant pin SRF05.

kinjalgp,

I dont have an oscilloscope so I cant test whats going on at the hardware level. At the moment, when I download the program and connect it up on the breadboard, The object detected and object not detected LEDs come on and off randomly regardless of distance of an object in fron of the sensor. Sometimes I notice some consistancy, but it is pretty random most of the time. If I keep an object at close range without moving it, the LEDs keep switching.


Here is the code:



;P1.0 = object detected, P1.1 no object detected P0.0 connected to the trigger pin of SRF05. Echo
;line reponse appears 700uS after the end of trigger pulse


AGAIN: MOV A, #0
MOV P0, A ;output port

SETB P0.0
ACAll DELAY_TWENTY
CLR P0.0 ;Trigger


MOV A, #0FFH
MOV P0, A ;input port
STAY: JNB P0.0, STAY

ACALL MONITOR
ACALL DELAY_FIFTY

SJMP AGAIN


;================================================
;=========DELAY_TWENTY=================================

DELAY_TWENTY: MOV TMOD, #01 ;(1)

MOV TL0, #0F1H ;(1) ;Will count up 14D, TOT 20
MOV TH0, #0FFH ;(1)


SETB TR0 ;(1)
AGAIN1: JNB TF0, AGAIN1


CLR TR0 ;(1)
CLR TF0 ;(1)

RET

;==============================================================
;======DELAY_FIFTY============================

DELAY_FIFTY: MOV TMOD, #01 ;(1)

MOV R5, #7
FIRE: MOV TL0, #0
MOV TH0, #0


SETB TR0 ;(1)
AGAIN2: JNB TF0, AGAIN2

CLR TR0 ;(1)
CLR TF0 ;(1)
DJNZ R5, FIRE
RET

;#0FCH ;(1)
;#04BH ;(1)
;============================================================
;=================Monitor=================

MONITOR: CLR C ;clear carry
MOV TMOD, #01 ;(1)

MOV TL0, #0H
MOV TH0, #0H

MOV A, #100 ;(1)

SETB TR0


REMAIN1: JB P0.0, REMAIN ;(1)

SETB P1.0
CLR P1.1
SJMP FINISH

REMAIN: MOV R5, TL0 ;(1)
;CJNE A, #32H, REMAIN1 ;(2)

NOP ;(1)
NOP ;(1)
SUBB A, R5 ;(1)
JNC REMAIN1 ;(2)

SETB P1.1
CLR P1.0


FINISH: CLR TR0
CLR TF0

RET
 
Last edited:
AceOfHearts said:
REMAIN1: JB P0.0, REMAIN ;(1)
Is this correct?
I think your idea is to stay here as long P0.0 is high so you should jump to "REMAIN1" not "REMAIN".
In the mean time T0 is counting 1ms intervals (if you have a 12MHz xtal).

What happens after that line is complete unclear to me.
According to what I read in the SRF05 spec, you should divide the measured time by 58 to get distance in cm. Where is your division?

Unless you just want to know if the US see something and check for 30ms time-out of the SRF05 :) But even then the sequence is wrong.

Explain your DELAY_FIFTY: routine
 
mcs51mc said:
Is this correct?
I think your idea is to stay here as long P0.0 is high so you should jump to "REMAIN1" not "REMAIN".
In the mean time T0 is counting 1ms intervals (if you have a 12MHz xtal).

What happens after that line is complete unclear to me.
According to what I read in the SRF05 spec, you should divide the measured time by 58 to get distance in cm. Where is your division?

Unless you just want to know if the US see something and check for 30ms time-out of the SRF05 :) But even then the sequence is wrong.

Explain your DELAY_FIFTY: routine

Firstly sorry for the late reply.

I am not looking to measure any distance numerically to any precision. All I want to do is detect if something is there at close range (at roughly any distance at first) and turn on P1.0 and P1.1 pff if anything is detected, and vice versa if nothing is detected.

If I may run through the MONITOR bit with you... basically, P0.0 is measuring the echo pulse. At REMAIN1 it is checking to see if it still at logic 1, if it is, it jumps to REMAIN. Bear in mind Timer 0 is rolling all this time. At REMAIN, we transfer TL0 into R5.

BTW, the CJNE instruction there is commented out and it not part of the code. We then subtract R5 (which has the the Timer value) from the accumulator which has the decimal 100 in it. At the beginning , 100 minus R5 will give ninety-something as the timer had just started. Carry flag will not be sat. We check to see if carry is not set, if it is not set, we jump back to REMAIN1 to check if P0.0 is still at logic 1. if it is, we again jump to REMAIN and minus the timer value from the accumulator. This time, the timer will have an even larger value, hence the accumulator will decrease by more in this go...if after several cycles of P0.0 being at logic 1 and performing this routine, the accumulator reaches below zero, carry flag is set and detected. It means P0.0 has stayed on for too long and so no object has been detected. P1.1 will be set and P1.0 is cleared.

If P0.0 is detected as low before the the carry flag is detected, it means there is an object there and P1.0 is set and P1.1 is cleared.

I expect the lights to remain constant when a object is fixed in front of the sensors, but they keep alternating; as if the objects kep moving randomly - in and out of range.

About the DELAY_FIFTY, it is not actually delaying for 50 milliseconds, but much longer. This is so that I could see the SFR06 LED flash...I dont have an osciloscope; I wanted to make sure everything happened before I trigger the next one, just until I get it working.

Thanks.
 
Last edited:
Basicly you just want to know if there's something in front of the SRF05. You must drop the "close range" in you first sentence because the SRF05 detects over the complete range (not found in datasheet(?) of SRF05 :()

Now I understood your algorithm. But it's too complicated to only detect presence/absence of object :(

Some problems in you code:
1) 100-TL0 is done only once, next time you pass the SUBB the acc still holds 100-TL0 from previous pass.

2) You have to clear the carry flag before the SUBB instruction :eek:

What I would do:
Code:
orl   P0,#00000001b     ;P0.0 is input
mov  TMOD, #01      ;Prepare T0 to time P0.0
mov  TL0, #0 
mov  TH0, #0 

jnb    P0.0, $           ;Wait for +edge of echo pulse
setb  TR0                ;Echo pulse active, start timer
jb      P0.0, $          ;Wait for -edge of echo pulse
clr    TR0                ;end of echo pulse is stop timer

mov   a,TL0           ;Load LB timed value
clr     c
subb  a,#29          ;Time out SRF05 is 30ms
jc      ObjectDetected        

clr     P1.0          ;No object: led off
jmp   AGAIN

ObjectDetected:
setb  P1.0          ;Object: set led on
jmp   AGAIN

Problem is the accuracy of T0 and the time out value (30ms) of the SRF05. I used 29 but maby you have to adapt this according to the hardware.
To evaluate it you can use the CJNE instruction in combination with the carry flag. That you will have greather, equal and less situations. Put each one on a different output led and see what happen...

This code can easily be modified to calculate the distance to the object.

Please notice that I didn't check that code with the assembler, just typed it while I was thinking, so a typo is always possible :D:D:D
 
Hi there,

thanks for the code...I really appreciate it.

I am going to look at it further to see how I can adapt it to what I need.

But very quickly, the problem I see is that as I am using a crystal of 11.0592MHZ, each cycle is 1.085uS, so for 30ms, I will need 30ms/1.085uS = 27650 cycles which LB of T0 will not represent 2^8=256.

I think I can use HB of T0...(2^16) - (2^8) = 65280 max.; lowest value on HB would be 256, next highest 512 etc.

Thanks again.
 
Last edited:
AceOfHearts said:
Hi there,

thanks for the code...I really appreciate it.

I am going to look at it further to see how I can adapt it to what I need.

But very quickly, the problem I see is that as I am using a crystal of 11.0592MHZ, each cycle is 1.085uS, so for 30ms, I will need 30ms/1.085uS = 27650 cycles which LB of T0 will not represent 2^8=256.

If I take 10mS to be my time out value, then 20mS/1.085uS = 18434 cycles are required...

Thanks again.
Timer-0 is a 16 bit timer. It can represent values upto 65535. Modify your code to compare contents of TL0 and TH0. For ex. 27650d = 6C02h
So check for TH0=6Ch and TL0=02h
 
AceOfHearts said:
Hi there,
But very quickly, the problem I see is that as I am using a crystal of 11.0592MHZ, each cycle is 1.085uS, so for 30ms, I will need 30ms/1.085uS = 27650 cycles which LB of T0 will not represent 2^8=256.
Shame on me :(
I mixed up µs and ms :(
You're wright when your timer counts more than 27648 you reached the time out of the SRF05.


This routine compares up to 32 bit signed or unsigned integers.
Make MathLib_Op1 your timed value and MathLib_Op2 your time out value, put the three outputs on three led's and see what happens.

Good luck

Code:
;------------------------------------------------------------------------------
; Compare 2 unsigned operands
;
;Inputs: Operand 1 HB = MathLib_Op1+0
;			MathLib_Op1+1
;			MathLib_Op1+2
;		   LB = MathLib_Op1+3
;
;	 Operand 2 HB = MathLib_Op2+0
;			MathLib_Op2+1
;			MathLib_Op2+2
;		   LB = MathLib_Op2+3
;
;Output: MathLib_Greater = 1 when Operand 1 > Operand 2
;	 MathLib_Equal   = 1 when Operand 1 = Operand 2
;	 MathLib_Less    = 1 when Operand 1 < Operand 2
;
;
Comp_8_Unsigned:	mov  MathLib_Op1+1,#0
			mov  MathLib_Op2+1,#0
			
Comp_16_Unsigned:	mov  MathLib_Op1+2,#0
			mov  MathLib_Op2+2,#0
			
Comp_24_Unsigned:	mov  MathLib_Op1+3,#0
			mov  MathLib_Op2+3,#0
			
Comp_32_Unsigned:	
			
CompareUnsigned:	clr  MathLib_Greater
			clr  MathLib_Equal
			clr  MathLib_Less
			
			mov  a,MathLib_Op1+0		;Check HB
			cjne a,MathLib_Op2+0,Comp_001
			mov  a,MathLib_Op1+1		;Check next byte
			cjne a,MathLib_Op2+1,Comp_001
			mov  a,MathLib_Op1+2		;Check next byte
			cjne a,MathLib_Op2+2,Comp_001
			mov  a,MathLib_Op1+3		;Check LB
			cjne a,MathLib_Op2+3,Comp_001
			setb MathLib_Equal
			ret
			
Comp_001:		jc   Comp_002
			setb MathLib_Greater
			ret
			
Comp_002:		setb MathLib_Less
			ret
			


			
			
Comp_8_Signed:		call CheckSigns
			jnc  Comp_8_Unsigned
			ret
			
Comp_16_Signed:		call CheckSigns
			jnc  Comp_16_Unsigned
			ret
			
Comp_24_Signed:		call CheckSigns
			jnc  Comp_24_Unsigned
			ret
			
Comp_32_Signed:		call CheckSigns
			jnc  Comp_32_Unsigned
			ret
			
			
CheckSigns:		clr  MathLib_Greater
			clr  MathLib_Equal
			clr  MathLib_Less
			
			mov  a,MathLib_Op1+0		;Check sign Operand 1
			rlc  a
			jc   Comp_003			;Operand 1 Neg
			mov  a,MathLib_Op2+0		;Operand 1 Pos; check Operand 2
			rlc  a
			jnc  Comp_004			;Operand 2 Pos
			setb MathLib_Greater		;Op 1 is Pos & Op 2 is Neg -> Greater
			setb c
			ret
			
Comp_003:		mov  a,MathLib_Op2+0		;Operand 1 Neg; check Operand 2
			rlc  a
			jc   Comp_004			;Operand 2 Neg
			setb MathLib_Less		;Op 1 is Neg & Op 2 is Pos -> Less
			setb c
			ret
			
Comp_004:		clr  c
			ret
 
It seems that the echo pin goes high and then the echo pin goes low and that is the period you are trying to measure.

Timer 0 and timer 1 can be gated. Timer 0 can be prevented from running if /INT0 is one and timer 1 can be prevented from running if /INT1 is one. So by connecting the echo pin to INT0 or INT1 in an appropriate way, you can get a measure of the time the echo pin is high.

Alternatively timer 2 has a capture facility. You can capture the count of the timer 2 counter registers on T2EX falling edge. That's another way of measuring the time the echo pin is high.
 
Status
Not open for further replies.

Latest threads

Back
Top