# adding all digits in a number, MCU 8051

Thank you, KISS.

Regards
PG

#### Jon Wilder

##### Active Member
Vpp is the required 12V programming voltage when the main code is being written to the chip by the parallel programmer. The programming hardware supplies this voltage.

The PROG in "ALE/PROG" is the pin that the programming hardware sends the clocking pulse to during the programming phase when programming the chip. When the program data is placed onto the data pins (P0), a pulse is sent to the chip to tell the chip when to read the data present on the P0 pins and store it into the chip's internal code memory.

This is all stuff that is used by a parallel programmer only. If you're using an ISP programmer such as the AT89ISP cable, these signals are not needed (ISP stands for In System Programming).

"EA" stands for "External Access". It is an active low pin that tells the chip whether to execute code in its internal memory or from an external EPROM. In normal use, EA/VPP gets tied to Vdd when using the chip's internal code space. When EA is high, the chip will execute code from its internal memory. Any code memory addresses past the internal code memory address range will address external code memory. This allows you to use the chip's internal code memory with additional code memory residing off chip up to a total of 64K.

Example...if your chip has 12K of code space on chip and EA is tied to Vdd, you can have the 12K of internal code memory with an additional 52K of external code memory. Addresses 0x0000-0x2FFF will access the on chip memory while addresses 0x3000-0xFFFF will accesses external code memory.

If all code execution is to take place from an external EPROM, EA should be tied to Vss instead.

Last edited:

#### PG1995

##### Active Member
Thank you very much, Jon. I understand it now.

Regards
PG

#### PG1995

##### Active Member
Hi

You could find Q1 here, Q2 here, and Q2, Q3, Q4, and Q5 here.

Regards
PG

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Q1.... There is frequency being produced on P1.7... This will emit a sound on a siren.
Q2.... We've been here before... You MUST make a pin an input BEFORE you read it.... Writing a 1 to the port makes it an input.
Q3,Q5 Try not to think of it as a latch......If you want to "output the port" you just do.... If you need to "input a port" you just need to prevent contention by writing a 1 to it..

***The latch controls a FET.... If you write a 1 the FET is off..... No contention!!! If you write a 0 the FET is on... Ground is on the pin...If you read a 1 on the port in this condition

MELTDOWN...

#### Jon Wilder

##### Active Member
Q3: If there is one thing I cannot stand about 8051 books, it is the incorrect explaining of the port operations.

The first thing that needs to be cleared up...THERE IS NO "INPUT MODE" AND "OUTPUT MODE"! 8051 ports are NOT to be thought of in this fashion. This is what messes most people up when dealing with 8051 I/O ports. They ARE NOT a tri-state port like a PIC micro has. They don't have a tristate register that allows you to turn off the pin output drivers. The weak internal pull up driver is ALWAYS on. Only the pull down driver gets turned on/off when writing to the port. 0 turns on the pull down driver, pulling the pin low. 1 turns the pull down driver off, which allows the pull up driver to pull the pin high. Again it IS NOT a "push-pull" style output driver. This is the reason why they cannot source nearly as much current as they can sink.

OK...the ports on an 8051 are bi-state quasi-bidirectional. Let's look at what these two terms mean -

Bi-State: The pins on the port can only be in 1 of 2 possible states...HIGH or LOW. This differs from more modern microcontrollers (such as the PIC microcontroller) that feature tri-state ports. On tri-state ports, the pins can either be HIGH, LOW, or HI-IMPEDANCE (all output drivers off). On the traditional 8051 however, the weak pullup drivers are always active so the hi-impedance state is not available, making it a bi-state port.

Port 0 is a bit different. When it is being used as a standard I/O port, it does not have any internal pull up because it is an open drain design. So the two states available on port 0 are HI-IMPEDANCE and LOW. When used as the low order address/data port, its internal pull ups are active, making it a HIGH/LOW bi-state port.

Quasi-Bidirectional: This means that the port functions as BOTH input AND output when the pins are internally pulled high by writing 1's to the port latch. However, when 0's are written to the port latch, the port pins function as output only. When a 1 is written to a pin, the pin is placed in a high state and can be externally pulled low by some external hardware. If a pin has a 1 written to it and something external is pulling the pin low, reading this pin will return a 0, NOT the 1 that was written to the pin in the latch.

When a 0 is written to a pin, the pin is placed in a low state. A pin CANNOT be externally pulled high when it is internally pulled low. This is why it only functions as an output when a 0 is written to it.

Let's review -

Port pins which contain a 1 in the port latch function as BOTH and input AND and output

Port pins which contain a 0 in the port latch function as output only

Any instructions which WRITE to the port write to the port latch. Any instructions which READ the port read the data present on the port pins themselves.

Q4: Write instructions modify the value in the port latch. "mov P1,#44" is a write instruction. After executing this instruction, the port latch will contain the value of 44.
Keep in mind that you CANNOT read the contents of the latch. You can only read the contents of the port itself. Reading the port contents returns the high/low states of the port pins themselves...NOT the contents of the latch.

Q5: ALE has NOTHING to do with the port latch. ALE is for an external latch IC that is used to demultiplex the low order address byte from the data byte on port 0 when accessing external memory only. Again, THIS PIN IS ONLY USED WHEN ACCESSING EXTERNAL MEMORY!

The port latch is used ONLY when writing a value to a port. Reading a port ONLY reads the port pins themselves...NOT THE LATCH.

I'll give you an example. Let's say we execute "mov P1,#0xFF". The latch will contain the value of 0xFF, or 11111111. If nothing is externally pulling any port 1 pins low, all of port 1's pins will be high.

However, let's say we use a switch to drive pin P1.5 low. Then we read port 1 by executing "mov A,P1". The accumulator will contain the value of 11011111 even though the latch contains 11111111. This is because pin 5 of port 1 is being pulled low by a switch. Since reading the port returns the high/low state of the port's pins, reading the port returned the value of 0 on pin 5 because of this.

Last edited:

#### PG1995

##### Active Member
Thank you very much, Rogers, Jon. Very kind of you.

Is my calculation of extra delay which is mostly ignored is correct? Please let me know. I have calculated it for AT89C51 using 12 MHz frequency XTAL. Thanks

Code:
;-------Delay Subroutine

;period of one MC = 0.001 ms
;75(50(255x2x0.001)) = 1912.5 ms = 2 s

org 0x300

Delay:
mov R0, #75		;1 MC
L1: mov R1, #50
L2: mov R2, #255
L3: DJNZ R2, L3		;2 MC
DJNZ R1, L2
DJNZ R0, L1
RET			;2 MC

end

;please notice that we have ignored extra delay corresponding to some instructions in the Delay
;subroutine and this extra delay is: {50(1+2) + 75(1+2) + 2} x 0.001 = 0.377 ms = 0.000377 s

#### PG1995

##### Active Member
Hi

Do you think that the code below is correct? I'm confused because the code given in the book is quite different. Please help me. Thank you.

Code:
;Assume that bit P2.3 is an input and represents the condition of an oven. If it goes HIGH, it means that
;the oven is hot. Monitor the bit continuously. Whenever it goes HIGH, send a low-to-high pulse to
;pin P1.5 to turn on the buzzer.

ORG 0H

OVEN BIT P2.3
SETB OVEN	;to make the pin an input

BUZZER BIT P1.5

REPEAT:	JB OVEN, BUZ
SJMP REPEAT

BUZ: 	CLR BUZZER
SETB BUZZER

SJMP REPEAT

END

#### Jon Wilder

##### Active Member
First we need to talk about proper assembly code format.

Assembly code follows a very simple syntax. You have 3 columns -

Code:
<LABEL>			<INSTRUCTION>		<OPERAND>
Label - Labels are optional and provide a means to give a line of code a "name" to refer to when using jump and call instructions without having to know the physical address that the line of code resides in.

Instruction - This is the instruction itself

Operand - This is what the instruction is being performed on and the values for the instruction to use. Also known as "arguments".

When you're doing equates tables (i.e. EQU, DATA, IDATA, BIT, etc etc), the label goes in the label column, the EQU/BIT/DATA/IDATA/etc goes in the instruction column while the value it's being equated to goes in the operand column. For example -

Code:
OVEN			BIT			P2.3
Equates tables do not go in the code. You place them BEFORE the first org instruction. Your code should appear as such -

Code:
;equates table

OVEN			BIT			P2.3
BUZZER			BIT			P1.5

;start main code

org			0x0000		;reset vector

setb			OVEN		;P2.3 high

Repeat:			jnb			OVEN,Repeat	;continuously poll P2.3 until P2.3 is high
acall			Delay		;run delay
cpl			BUZZER		;switch P1.5 to opposite state
acall			Delay		;run delay
ajmp			Repeat		;loop forever

Delay:			mov			R0,#0xFF
mov			R1,#0xFF
DelayCount:		djnz			R0,DelayCount
djnz			R1,DelayCount
ret

end
For the buzzer to continuously sound you have to continuously compliment bit P1.5 at an audible frequency, which will require a delay loop before and after each compliment of the pin. Otherwise it will switch the pin at a frequency that is too high for the human ear to hear it.

Let's look at what the code is doing. The first instruction says to continuously jump to itself if bit P2.3 is not set. The program counter will continuously jump to that line of code if the sensor is holding pin P2.3 low. As soon as the oven gets hot, the sensor will drive pin P2.3 high, causing it to jump out of the continuous loop.

Once out of the continuous polling loop, the next instruction calls a delay loop. After returning from the delay loop, the next instruction states to compliment bit P1.5 (compliment means to switch the bit to the opposite state). After complimenting bit P1.5, it calls the delay loop again, then returns and jumps back to the first line that continuously polls bit P2.3 if the sensor is holding P2.3 low.

The buzzer will continuously sound until P2.3 is driven low again by the sensor.

Last edited:

#### PG1995

##### Active Member
Code:
;equates table

OVEN			BIT			P2.3
BUZZER			BIT			P1.5

;start main code

org			0x0000		;reset vector

setb			OVEN		;P2.3 high

Repeat:			jnb			OVEN,Repeat	;continuously poll P2.3 until P2.3 is high
acall			Delay		;run delay
cpl			BUZZER		;switch P1.5 to opposite state
acall			Delay		;run delay
ajmp			Repeat		;loop forever

Delay:			mov			R0,#0xFF
mov			R1,#0xFF
DelayCount:		djnz			R0,DelayCount
djnz			R1,DelayCount
ret

end
...

The buzzer will continuously sound until P2.3 is driven low again by the sensor.
Thanks a lot, Jon.

In my humble view, whether the buzzer will sound or not once P2.3 is driven low entirely depends what was the state of the buzzer just before P2.3 went low. The complement operation is actually turning the buzzer on and off. Do you get my point? Please let me know if I'm correct. Thank you.

Best wishes
PG

#### Jon Wilder

##### Active Member
Thanks a lot, Jon.

In my humble view, whether the buzzer will sound or not once P2.3 is driven low entirely depends what was the state of the buzzer just before P2.3 went low. The complement operation is actually turning the buzzer on and off. Do you get my point? Please let me know if I'm correct. Thank you.

Best wishes
PG
No you are not correct.

In order for the buzzer to sound, it must be cycled high and low continuously at a human audible frequency with a square wave. That is what the loop routine that continuously compliments P1.5 does with the delay calls and the "cpl" instruction. When P2.3 is set low again, pin P1.5 may remain in either the high or the low state, but it will not sound if it is left in either of those two states because pin P1.5 is outputting a continuous high or a continuous low (basically a DC signal) once P2.3 is set low.

On a side note...can you please start a new thread each time you ask a new question that is not related to the original question? This thread has been filled with questions that are far from related to the original topic.

Last edited:

#### PG1995

##### Active Member
Thank you, Jon.

Yes, I understand that I should create a new thread and I will. But some time it's good to combine all the queries about a subject in one place. Besides in the last two months I have had good experience learning from you and Ian Rogers therefore making queries here would notify you that I need your help once again! Anyway, I will create a new thread.

1:
In order for the buzzer to sound, it must be cycled high and low continuously at a human audible frequency with a square wave. That is what the loop routine that continuously compliments P1.5 does with the delay calls and the "cpl" instruction. When P2.3 is set low again, pin P1.5 may remain in either the high or the low state, but it will not sound if it is left in either of those two states because pin P1.5 is outputting a continuous high or a continuous low (basically a DC signal) once P2.3 is set low.
Doesn't a buzzer work on a DC signal? In my last post I had in mind that a buzzer worked on DC and that made me confused.

2:
What's wrong with the code below? It doesn't assemble. Both "-120" and "-2" aren't out of range because range for negative numbers is -1 to -128. Please help me with this.

Code:
;Observe the following, noting the role of the OV flag

ORG 0H

MOV A, #-120
MOV R4, #-2

SJMP $END Errors: Code: Compiling file: EXAMP_14.asm Initializing pre-processor ... Notice at 5 in EXAMP_14.asm: Overflow -120' -> 65416' Syntax error at 5 in EXAMP_14.asm: Operand value out of range: -120' (65416') Notice at 6 in EXAMP_14.asm: Overflow -2' -> 65534' Syntax error at 6 in EXAMP_14.asm: Operand value out of range: -2' (65534') Pre-processing FAILED ! Creating code listing file ... -> "EXAMP_14.lst" 2 errors, 0 warnings #### ericgibbs ##### Well-Known Member Most Helpful Member hi PG, A buzzer or 'sounder will work with a DC voltage supply, I think Jon is confusing a buzzer with a piezo transducer which requires driving with a square wave voltage at the piezo transducer frequency. Last edited: #### PG1995 ##### Active Member Thank you, Eric. Yes, I also think that a buzzer should work with DC. But we should wait for Jon's reply. Best wishes PG #### Jon Wilder ##### Active Member Thank you, Jon. Yes, I understand that I should create a new thread and I will. But some time it's good to combine all the queries about a subject in one place. Besides in the last two months I have had good experience learning from you and Ian Rogers therefore making queries here would notify you that I need your help once again! Anyway, I will create a new thread. Yes but these questions you're asking have nothing to do with "adding all digits in a number", which is the title of this thread. This is why I mentioned to start new threads for any and all questions which do not pertain to "adding all digits in a number". Ian and I constantly monitor this thread so we will see your new posts regardless. Doesn't a buzzer work on a DC signal? In my last post I had in mind that a buzzer worked on DC and that made me confused. A self contained buzzer only needs a high or a low DC signal. If the code in your book were meant to work with a self contained buzzer, it would set bit P1.5 if P2.3 is high and clear P1.5 if P2.3 is low. But that's not how the code in the book is written. It is written to work with a piezo transducer, which requires a square wave at a human audible frequency in order to make the piezo element vibrate and create a sound. Continuously complimenting P1.5 as long as P2.3 is driven low by the sensor with the delay calls in between does exactly that...generates the needed square wave to make a piezo transducer work. Furthermore, even if you did have a self contained buzzer, the 8051 port pin cannot source current to it so you would have to use a transistor to switch the buzzer on/off and have the 8051 send the high/low signal to the transistor base. What's wrong with the code below? It doesn't assemble. Both "-120" and "-2" aren't out of range because range for negative numbers is -1 to -128. Please help me with this. Assemblers don't deal with signed values (+/-). They only deal with unsigned values (+ only). The microcontroller does not have a floating point unit on it so the microcontroller itself can only deal with unsigned integers (i.e. positive only). In C language, you can use negative values via using signed variables because the compiler handles them via the use of the carry flag. But assemblers weren't really meant to deal with signed variables. Since the 8051 is an 8-bit processor and the accumulator is only 8 bits wide (along with all other RAM registers on an MCS-51), you can only load it with values between 0-255, or 0x00-0xFF in hex. Last edited: #### PG1995 ##### Active Member Thank you very much, Jon. Jon Wilder said: Assemblers don't deal with signed values (+/-). They only deal with unsigned values (+ only). The microcontroller does not have a floating point unit on it so the microcontroller itself can only deal with unsigned integers (i.e. positive only). In C language, you can use negative values via using signed variables because the compiler handles them via the use of the carry flag. But assemblers weren't really meant to deal with signed variables. Since the 8051 is an 8-bit processor and the accumulator is only 8 bits wide (along with all other RAM registers on an MCS-51), you can only load it with values between 0-255, or 0x00-0xFF in hex. So, does this mean that I can't do the code below in the assembler? Please let me know. Thanks. Code: ORG 0H MOV A, #-120 MOV R4, #-2 ADD A, R4 SJMP$

END
PS: I see Rogers' post now. Yes, there is a calculator in MCU 8051 IDE. Do you want to do the conversion myself? Can't assembler handle the conversion by itself? Please let me know. Thanks.

Regards
PG

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Code:
ORG 0H

MOV A, #87h   ; is the same as -120
MOV R4, #0FEh   ; is the same as -2

SJMP $END This is how you initiate negative numbers When you work with negative numbers, you must take care of the sign... ie if you TeST a number by checking the MSBit to check for negativity (is that a word ) #### PG1995 ##### Active Member Code: ORG 0H MOV A, #87h ; is the same as -120 MOV R4, #0FEh ; is the same as -2 ADD A, R4 SJMP$

END
This is how you initiate negative numbers

When you work with negative numbers, you must take care of the sign... ie if you TeST a number by checking the MSBit to check for negativity (is that a word )
Thanks a lot, Rogers.

1:
So, this means I have to make conversions myself. Too bad! But I'm wondering that why the book give the code below when the 8051 can't do the conversion itself. The book should have at least mentioned it.

Code:
ORG 0H

MOV A, #-120
MOV R4, #-2

SJMP $END 2: Could you please tell me why I'm getting the error? Apparently I can't see any error in the syntax for line which has #'s as a comment. Thank you. Code: ;Assume that P1 is an input port connected to a temperature sensor. Write a program to read ;the temperature and test it for the value 75. According to the test results, place the temperature ;value into the registers indicated by the following. ; if T=75 then A=75 ; if T<75 then R1=T ; if T>75 then R2=T ORG 0H MOV P1, #0FFH MOV A, P1 MOV R0, #75 CJNE A, R0, UN_EQUAL ;############################################### SJMP EXIT UN_EQUAL: JC GREATER MOV R2, A SJMP EXIT GREATER: MOV R1, A EXIT: NOP SJMP$

END
Error:
Code:
Compiling file: EXAMP_25.asm
Initializing pre-processor ...
Syntax error at 14 in EXAMP_25.asm: Invalid set of operands: cjne 224,R0,UN_EQUAL
Pre-processing FAILED !
Creating code listing file ...		-> "EXAMP_25.lst"
1 error, 0 warnings

Last edited: