When you work on a relatively complex project in a project team, it means that you are no longer alone. You need to work with your team members to complete the project together. This requires that the team members are responsible for a part of the project. For example, you may only be responsible for communication or display this piece. At this time, you should write your own piece of this program as a module, debug alone, leaving the interface for other modules to call. Finally, after the team members finish writing the module they are responsible for and debug it, the team leader will perform the combined debugging. Like these occasions require that the program must be modular. The benefits of modularity are many, not only to facilitate the division of labor, but also to facilitate the debugging of the program, to facilitate the division of the program structure, but also to increase the readability and portability of the program.
Beginners often do not understand how modular programming is, in fact, it is easy to learn, but it is also one of the effective ways to organize a good program structure.
This article will first talk about modular methods and precautions. Finally, we will use the most widely used keil c compiler for beginners as an example to give the detailed steps of modular programming.
Modular programming should understand the following overview:
(1) The module is a combination of a .c file and a .h file, and the header file (.h) is the declaration for the module interface;
This article outlines the implementation and nature of the modularization: write the code of a function module as a .c file, and then place the interface functions of the module in the .h file. For example: If you use a liquid crystal display, then You may write an LCD driver module to implement the reality of characters, Chinese characters, and images, named: led_device.c. The module's .c file can be roughly written as:
Note: Only these two functions are written here. The scope of the first delay function is within the module and the second one is needed by other modules. For simplicity, the function body is not written here.
The module interface is given in the .h file. In the above example, a character function is written to the LCD: wr_lcd (uchar dat_comm, uchar content) is an interface function, because other modules call it, then the .h file must Declaring this function as an external function (using the extrun keyword modifier), another delay function: void delay (uint us) is only used in this module (local function, decorated with the static keyword), so it does not need to put To the .h file.
The .h file format is as follows:
Here are three things to note:
1. In the keil compiler, the extern keyword does not complain even if it is not declared, and the program works well, but it does not guarantee that other compilers will be used. It is strongly recommended that you develop good programming practices.
2. The functions in the .c file will only appear in the .h file when used by other modules. Like the local delay function static void delay (uint us), even if it appears in the .h file, it is doing no work because the other modules are Do not call it, in fact it can not call it (static keyword restrictions).
3. Note that this sentence must end with a semicolon ";", I believe that many students have encountered this strange compiler error: error C132: 'xxxx': not in the formal parameter list, this error is actually .h The last part of the function declaration is missing the semicolon.
Application of the module: If you need to use the function void wr_lcd (uchar dat_comm, uchar content) of the LCD driver module lcd_device.c in the LCD menu module lcd_menu.c, just add the LCD driver module to the lcd_menu.c file in the LCD menu module. The header file lcd_device.h can be.
(2) The external functions and data that a module provides to other modules should be called with the extern keyword declaration in the .h file;
This sentence has been reflected in the above example, that is, a module provides external functions and global variables for other modules to call the file in the .h file with the extern keyword declaration. The following focuses on the use of global variables. One of the difficulties in using modular programming (as opposed to the novice) is the setting of global variables. It is often difficult for beginners to figure out how the variables that are common to the module and the module are implemented. The conventional approach is mentioned in this sentence, in .h. The external data in the file is declared with the extern keyword. For example, the variable value in the above example is a global variable. If a module also uses this variable, just like the use of an external function, you only need to include #include “lcd_device.h†in the used module.c file.
Another method of dealing with global variables between modules comes from the embedded operating system uCOS-II. This operating system handles global variables in a very special way and is also more difficult to understand. However, after learning, it can be used magically. This method only needs to be used in the header file. Is defined once. The method is:
In the .h header file that defines all global variables (uCOS-II defines all global variables in a .h file):
When the compiler processes the .C file, it forces xxx_EXT (found in the corresponding .H file) to be empty (since xxx_GLOBALS is already defined). So the compiler allocates memory space for each global variable, and when the compiler processes other .C files, xxx_GLOBAL is not defined and xxx_EXT is defined as extern so that the user can call external global variables. To illustrate this concept, see uC/OS_II.H, which includes the following definitions:
At the same time, uCOS_II.H has the following definitions:
#define OS_GLOBALS
#include "includes.h"
When the compiler processes uCOS_II.C, it causes the header file to become as follows because OS_EXT is set to null.
INT32U OSIdleCtr;
INT32U OSIdleCtrRun;
INT32U OSIdleCtrMax;
The compiler will allocate these global variables in memory. When the compiler processes other .C files, the header file becomes as follows because OS_GLOBAL is not defined, so OS_EXT is defined as extern.
Extern INT32U OSIdleCtr;
Extern INT32U OSIdleCtrRun;
Extern INT32U OSIdleCtrMax;
In this case, there is no memory allocation, and any .C file can use these variables. This only needs to be defined once in the .H file.
(3) The functions and global variables in the module must be declared with the static keyword at the beginning of the .c file;
This sentence mainly describes the role of the keyword static. Static is a very important keyword. He can do some constraints on functions and variables, and can pass some information. For example, in the above example, the delay function static void delay (uint us) is defined in the LCD driver module .c file. This function is modified by static. On the one hand, it limits the function scope of the function and it only works in this module. The aspect also gives people the message that the function will not be called by other modules. The following is a detailed description of the role of this keyword. In the C language, the keyword static has three distinct effects:
1. In the body of the function, a variable declared as static maintains its value during the function being called.
2. Within the module (but outside the body of the function), a variable that is declared static can be accessed by functions used within the module but cannot be accessed by other functions outside the module. It is a local global change
the amount.
3. Within a module, a function declared static can only be called by other functions within this module. That is, this function is limited to the local scope of the module that declares it.
The first two are easier to understand. The last one is the static void delay (uint us) that was just mentioned in the example. The localization function works quite well.
(4) Never define a variable in the .h file!
Oh, it seems a little alarmist, but I don't think how many people will define variables in the .h file.
Compare the code:
Code one:
The result of the above program is that integer variables a are defined in modules 1, 2, and 3, and a different address element corresponds to different modules. Such a program is never needed in the world. The correct approach is:
Code two:
In this way, if module 1, 2, and 3 operate a, corresponding to the same memory unit.
Note:
An embedded system usually includes two types (note two types, not two):
(1) hardware driver module, a specific hardware corresponding to a module;
(2) Software function modules, the division of modules should meet the requirements of low coupling and high cohesion.
The following takes the keil C compiler as an example to talk about the modular programming steps.
The following program is divided into three layers, a total of seven modules, together serving the main program (they will also call each other).
The structure of the program is as follows:
The introduction of the main modules and functions:
First, the underlying driver
1. Infrared keyboard: The program operates via the infrared keyboard. Infrared keyboard exclusive timer 0 and external interrupt 0 to achieve infrared decoding and keyboard key value recognition. The infrared keyboard defines five buttons, namely, up, down, left, right and confirm.
2. LCD liquid crystal display: The program mainly displays information through the LCD, and the LCD liquid crystal display driver provides a function interface for displaying Chinese characters, graphics, and ASCII codes. Can display full-screen, single-line Chinese characters, ASCII code at any position, but also full-screen, half-screen display graphics.
Second, the function module
1. LCD menu program: The menu program can make the human-computer interaction more convenient and easier. The depth of the menu level of this menu program is limited by the size of the RAM, which will consume 4 bytes of RAM for each additional level of menu. The menu program mainly completes the scheduling of the menu function function, LCD display refresh.
2. Calculator program: To achieve addition, subtraction, multiplication, and division within 65536, an overflow will occur if the range is exceeded. When the overflow occurs, the LCD will display the error message “Error: Overflow occurred.†At the same time, this operation is ignored. For a negative number, the "-" sign is displayed. When the division number is zero, the LCD displays the error "Error: Divisor is zero".
3. Power-on frequency memory program: It mainly reads and writes the EEPROM based on IIC bus. After power-on, the MCU writes the power-on times to EEPROM.
4. Serial port test program: After entering the program, the microcontroller sends the string “Hello Word!†to the computer and sends the number 24 (displayed as characters). The purpose of writing this program is to be able to easily send strings and variables to the computer, to facilitate the debugging of the program. The serial port occupies the serial port resources and shares the timer 1 with the frequency measurement program.
5. Frequency measurement: multiplex timer 1, occupy external interrupt 1, and achieve 5~20KHZ frequency measurement.
Third, the main program
The main program mainly completes the initialization of the program, displays the LCD menu, monitors the keyboard program, and updates the menu according to the key value.
The steps are:
1. New project.
2. Click File-New (or click the shortcut icon: ), create a new document.
3. Click File-Save (or click the shortcut icon: ), Save the newly created document, fill in the LCD_device.c (liquid crystal driver module: LCD_device, provide interface for displaying Chinese characters, characters and images) after the file name, and click OK.
Write the LCD driver within this document.
4. Click on File-New (or click the shortcut icon: ), then create a new document.
5. Click on File-Save (or click the shortcut icon: ), Save the new document, fill in the LCD_device.h in the file name (the header file of the LCD driver module, the module's interface and global variables are declared here (thank you for the error of the user Yang Kangjia correcting this, the original will be "declaration" written as " Definitions", header files are generally used to declare variables and interfaces). Click OK. Organize global variables and interface functions in this document. The effect after the above steps is shown in the figure below:
At this point, the LCD driver module is written, and the module can be individually debugged.
6. Repeat steps 2~5 above to define the infrared keyboard module: key.c and key.h
Menu module: menu.c and menu.h
Serial communication module: uart_.c and uart.h
Calculator module: counter.c and counter.h
Frequency measurement module: mea_fre.c and mea_fre.h
Boot memory module: eepram.c and eepram.h
7. Repeat steps 2~3 above to define the main program main.c
The final result is shown in the figure below:
After completing 1~7 steps, some whites will habitually click the compile button. At this time, two warning messages will appear:
*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
This is because you just wrote the program modules but did not add them to the project.
Solution: In the Project Workspace box, right-click the Source group 1 folder, select Add Files to Group 'Source Group 1', and add your .c file in the pop-up dialog box.
For a long time long ago, I also had personal experience of the above two warnings. At that time I was still in college. There was a large group of good buddies around. Now... I just want to think of myself! ! !
Butt Connector,Lugs Insulated Female Connectors,Insulated Female Connectors,Non-Insulated Spade Terminals Wire Connector
Taixing Longyi Terminals Co.,Ltd. , https://www.lycopperterminals.com