# adding all digits in a number, MCU 8051

Status
Not open for further replies.

#### PG1995

##### Active Member
Hi

I want to add every digit in this number 457-85-9999-1, i.e. 4+5+7+8+.... I'm new to assembly language and using MCU 8051.

One way to do it is given below. How else can I do it efficiently and using few lines without making it complex for myself? Please help me with it. Thank you.

Code:
;add all digits of the number 457-85-9999-1

ORG 0H

Repeat:
CLR A
SJMP Repeat

END
Regards
PG

Forum Supporter

#### Jon Wilder

##### Active Member
A really good site I recommend to anyone wishing to learn the MCS-51 family is http://www.8052.com

This site was what got me started with the MCS-51 family. I started embedded electronics and assembly language programming with the 16F series of PIC microcontrollers a year and a half ago (knowing nothing about digital electronics or any sort of programming), then took on learning the MCS-51 family last summer. I just finished up writing my first MCS-51 code that I started back in February and it's working 100% bug free now.

Despite the haters who hate on it for no other reason than its age, the MCS-51 family is a very fun family to code in assembly. I enjoy coding it over the PIC to be honest. But I use both processors in different types of applications, with my favorite PIC being the 16F88/F886/F887. For MCS-51 stuff I use Atmel's AT89S series and am currently working with the AT89S8253.

Last edited:

#### Jon Wilder

##### Active Member
You can also preload these values into RAM registers, then set up a loop that adds them via indirect addressing. With indirect addressing you can set the add loop as a subroutine, then change the values loaded in the registers in main code, init the counter and call the subroutine to add any combination of digits, making the whole thing configurable in main code -

Code:
DigitLoad:	mov		0x30,#4			;load digits into RAM
mov		0x31,#5
mov		0x32,#7
mov		0x33,#8
mov		0x34,#5
mov		0x35,#9
mov		0x36,#9
mov		0x37,#9
mov		0x38,#9
mov		0x39,#1

mov		R1,#0x0A		;set counter for 10 digits

;continue with main code

push		R0			;store R0
mov		R0,#0x30		;set starting RAM address
mov		A,#0			;clear accumulator
pop		R0			;restore R0
pop		ACC			;restore accumulator
ret
When using this method, make sure you load the first digit into RAM location 0x30, then follow them with each digit in sequence as shown above.

Notice I also use the stack to my advantage to back up the registers that will be used in the subroutine, then restore them on subroutine exit. This is a very good programming habit to get into.

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Jon.. In my hayday, I went to Portsmouth University to visit Frederick Cowan, David Callcot and Hassan Parchizadeh the three authors of "8051 Microcontrollers"

I spent a great day with them discussing the book... I came away with oodles of goodies... SBC's, Development kits and tons of literature. I was a tiny bit responsible for the second edition.. Hassan, whom wrote the C portions of the book, had minor mistakes and we sat down and corrected the parts that needed correcting. I treated them to a dinner. This was my first experience of 3D printing as they had one of the first.. It printed wax or wood.. The wood was liquid and came out with a kind of veneer finish.

I totally love it... Right in the heart of phillips development.... (Portsmouth was an excellence center for Phillip's micro's)

#### PG1995

##### Active Member
Thank you very much, once again, Rogers, Jon. You guys are really helpful and nice too!

Just wanted to confirm: I don't think assembly language for 8051 is case sensitive, is it? Is it true of every other assembly language? Please let me know.

@Rogers: You were right about MCU 8051 IDE. It is a great simple tool for beginners like me. Though I have Keil installed too but I like it more. Thanks for the recommendation.

Best wishes
PG

Last edited:

#### Jon Wilder

##### Active Member
The labels you use are case sensitive yes. I think the built in assembler in MCU8051IDE is a bit forgiving with that.

I always tend to type instructions in lower case and constant labels in upper case. For line labels and subroutine names I capitalize the first letter of every word. That's just my personal naming convention.

#### PG1995

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

@Rogers: I have Proteus ISIS installed along with Keil uVision and MCU 8051 IDE. I have also downloaded VSM Studio but I think I would stick with MCU 8051 IDE because as a beginner it seems simple to me. But thanks for telling me about the VSM.

Best regards
PG

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I must admit... Its very good!! The more I play with it, the more it seems to do..... If you ever start messing with C.. You can add the compilers directly to it.

Have fun.

#### PG1995

##### Active Member
Hi

First I need to change the code below so that "AMERICA" is sent to port 0 which is connected to a LCD.

Regards
PG

Code:
ORG	0000
MOV 	DPTR,#MYDATA
MOV 	R0,#40H
MOV 	R2,#7
BACK:	CLR 	A
MOVC	A,@A+DPTR
MOV	@R0,A
INC	DPTR
INC	R0
DJNZ	R2,BACK
HERE: 	SJMP	HERE

ORG 	250H
MYDATA:	DB 	"AMERICA"
END

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Code:
; Lcd 16x2 display
;P3.2 = RS... P3.3 = R/W... P3.4 = E

org	0
sjmp	Start
org	20h

Start:
clr	P3.3
mov	a.#38h		; function set 8 bits 2 rows 5x7 font
acall	lcd_cmd
mov	a.#0Eh		; screen on..cursor on.. no blink
acall	lcd_cmd
mov	a.#06h		; R/L cursor
acall	lcd_cmd
mov	a.#01h		; clear and home
acall	lcd_cmd

mov	DPTR, #msg	; point at message
acall	lcd_print	; send it to display

fin:
sjmp	fin

lcd_print:
mov	a,#0h		; start of msg
movc	a,@a+DPTR	; set data pointer
cjne	a,#0h, mod1	; wait for null
ret
mod1:
acall	lcd_data	; send char to screen
inc	DPTR		; get next char
sjmp	lcd_print	; again

msg1:
db	"AMERICA",0	; message

lcd_data
mov	P1,#0FFh	; make input
setb	P3.3		; R/W = Read
clr	P3.2		; RS = command
waitd:
clr	P3.4		; E low
setb	P3.4		; E high
jb	P1.7,waitd	; get busy flag
clr	P3.4		; E low
clr	P3.3		; R/W write
setb	P3.2		; RS data
mov	P1,a		; put data on LCD port
setb	P3.4		; E high
clr	P3.4		; E low
ret

lcd_cmd
mov	P1,#0FFh	; make input
setb	P3.3		; R/W = Read
clr	P3.2		; RS = command
waitc:
clr	P3.4		; E low
setb	P3.4		; E high
jb	P1.7,waitc
clr	P3.4		; E low
clr	P3.3		; R/W write
clr	P3.2		; RS command
mov	P1,a		; put command on LCD port
setb	P3.4		; E high
clr	P3.4		; E low
ret

end
This is a simple program to write to port 1 (8 bit ) with control on port 3 its easy to change ports..

#### PG1995

##### Active Member
Hi Jon

I'm using this software, MCU IDE 8051, recommended by Rogers. Though, I also have Keil uVision. It was a virtual, probably generic, LCD. Please see the attachments. I don't think I would be able to interface it because what Rogers posted in the last post just was over my head!

Regards
PG

Last edited:

#### Jon Wilder

##### Active Member
The LCD has an 8 bit data port. This data port has pins DB0-DB7. You pick a port on the MCU to drive this 8 bit data port with and the MCU's port pins will connect to their corresponding pins on the LCD data port.

Example, let's say you decide to use Port 1 on the MCU for the LCD data port. You would connect lines DB0-DB7 on the LCD module to Port 1 on the MCU as follows -

DB0 - MCU Port 1 Bit 0 (P1.0)
DB1 - MCU Port 1 Bit 1 (P1.1)
DB2 - MCU Port 1 Bit 2 (P1.2)
DB3 - MCU Port 1 Bit 3 (P1.3)
DB4 - MCU Port 1 Bit 4 (P1.4)
DB5 - MCU Port 1 Bit 5 (P1.5)
DB6 - MCU Port 1 Bit 6 (P1.6)
DB7 - MCU Port 1 Bit 7 (P1.7)

Then you would decide what port lines on either ports 2, 3 or 4 to use for driving the E (Enable), RS (Register Select) and R/W (Read/Write) lines on the LCD module. To send data to the LCD, you would write the data to register P1 on the MCU and set the RS, R/W and E lines accordingly.

#### PG1995

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

Though Rogers gave me the code in his last post, I wasn't able to understand it as I pointed out in my last posting. Forget about the LCD interfacing. Could you please help me to edit this code in a way that the word AMERICA is sent to the port 1? I think sending the complete word at one time would make things difficult so it sends one letter of word AMERICA to port 1 at a time with a delay of 200ms between sending each letter and a delay of 400ms between start of each sending cycle. This is what I'm trying to say. At first letter "A" is sent to port 1, then there is a delay of 200ms, then "M" is sent,..., now "C" is sent, 200ms delay, and now at last last "A" is sent. One cycle of sending the word is complete. Now there is a delay of 400ms and after that cycle restarts.

Code:
ORG	0000
MOV 	DPTR,#MYDATA
MOV 	R0,#40H
MOV 	R2,#7
BACK:	CLR 	A
MOVC	A,@A+DPTR
MOV	@R0,A
INC	DPTR
INC	R0
DJNZ	R2,BACK
HERE: 	SJMP	HERE

ORG 	250H
MYDATA:	DB 	"AMERICA"
END

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
That's is what all lcd code does.... Notice the routine in the code I posted

lcd_print It is very similar to your original code... It has the msg pointer placed in the DPTR.. and fetches one byte at a time

Code:
lcd_print:
mov	a,#0h		; start of msg
movc	a,@a+DPTR	; set data pointer
cjne	a,#0h, mod1	; wait for null
ret
mod1:
acall	lcd_data	; send char to screen
inc	DPTR		; get next char
sjmp	lcd_print	; again
You need to open the lcd port only when the command bits are correct.. This is why we write lcd_data and lcd_cmd routines

All these routines do is wait for the module to be ready!!! then place the data or command on P1...

You can't just put data on P0 or P1 without controlling the LCD module... The module has its own processor on board (even virtual ones)

Last edited:

#### PG1995

##### Active Member
Code:
; Lcd 16x2 display
;P3.2 = RS... P3.3 = R/W... P3.4 = E

org	0
sjmp	Start
org	20h

Start:
clr	P3.3
mov	a.#38h		; function set 8 bits 2 rows 5x7 font
acall	lcd_cmd
mov	a.#0Eh		; screen on..cursor on.. no blink
acall	lcd_cmd
mov	a.#06h		; R/L cursor
acall	lcd_cmd
mov	a.#01h		; clear and home
acall	lcd_cmd

mov	DPTR, #msg	; point at message
acall	lcd_print	; send it to display

fin:
sjmp	fin

lcd_print:
mov	a,#0h		; start of msg
movc	a,@a+DPTR	; set data pointer
cjne	a,#0h, mod1	; wait for null
ret
mod1:
acall	lcd_data	; send char to screen
inc	DPTR		; get next char
sjmp	lcd_print	; again

msg1:
db	"AMERICA",0	; message

lcd_data
mov	P1,#0FFh	; make input
setb	P3.3		; R/W = Read
clr	P3.2		; RS = command
waitd:
clr	P3.4		; E low
setb	P3.4		; E high
jb	P1.7,waitd	; get busy flag
clr	P3.4		; E low
clr	P3.3		; R/W write
setb	P3.2		; RS data
mov	P1,a		; put data on LCD port
setb	P3.4		; E high
clr	P3.4		; E low
ret

lcd_cmd
mov	P1,#0FFh	; make input
setb	P3.3		; R/W = Read
clr	P3.2		; RS = command
waitc:
clr	P3.4		; E low
setb	P3.4		; E high
jb	P1.7,waitc
clr	P3.4		; E low
clr	P3.3		; R/W write
clr	P3.2		; RS command
mov	P1,a		; put command on LCD port
setb	P3.4		; E high
clr	P3.4		; E low
ret

end
This is a simple program to write to port 1 (8 bit ) with control on port 3 its easy to change ports..
Thank you, Rogers.

I have tried to assemble the quoted code above in MCU 8051 IDE and several errors were repoted. Could you make any sense out them? Thank you for the help.

Code:
Compiling file: rogersLCD.asm
Initializing pre-processor ...
Syntax error at 11 in rogersLCD.asm: Too few operands, mov must take exactly 2 operands
Syntax error at 13 in rogersLCD.asm: Too few operands, mov must take exactly 2 operands
Syntax error at 15 in rogersLCD.asm: Too few operands, mov must take exactly 2 operands
Syntax error at 17 in rogersLCD.asm: Too few operands, mov must take exactly 2 operands
Syntax error at 12 in rogersLCD.asm: Symbol not defined: lcd_cmd
Syntax error at 14 in rogersLCD.asm: Symbol not defined: lcd_cmd
Syntax error at 16 in rogersLCD.asm: Symbol not defined: lcd_cmd
Syntax error at 18 in rogersLCD.asm: Symbol not defined: lcd_cmd
Syntax error at 20 in rogersLCD.asm: Symbol not defined: msg
Syntax error at 32 in rogersLCD.asm: Symbol not defined: lcd_data
Syntax error at 37 in rogersLCD.asm: Invalid expression: "AMERICA"'
Syntax error at 39 in rogersLCD.asm: Unknown keyword: lcd_data'
lcd_data' is neither macro nor instruction nor directive
Syntax error at 55 in rogersLCD.asm: Unknown keyword: lcd_cmd'
lcd_cmd' is neither macro nor instruction nor directive
Pre-processing FAILED !
Creating code listing file ...		-> "rogersLCD.lst"
13 errors, 0 warnings

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Sorry mate..... I did copy it over quickly

Code:
; Lcd 16x2 display
;P3.2 = RS... P3.3 = R/W... P3.4 = E

org	0
sjmp	Start
org	20h

Start:
clr	P3.3
mov	a,#38h		; function set 8 bits 2 rows 5x7 font
acall	lcd_cmd
mov	a,#0Eh		; screen on..cursor on.. no blink
acall	lcd_cmd
mov	a,#06h		; R/L cursor
acall	lcd_cmd
mov	a,#01h		; clear and home
acall	lcd_cmd

mov	DPTR, #msg1	; point at message
acall	lcd_print	; send it to display

fin:
sjmp	fin

lcd_print:
mov	a,#0h		; start of msg
movc	a,@a+DPTR	; set data pointer
cjne	a,#0h, mod1	; wait for null
ret
mod1:
acall	lcd_data	; send char to screen
inc	DPTR		; get next char
sjmp	lcd_print	; again

msg1:
db	'AMERICA',0	; message

lcd_data:
mov	P1,#0FFh	; make input
setb	P3.3		; R/W = Read
clr	P3.2		; RS = command
waitd:
clr	P3.4		; E low
setb	P3.4		; E high
jb	P1.7,waitd	; get busy flag
clr	P3.4		; E low
clr	P3.3		; R/W write
setb	P3.2		; RS data
mov	P1,a		; put data on LCD port
setb	P3.4		; E high
clr	P3.4		; E low
ret

lcd_cmd:
mov	P1,#0FFh	; make input
setb	P3.3		; R/W = Read
clr	P3.2		; RS = command
waitc:
clr	P3.4		; E low
setb	P3.4		; E high
jb	P1.7,waitc
clr	P3.4		; E low
clr	P3.3		; R/W write
clr	P3.2		; RS command
mov	P1,a		; put command on LCD port
setb	P3.4		; E high
clr	P3.4		; E low
ret

end`
'll need to look into the "AMERICA" error... It seems fine....Ah single quotes not double...

Last edited:

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I've tested this in the real world and it works ok...But it wont work on the simulator.... It wont read the busy flag... You may want to put a delay in instead of polling the busy...

Status
Not open for further replies.