• 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.

adding all digits in a number, MCU 8051

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
	ADD A, #4
	ADD A, #5
	ADD A, #7
	ADD A, #8
	ADD A, #5
	ADD A, #9
	ADD A, #9
	ADD A, #9
	ADD A, #9
	ADD A, #1
	SJMP Repeat

END
Regards
PG
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member

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
		acall		AddDigit

		;continue with main code

		

AddDigit:	push		ACC			;store accumulator
		push		R0			;store R0
		mov		R0,#0x30		;set starting RAM address
		mov		A,#0			;clear accumulator
AddLoop:	add		A,@R0			;add digit
		inc		R0			;increment digit address
		djnz		R1,AddLoop		;decrement digit counter, continue adding if counter > 0
		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
Most Helpful Member
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
 

PG1995

Active Member
Hi

Could you please help me with interfacing LCD display in MCU 8051 IDE?

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

Please help me. Thanks.

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
Most Helpful 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..
 

Jon Wilder

Active Member
Can you tell us the make and model of the exact display you're using? Please help me help you. Thanks. ;)
 

PG1995

Active Member
Can you tell us the make and model of the exact display you're using? Please help me help you. Thanks. ;)
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
Most Helpful Member
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
Most Helpful Member
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:

EE World Online Articles

Loading

 
Top