(1) Use macro definitions instead of direct IO operations
I think the most typical example is a buzzer, a 4KHZ driven AC buzzer. If the buzzer is connected to the P50 port, then the driver code should be:
mov a,@0x01
xor 0x05,a
The code is very simple. The result of XORing 0x01 with P5 is the inversion of P50. If the inversion is continued, the output square wave of P50 is obtained. It can be described in C language as follows:
PORT5 ^= 0x01
Well, the portability of this code is extremely poor. If my buzzer needs to be modified to port P62, the code must also be modified accordingly:
mov a,@0x04
xor 0x06,a
Of course, we only need one place here, so it is not necessarily troublesome. If there are 50 or even 100 places in your code that need to be modified, I think you will definitely go crazy. So this non-portable code must be thrown away.
Modification 1:
By defining the IO port of the buzzer
buz_port EQU 0x05
mov a,@0x01
xor buz_port,a
Here, the name buz_port is used to replace the output port of the buzzer. Now the portability is improved. If the port is modified, we only need to redefine the buz_port macro to complete all the modifications to the code.
According to the above description, the port problem can be solved, but we found that the problem has not been completely solved. For mov a,@0x01, we still have to manually calculate which pin the buzzer is on, and we have to modify them one by one, so it still needs improvement.
Modification 2:
buz_port EQU 0x05
buz_pin EQU 0
mov a,@1< xor buz_port,a This code truly achieves the so-called portability. Explain it in C language buz_port ^= 1< Students who are familiar with C language should be familiar with this expression. 1< For example 1<<0 The result is 1 (00000001b) 1<<3 The result is 8 (00001000b) This is the truth, but it is not responsible at all to use, it can be said to be very easy to use. It can be directly matched with the name of the IO, for example, if it is P62 mentioned above, then the definition should be: buz_port EQU 0x06 buz_pin EQU 2 You only need to modify the definition, and all parts of the program that use this IO port do not need to be modified, so the portability is very good. Although this technique is simple, it must be learned. (2) Dynamically bind IO ports Consider a situation where we use three IO ports to send PWMs with different duty cycles to drive three LEDs of different colors to create a colorful light effect. The requirement is that the three IO ports are independently controlled, so the natural idea is that each of the three programs generates PWM, which means that the situation of one channel is expanded to three channels and controlled separately. However, the consumption of registers and ROM has also become three times correspondingly, which is easy to understand. However, the three programs are surprisingly similar, and it is very likely that only the IO port output part has been modified. Let's think about it, can we write them together? In other words, use one PWM program to generate PWM and output it to three different IO ports. I suggest that you think about it yourself before reading it, and type the program, and you will deeply understand the difficulty of this problem. Similar situations are not uncommon, such as RC temperature measurement. If you measure one channel, it is easy to do, but what if you measure many channels? You don't really need a corresponding program for each channel, right? That's absolutely impossible. The solution is similar, that is, use one program to process the input data of multiple IOs and switch. This is a bit like the data selector in the digital circuit. The answer is: dynamically bind IO port input and output, the way is indirect addressing with R0 and R4. How to achieve it? In fact, it is very simple, because indirect addressing itself can access addresses 0x05 and 0x06, that is, it can directly access PORT5 and PORT6, so it is easy to think of, for example, the output status of PORT6, and then the output status of PORT6 is changed to 0X0F (P60~P63 high level, P64~P67 low level). The general practice is: mov a,@0x0f mov PORT6,a If indirect addressing is used, then mov a,@0x06 mov R4,a mov a,@0x0f mov R0,a First, put the register address 0x06 to be accessed into the address register R4, and then send the data 0x0f to R0. The actual effect is to send 0xf to PORT6. Just run it with the emulator and it will be OK. It is very simple. After understanding this principle, the so-called "dynamic binding" is easy to understand. The original instructions for accessing the IO port using PORT5 PORT6 are changed to indirect addressing using R0 R4, so that the program can become very flexible. For example, let’s go back to the previous buzzer example. The system has two buzzers, P50 and P62. Let's see how to output square waves to these two buzzers through dynamic binding. Allocate two registers to store the port information that currently needs to be operated. REG_PORT == 0x10 REG_PIN == 0x11 If you need to output P50 Mov a,@0x05 Mov REG_PORT,a Mov a,@1<<0 Mov REG_PIN,a Then the buzzer driver function should be modified accordingly. As mentioned earlier, it used to operate directly on the PORT port, but now it has become indirect addressing. Move a,REG_PORT Mov R4,a Move a,REG_PIN Xor R0,a Do you understand? Actually, it is very simple. First, determine the port that needs to be operated. The value of REG_PORT is set to 0x05, which means to operate PORT5. Then, XOR the pin 1<<0, which is 0x01, with R0 (now pointing to PORT5). The result is that P50 changes the level. Multiple calls will turn it into an output square wave. If you need to output P62 now, then things become very simple, just need to: Mov a,@0x06 Mov REG_PORT,a Move a,@1<<2 Mov REG_PIN,a Then the square wave generation part in the middle is universal. We can directly send the value to the port we need to operate. See? This is the so-called dynamic binding. If you consider portability, that is, if the port may be modified in the future, then define a macro as mentioned in the first point of the set. Anyway, this thing needs to be used flexibly. Conclusion: These are two very simple things. I have spent a lot of time describing them just to illustrate the problem. If you understand them, they are really simple, even not worth mentioning. However, how should I put it? Programs are accumulated little by little with these little tricks. I hope the two little tricks I talked about today can be helpful to you.
Previous article:Microcontroller macro definition study notes
Next article:MCU Multiplication and Division Examples
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- Sensirion SEK-SVM40 Review Summary
- [Pingtou Ge RVB2601 creative application development] Weather broadcaster based on Pingtou Ge RVB2601
- How to replace STM32 with GD32?
- [Homemade] DS-T10 Portable Smart Soldering Iron
- Frequently Asked Questions about Lingdongwei MM32F103 MCU
- The problem of increasing the driving capability of the oscillation circuit
- Antenna Design Solutions for Next Generation Mobile Devices
- Chapter 3 Using external interrupt EXTI to read keystrokes
- What are the effects of placing TVS tubes in front and behind? Which one is correct? Why?
- MAGTROL HD-106-8NA-0100 Dynamometer Failure