📄 c515.txt
字号:
if(clock.sec == 60) {
clock_sec = 0 ;
}
}
}
To make this 4 module program useful, the main loop needs to be altered to:
/* Module Containing Main Program */
/* MAIN.C */
#include <reg517.h>
/* External Definitions */
extern void v24ini_537(void) ;
extern void timer0_init_537(void) ;
/* General Clock Structure Template */
struct time { unsigned char secs ;
unsigned char msec ; } ;
/* Reference XDATA Structure In Another Module */
extern struct time xdata clock ; extern bit clock_reset_fl // Flag to tell t
imer0 interrupt to reset clock to zero
/* Local Data Declaration */
bit clock_run_fl ; // Flag to tell timer0 interrupt
// to stop clock
void main(void) {
v24ini_537() ;
timer0_init_537() ;
while(1) {
printf("Time = %d:%d:%d:%d",clock.hours,
clock.mins,
clock.secs,
clock.msecs) ;
}
if(P1 | 0x01) {
clock_run_fl = 1 ; // If button pressed start clock
}
else {
clock_run_fl = 0 ; // If button released stop clock
}
if(P1 | 0x02) {
clock_reset_fl = 1 ; // If button pressed clear clock
}
}
4.3.2 Maintainable Inter-Module Links
The foregoing program has been contructed in a modular fashion with each maj
or functional block in a separate module (file). However even with this smal
l program a maintenance problem is starting to become apparent The source of
the trouble is that to add a new data item or function, at least two module
s need to be edited - the module containing the data declaration plus any ot
her module which makes a reference to the additional items. With long and me
aningful names common in C and complex memory space qualification widespread
in C51, much time can be wasted in getting external references to match at
the linking stage. Simple typographic errors can waste huge amounts of time!
In large programs with many functions and global variables, the global area
preceding the executable code can get very untidy and cumbersome. Of course,
there is an argument that says that having to add external references to th
e top of a module when first using a new piece of global data is good practi
ce, as it means that you are always aware of exactly which items are used. I
t is preferable to the common approach of having a single include file incor
porated as a matter of course in each source file, containing an external re
ference for every global item, regardless of whether the host file actually
needs them all.
This latter method inevitably leads to the undesirable situation where an or
iginal data declaration in the source module is sitting alongside its extern
al reference in the general include file.
A solution to this is to have "module-specific" include files. Basically, fo
r each source module ".c" file, a second ".h" include is created. This auxil
liary file contains both original declarations and function prototypes plus
the external references. It is therefore similar in concept to the standard
library .h files used in every C compiler. The trick is, however, to use con
ditional compilation to prevent the original declarations and the external v
ersions being seen simultaneously.
When included in their home modules, i.e. the ".c" file having the same root
, only the original declarations are seen by C51 whereas, when included in a
foreign module, only the external form is seen. To achieve this apparent in
telligence, each source module must somehow identify itself to the include f
ile.
The means to achieve this is to place a #define at the top of each module gi
ving the name of the module. When included in its "home" module, the #ifdef-
#else#-endif will cause the preprocessor to see the original declarations. W
hen placed in foreign modules not sharing the same root, the preprocessor wi
ll see the external equivalents. Keil supports __FILE__ but it is not of pra
cticle use in this context, as its "value" cannot be used for a #define name
.
By only including module-specific header files in those modules that actuall
y need to access an item in another module, the operation of powerful make u
tilities such as Polymake or Keil's own AMAKE, is improved; provided the dep
endency list is kept up to date, any changes to a .h file will cause all mod
ules that reference it to be recompiled automatically. Thus a modified progr
am cannot be built for testing unless all modules referencing the altered it
em successfully re-compile. This usefully relieves the linker from being alo
ne responsible for symbol attribute cross-checking - something which some li
nkers cannot be relied upon to do.
In most embedded C dialects this can be a major help in program development
as, for example, a change in a widely-used function's memory model attribute
can easily be propagated through an entire program; the change in the intel
ligent header file belonging to the function's home module causing the AMAKE
to recompile all other modules referencing it. Likewise, a change in a vari
able's memory space from say XDATA to PDATA needs only one header file to be
edited - AMAKE will do the rest!
Here's how it's done in practice:
/* Module Containing Main Program - MAIN.C */
#define _MAIN_
/* Define module name for include file control */
#include <reg517.h> // Definitions for CPU
#include <v24ini537.h> // External references from V24INI.C #include <t0ini
537.h> // External references from
//T0INI537.C
#include <rlt_int.h>
// External references for RLT_INT.C
void main(void) {
v24ini_537() ;
timer0_init_537() ;
while(1) {
printf("Time = %d.%d",clock.secs,clock.msecs) ;
}
if(P1 | 0x01) {
clock_run_fl = 1 ; // If button pressed start clock
}
else {
clock_run_fl = 0 ; // If button released stop clock
}
if(P1 | 0x02) {
clock_reset_fl = 1 ; // If button pressed clear clock
}
}
/* Module Containing Timer0 Service Routine - RLT_INT.C */
#define _RLT_INT_ /* Identify module name */
/* External References */
extern bit clock_reset_fl // Flag to tell timer0 interrupt to
// reset clock to zero
/*** INTERRUPT SERVICE FOR TIMER 0 ***/
void timer0_int(void) interrupt 1 using 1 {
if(clock.msec++ == 1000) {
clock.sec++ ;
if(clock.sec == 60) {
clock_sec = 0 ;
}
}
}
Taking the include files:
/* Include File For RLT_INT.C */
/* General, non-module specific definitions */
/* such as structure and union templates */
/* Clock Structure Template - Available To All Modules */
struct time { unsigned char secs ;
unsigned char msec ; } ;
#ifdef _RLT_INT_
/* Original declarations - active only in home module */
/* Create XDATA Structure */
struct time xdata clock ;
bit clock_run_fl = 0 ; // Flag to tell timer0 interrupt to stop clock
#else
/* External References - for use by other modules */
extern struct time xdata clock ;
extern bit clock_run_fl = 0 ; // Flag to tell timer0 interrupt to stop cloc
k
#endif
/* Include File For MAIN.C */
#ifdef _MAIN_
/* Local Data Declaration */
bit clock_run_fl = 0 ; // Flag to tell timer0 interrupt to stop clock
#else
/* External References - for other modules */
extern bit clock_run_fl ; // Flag to tell timer0 interrupt to stop clock
#endif
/* Include File For V24INI537.C */
#ifdef _V24INI537_
/* Original Function Prototype - for use in V24INI537.C */
void v24ini_537(void) ;
#else
/* External Reference - for use in other modules */
extern void v24ini_537(void) ;
#endif
Now, should any new global data be added to, for example, RLT_INT.C, adding
the original declaration above the "#endif" and the external version below,
this makes the new item instantly available to any other module that wants i
t.
To summarise, the basic source module format is:
#define _MODULE_
#include <mod1.h>#include <mod2.h?
.
.
.
functions()
The include file format is:
/* General, non-module specific definitions such as structure and union temp
lates */
#ifdef _MODULE_
/* Put original function prototypes and global data declarations here */
#else
/* Put external references to items in above section here */
#endif
Standard Module Layouts For C51
To help integrate this program construction method, the following standard s
ource and header modules shown overleaf may be used.
Standard Source Module Template
#define __STD__
/* Define home module name */
***********************************************************/
***********************************************************/
/* Project: X */
/* Author: X Creation Date: XX\XX\XX */
/* Filename: X Language: X */
/* Rights: X Rights: X */
/* */
/* Compiler: X Assembler: X */
/* Version: X.XX Version: X.XX */
/**********************************************************/
/* Module Details: */
/**********************************************************/
/* Purpose: */
/* */
/* */
/**********************************************************/
/* Modification History */
/**********************************************************/
/* Name: X Date: XX\XX\XX */
/* Modification: X */
/* */
/* Name: X Date: XX\XX\XX */
/* Modification: X */
/* */
/* Name: X Date: XX\XX\XX */
/* Modification: X */
/* */
/**********************************************************/
/**********************************************************/
/* External Function Prototypes */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -