51 MCU Tutorial from Scratch - 9: MCU Addressing Mode and Instruction System

Publisher:温馨生活Latest update time:2012-02-15 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

What is the microcontroller addressing mode and instruction system

Through previous studies, we have understood the internal structure of the microcontroller, and we also know that to control the microcontroller and let it do things for us, we need to use instructions. We have learned a few instructions, but they are very scattered. From now on, we will systematically study the instruction part of the 8051 microcontroller.

1. Overview

1. Instruction format

We know that to make a computer do something, we have to give it instructions, and we also know that computers are very "stupid" and can only understand numbers, such as 75H, 90H, 00H, etc. that we wrote into the machine before, so the first format of instructions is the machine code format, also known as the digital format. But this format is really difficult for us humans, it is too difficult to remember, so there is another format, the mnemonic format, such as MOV P1, #0FFH, which is easier to remember. The relationship between these two formats is not difficult for us to understand. In essence, they are completely equivalent, just in different forms.

2. Assembly

We write instructions in assembly format, but computers and microcontrollers only understand machine code format, so we need to convert the instructions in assembly format into machine code format. There are two ways to do this conversion: manual assembly and machine assembly. Manual assembly is actually a table lookup, because the two formats are purely different, so there is a one-to-one correspondence, and you only need to look up a table. However, manual table lookup is always troublesome, so there is computer software, which replaces manual table lookup with computer software, and this is machine assembly.

2. Addressing of MCU

Let's review some of the instructions we have learned: MOV P1, #0FFH, MOV R7, #0FFH. These instructions are to send some data to the corresponding location. Why do we need to send data? The first reason is that the number sent in can make all the lights go out, and the second reason is to achieve delay. From here we can see that when programming with the programming language of the microcontroller, data transfer is often used. In fact, data transfer is an important task when programming the microcontroller. There are 28 instructions in total (the microcontroller has a total of 111 instructions). Let's start with the data transfer instructions.

Analyzing the instruction MOV P1, #0FFH, we can easily come to the conclusion that the first word MOV is a command verb, which is to decide what to do. MOV is MOVE with one less E, so it means "transfer", which is the instruction that specifies what to do. There are some parameters behind it. Analyzing it, data transfer must have a "source", which is the number you want to send, and a "destination", which is where you want to send the number. Obviously, in the above MCU instruction, the number to be sent (source) is 0FFH, and the place to be sent (destination) is the P1 register. In data transfer instructions, the destination is written after the instruction, and the source is written at the end.

In this instruction, the number itself is sent to P1. In other words, after completing this instruction, we can clearly know that the value in P1 is 0FFH, but the number itself cannot be given directly at any time. For example, the delay program example of the microcontroller given above is written like this:

MAIN: SETB P1.0; (1)

LCALL DELAY; (2)

CLR P1.0; (3)

LCALL DELAY; (4)

AJMP MAIN; (5)

; The following subroutine

DELAY: MOV R7, #250; (6)

D1: MOV R6, #250; (7)

D2: DJNZ R6, D2; (8)

DJNZ R7, D1; (9)

RET; (10)

END; (11)

Table 1

-------------------------------------------------- ---

MAIN: SETB P1.0; (1)

MOV 30H, #255

LCALL DELAY;

CLR P1.0; (3)

MOV 30H,#200

LCALL DELAY; (4)

AJMP MAIN; (5)

; The following subroutine

DELAY: MOV R7, 30H; (6)

D1: MOV R6, #250; (7)

D2: DJNZ R6, D2; (8)

DJNZ R7, D1; (9)

RET; (10)

END; (11)

Table 2

In this way, the delay time is the same every time I call the delay program (roughly 0.13S). If I put forward such a requirement: after the light is on, the delay time is 0.13S and then the light goes out, and after the light goes out, the delay time is 0.1s and then the light comes on, and so on. Can such a program still meet the requirements? No, what should we do? We can change the delay program to this (see Table 2): The call is the main program in Table 2, that is, first send a number to 30H, and the value in R7 in the subroutine is not fixed, but is determined according to the number passed from the 30H unit. This can meet the requirements.

From this we can conclude that in data transfer, to find the number being transferred, in many cases, this number cannot be given directly and needs to be changed. This leads to a concept: how to find the operand. We call finding the address of the unit where the operand is located addressing. Here we directly use the address of the unit where the number is located to find the operand, so this method is called direct addressing. In addition to this method, there is another method. If we put the number in the working register and find the data from the working register, it is called register addressing. For example: MOV A, R0 is to send the data in the R0 working register to the accumulator A. Here is a question: We know that the working register is part of the memory unit. If we choose the working register group 0, then R0 is the 00H unit of the RAM. In this case, isn't there any difference between MOV A, 00H and MOV A, R0? Why should we make a distinction? Indeed, the results of executing these two instructions are exactly the same. Both of them send the content in unit 00H to A, but the execution process is different. It takes 2 cycles to execute the first instruction, while the second one only takes 1 cycle. The first instruction requires two bytes (E5H 00H) to become the final target code, while the second one only needs one byte (E8h).

Why are you so fussy? Isn't it just one cycle? If it is a 12M crystal oscillator, it is only 1 microsecond. How much can a byte have?

No, if this instruction is executed only once, it may not matter, but if an instruction is executed 1,000 times, it is 1 millisecond. If it is executed 1000000 times, it is 1S error, which is considerable. The microcontroller is responsible for real-time control, so it must be so "meticulous". The same is true for the number of bytes.

Let me ask another question. Now we know that we can find operands by directly giving them (immediate addressing) and by directly giving the address of the unit where the number is located (direct addressing). Is this enough?

Looking at this problem, it requires starting from unit 30H, taking 20 numbers and sending them into the A accumulator respectively.

As far as the method we have mastered at present is concerned, to fetch a number from the 30H unit, we use MOV A, 30H. Then what about the next number? If it is from the 31H unit, how to fetch it? Or can we only use MOV A, 31H? Then, wouldn't it take 20 instructions to write 20 numbers? There are only 20 numbers here. If we want to send 200 or 2000 numbers, wouldn't we have to write 200 or 2000 commands? This is too stupid. Why does this happen? Because we only know how to write the address in the instruction, so there is no way. If we don't write the address directly in the instruction, but put the address in another register unit, and decide which unit to fetch data according to the value in this register unit, for example, if the current value in this register is 30H, then fetch it from the 30H unit, and if it is 31H, fetch it from the 31H unit, and this problem can be solved. How to solve it? Since we are looking at the value in the register, we can change the value in it by some means, such as adding 1 to the value in the register after taking a number. It is still the same instruction, but the object of the number is different, right? Let's explain it through an example.

MOV R7, #20

MOV R0, #30H

LOOP: MOV A, @R0

INC R0

DJNZ R7,LOOP

We can understand most of the instructions in this example. The first sentence is to send the immediate value 20 to R7. After execution, the value in R7 should be 20. The second sentence is to send the immediate value 30H to the R0 working register. So after execution, the value in the R0 unit is 30H. The third sentence is to see what the value in the R0 unit is, use this value as the address, take the content of this address unit and send it to A. At this time, the result of executing this instruction is equivalent to MOV A, 30H. The fourth sentence, which we have not learned, adds 1 to the value in R0. Therefore, after execution, the value in R0 is 31H. The fifth sentence, which we have learned, subtracts 1 from the value in R7 to see if it is equal to 0. If it is not equal to 0, it will jump to the label LOOP to continue execution. Therefore, after executing this sentence, it will jump to execute MOV A, @R0, which is equivalent to executing MOV A, 31H (because the value in R0 is already 31H at this time). This continues until the value in R7 is subtracted successively and equals 0, that is, the loop is repeated 20 times, and our requirement is achieved: 20 data are sent to A starting from unit 30H.

This is also a way to find data. Since the data is found indirectly, it is called indirect addressing. Note that in indirect addressing, only R0 or R1 can be used to store the data being searched.

Reference address:51 MCU Tutorial from Scratch - 9: MCU Addressing Mode and Instruction System

Previous article:51 MCU Tutorial from Scratch - Part 8 Special Function Registers
Next article:51 MCU Tutorial from Scratch - 10 Data Transfer Instructions

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号