"Professor Zhou Ligong's new book" programming for ametal framework and interface (Part I) "introduces the ametal framework in detail. By reading this book, you can learn the highly reusable software design principles and the development idea of interface oriented programming, focus on your own" core domain ", change your own programming thinking, and realize the common progress of enterprises and individuals.
Chapter 8 is to deeply understand ametal. The content of this paper is 8.3 buzzer interface and 8.4 temperature acquisition interface.
8.3 buzzer interface
>>>8.3.1 defining interfaces
1. Interface naming
Since the object of operation is a buzzer, the interface is named "am"_ buzzer_” As a prefix. For the buzzer, the basic operation is to turn on and off the buzzer. Two corresponding interface names can be defined:
am_ buzzer_ on
am_ buzzer_ off
In particular, in some applications, an operation similar to the "beep" of the buzzer is also required, that is, it will stop automatically after a certain time. The interface name can be defined as:
am_ buzzer_ beep
am_ buzzer_ beep_ async
Two interfaces are defined here, which are used for the specified time of buzzer ringing. The difference between them is that the return time of the function is different. am_ buzzer_ Beep will wait for the end of the beep and return to am_ buzzer_ beep_ Async will not wait, the function will return immediately, and the buzzer will stop automatically after the specified time.
Obviously, for am_ buzzer_ beep_ Async interface may not be thought of in the initial buzzer interface design. This interface is derived from a large number of practical applications. In some special application scenarios, you do not want the program to be blocked. Therefore, you need to provide am_ buzzer_ beep_ Asynchronous interfaces such as async.
2. Interface parameters
In the design of LED general interface, because there may be multiple LEDs in a system, some method must be used to distinguish different LEDs, such as LED with unique ID number_ ID to distinguish multiple LEDs in the system. According to this logic, do you also need a buzzer_ ID to distinguish different buzzers?
The buzzer has a single function and is a sound device. In a specific application, there is often only one sound device, so it is not necessary to use multiple buzzers. Therefore, the buzzer can be regarded as a single instance device of the system. Based on this, there is no need to use a device similar to buzzer_ ID to distinguish multiple buzzers. For the interface to turn on and off the buzzer, no parameters are required, that is:
am_ buzzer_ on(void);
am_ buzzer_ off(void);
In particular, for am_ buzzer_ Beep and am_ buzzer_ beep_ Async interface does not need parameters to distinguish multiple buzzers, but its function is to sound for a certain time. Therefore, it also needs a parameter to specify the duration of sound.
am_ buzzer_ beep(uint32_ t ms);
am_ buzzer_ beep_ async (uint32_ t ms);
Where MS is used to specify the duration of the beep, in milliseconds.
3. Return value
The interface has no special description. The return values of all interfaces are directly defined as the standard error number of int type. Based on this, the complete definition of buzzer control interface is shown in table 8.5.
Table 8.5 buzzer general interface (AM)_ buzzer.h)
See Figure 8.8 for the corresponding class diagram.
Figure 8.8 buzzer interface class diagram
>>>8.3.2 implementation interface
1. Abstract buzzer device class
The buzzer has 4 general interfaces in total, of which am_ buzzer_ Beep () and am_ buzzer_ beep_ The async () interface can be directly based on am_ buzzer_ On () and am_ buzzer_ Off () interface implementation, am_ buzzer_ See program listing 8.24 for the implementation of beep().
Procedure list 8.24 am_ buzzer_ Implementation of beep()
In the program, first use am_ buzzer_ On() turns on the buzzer. If it fails to turn on the buzzer (the return value is negative), the corresponding error number will be returned directly. If it succeeds, use am_ Mdelay() delays the specified time and finally turns off the buzzer. For am_ buzzer_ beep_ Async () interface, which needs to be returned immediately. The delay function cannot be used directly inside the function. It can be implemented based on the software timer. See the program list 8.25 for the example program.
Procedure list 8.25 am_ buzzer_ beep_ Async () sample program
In the program, first use am_ buzzer_ On() turns on the buzzer. If it fails to turn on the buzzer (the return value is negative), the corresponding error number will be returned directly. If it succeeds, the software timer will be started, and the timing time will be the specified beeping time. After starting the timer, the function will return immediately. When the timing time of the software timer expires, the user-defined callback function needs to be called__ beep_ timer_ Callback(), in the callback function, the software timer and buzzer are closed, and the beeping ends.
Obviously, before using the software timer, it needs to be initialized to__ beep_ timer_ The callback() function is used as the callback function after the timing time expires, such as:
Where are the initialization statements? Here we only show the implementation of am using software timer_ buzzer_ beep_ The async () function is an example, and the appropriate time to initialize the software timer will be introduced later.
Due to am_ buzzer_ Beep () and am_ buzzer_ beep_ The async () interface can be directly based on am_ buzzer_ On () and am_ buzzer_ Off (), so the core of the buzzer interface is to implement am_ buzzer_ On () and am_ buzzer_ The off () interface can abstract the corresponding two methods according to the design method of LED or hc595. Namely:
Although this design method is completely feasible, considering that on and off are a group of symmetrical interfaces, the functions belong to the same class and have great similarity, only one method can be abstracted and a Boolean parameter can be used to distinguish whether the operation is on or off, such as:
It can be seen that the definition of abstract methods is not necessarily intact. The definition of abstract methods according to the interface can be adjusted appropriately, as long as the general interface can be realized based on the abstract methods.
Although there is only one abstract method, in order to ensure the unity of structure and facilitate subsequent expansion (such as adding abstract methods), the abstract methods are often placed in a virtual function table. Namely:
Similarly, abstract methods and P_ Cookies are defined together as abstract buzzer devices. For example:
Implement am in front_ buzzer_ beep_ The software timer is used in async () interface. Obviously, the software timer is used to realize a buzzer calling function and is related to the buzzer device. It should not be defined as a global variable. Instead, it is directly defined in the abstract device structure, that is:
The abstract method defined in the abstract device needs to be completed by a specific buzzer device, am_ buzzer_ On () and am_ buzzer_ The off () interface can be implemented directly based on abstract methods.
When defining the buzzer interface, because the buzzer is a single instance device (there is only one in the system), the parameters that distinguish the buzzer object, such as ID number or handle parameter, are not defined in the interface. Then, how to find the corresponding device when implementing the interface? Since there is only one buzzer device in the system, a global variable can be directly used to point to the buzzer device, am_ buzzer_ On () and am_ buzzer_ See program listing 8.26 for the implementation of off().
Procedure list 8.26 am_ buzzer_ On and am_ buzzer_ Example program of off()
Among them__ gp_ buzzer_ Dev is a pointer to the buzzer device. Initially, there is no valid buzzer device, so the initial value is null. Obviously, to use the buzzer normally, you must make__ gp_ buzzer_ Dev points to a valid buzzer device, which requires a specific buzzer device to implement PFN_ buzzer_ Set abstract method.
In order to complete__ gp_ buzzer_ For the assignment of dev, a device registration interface needs to be defined to register a valid buzzer device in the system:
In order to facilitate adding a buzzer device to the system, avoid directly operating each member of the buzzer device, and pass the member to be assigned to the interface function through parameters. See procedure list 8.27 for details.
Procedure listing 8.27 adding a buzzer device to the system
The program first determines the validity of parameters, and then completes the abstract method and P_ The cookie is assigned, and then the global variable is assigned__ gp_ buzzer_ The assignment of dev makes it point to the effective buzzer device. Finally, the software timer in the abstract device is initialized to facilitate the implementation of asynchronous buzzer calling interface. It can be seen that the initialization operation of software timer is completed when adding a buzzer device.
Obviously, next, we need to derive the specific buzzer device based on the abstract buzzer device, and complete the abstract method PFN in the specific buzzer device_ buzzer_ Set, and use am_ buzzer_ dev_ Register () interface adds a buzzer device to the system, so that users can use the buzzer general interface to operate to specific and effective buzzers.
For ease of reference, the buzzer device interface file (AM) is shown in program listing 8.28_ buzzer_ Dev.h). See Figure 8.9 for the corresponding class diagram.
Procedure list 8.28 am_ buzzer_ Dev.h file contents
Figure 8.9 Abstract buzzer device class
2. Specific buzzer equipment
Taking the use of PWM output to control the sound of buzzer as an example, this paper briefly describes the implementation method of specific buzzer equipment. First, a specific device class should be derived from the abstract device class. See Figure 8.10 for the class diagram. Specific buzzer device classes can be directly defined, such as:
Figure 8.10 specific buzzer equipment
am_ buzzer_ pwm_ dev_ T is the specific buzzer equipment class. After having this type, you can use this type to define a specific buzzer device instance, that is:
In particular, since the buzzer is a single instance device, it is not possible to define multiple instances using this type. Therefore, you can directly define a buzzer device instance in the file implemented by a specific device, without requiring users to customize the device instance using this type. Based on this, am_ buzzer_ pwm_ dev_ T type does not need to be open to users and can be defined directly in. C file_ buzzer_ pwm_ dev_ T type does not need to be open to users, but is only used internally. Therefore, the type name can be modified to be double underlined "_" Start, as in am_ buzzer_ The equipment type defined in PWM. C file and corresponding equipment examples are as follows:
When using PWM output to control buzzer, you need to know PWM handle, channel number and other relevant information, which needs to be saved in the equipment. Therefore, the definition of updated equipment type is as follows:
Obviously, these members can only be used after initialization. The prototype of the defined initialization function is:
Among them, PWM_ Handle is the standard PWM service handle, Chan is the PWM channel number, duty_ NS and period_ NS specifies the pulse width and period of the output PWM waveform respectively, and determines the loudness and frequency of the buzzer. For example, the buzzer on am824 core board.
If SCT is used to output PWM, pio0_ 24 corresponds to channel 1 of SCT, so the call form of initial call function is as follows:
In the program, am is used_ lpc82x_ sct0_ pwm_ inst_ The init() function obtains the PWM handle, uses channel 1, and sets the cycle of the output PWM to 400000ns, that is, 2.5KHz (1000000000 / 400000), and the pulse width is exactly half of the cycle, that is, the duty cycle of the output PWM is 50%. See Listing 8.29 for the implementation example of initialization function.
Listing 8.29 implementation example of initialization function
The program first determines the validity of parameters, then completes the assignment of relevant members in the device instance, and then calls am_ buzzer_ dev_ Register() function, add buzzer equipment to the system, and finally configure the pulse width and cycle of PWM output channel. When you add a device, P_ FuncS is assigned as&__ g_ buzzer_ pwm_ drv_ funcs,p_ The cookie is assigned to the address of the specific device, i.e. P_ The cookie points to the device itself__ g_ buzzer_ pwm_ drv_ FuncS contains the concrete implementation of abstract methods. See the procedure for the complete definition
Our other product: