📄 chapter 1 program structure -- valvano.htm
字号:
href="http://www.ece.utexas.edu/~valvano/embed/app1/app1.htm#CPPCOMMENT">compiler
option dialog</A>). The start comment sequence is <CODE>// </CODE>and the
comment ends at the next line break or end of file. Thus, the following two
lines are equivalent:</P>
<DIR>
<P><CODE>OpenSCI(); /* turn on SCI serial port */<BR>OpenSCI(); // turn on SCI
serial port</CODE></P></DIR>
<P>C does allow the comment start and stop sequences within character constants
and string constants. For example the following string contains all 7
characters, not just the <FONT face=Monaco>ac</FONT>:</P>
<DIR>
<P><CODE>str="a/*b*/c";</CODE></P></DIR>
<P>ICC11 and ICC12 unfortunately do not support comment nesting. This makes it
difficult to comment out sections of logic that are themselves commented. For
example, the following attempt to comment-out the call to <CODE>OpenSCI</CODE>
will result in a compiler error.</P>
<DIR>
<P><CODE>void main(void){ unsigned char
Info;<BR>/*<BR> OpenSCI(); /* turn on
SCI serial port
*/<BR>*/<BR> DDRC=0x00; /* specify Port
C as input
*/<BR> while(1){<BR> Info=PORTC; /*
input 8 bits from parallel port C
*/<BR> OutSCI(Info);}} /* output 8 bits
to serial port */</CODE></P></DIR>
<P>The<A
href="http://www.ece.utexas.edu/~valvano/embed/chap11/chap11.htm#CONDITION">
conditional compilation</A> feature can be used to temporarily remove and
restore blocks of code.</P>
<P><B><I><FONT face=Helvetica,Arial><A name=PREPROCESSOR></A>Preprocessor
Directives</FONT></I></B></P>
<P>Preprocessor directives begin with <CODE># </CODE>in the first column. As the
name implies preprocessor commands are processed first. I.e., the compiler
passes through the program handling the preprocessor directives. Although there
are many possibilities (assembly language, conditional compilation, interrupt
service routines), I thought I'd mention the two most important ones early in
this document. We have already seen the macro definition (<B>#define</B>) used
to define I/O ports and bit fields. A second important directive is the
<CODE>#include</CODE>, which allows you to include another entire file at that
position within the program. The following directive will define all the 6811
I/O port names. </P>
<DIR>
<P><CODE>#include "HC11.h"</CODE></P></DIR>
<P>Examples of <CODE>#include</CODE> are shown <A
href="http://www.ece.utexas.edu/~valvano/embed/chap1/chap1.htm#SOURCE">below</A>,
and more in <A
href="http://www.ece.utexas.edu/~valvano/embed/chap11/chap11.htm#INCLUDE">Chapter
11</A>.</P>
<P><B><I><FONT face=Helvetica,Arial><A name=GLOBAL></A>Global
Declarations</FONT></I></B></P>
<P>An object may be a data structure or a function. Objects that are not defined
within functions are global. Objects that may be declared in ICC11/ICC12/Hiware
include:</P>
<DIR>
<P>integer variables (16 bit signed or unsigned) <B><FONT
face=Monaco><BR></FONT></B>character variables (8 bit signed or
unsigned)<B><FONT face=Monaco><BR></FONT></B>arrays of integers or characters
<B><FONT face=Monaco><BR></FONT></B>pointers to integers or characters <B><FONT
face=Monaco><BR></FONT></B>arrays of pointers<B><FONT
face=Monaco><BR></FONT></B>structure (grouping of other objects)<B><FONT
face=Monaco><BR></FONT></B>unions (redefinitions of storage)<B><FONT
face=Monaco><BR></FONT></B>functions </P></DIR>
<P>Both Hiware and ICC12 support 32 bit long integers and floating point. In
this document we will focus on 8 and 16 bit objects. Oddly the object code
generated with the these compilers is often more efficient using 16 bit
parameters rather than 8 bit ones.</P>
<P><B><I><FONT face=Helvetica,Arial><A name=DECLARATIONS></A>Declarations and
Definitions</FONT></I></B></P>
<P>It is important for the C programmer two distinguish the two terms
<I>declaration</I> and <I>definition</I>. A function declaration specifies its
name, its input parameters and its output parameter. Another name for a function
declaration is <I>prototype</I>. A data structure declaration specifies its type
and format. On the other hand, a function definition specifies the exact
sequence of operations to execute when it is called. A function definition will
generate object code (machine instructions to be loaded into memory that perform
the intended operations). A data structure definition will reserve space in
memory for it. The confusing part is that the definition will repeat the
declaration specifications. We can declare something without defining it, but we
cannot define it without declaring it. For example the declaration for the
function <CODE>OutSCI</CODE><FONT face=Monaco> </FONT>could be written as</P>
<DIR>
<P><CODE>void OutSCI(unsigned char);</CODE></P></DIR>
<P>We can see that the declaration shows us how to use the function, not how the
function works. Because the C compilation is a one-pass process, an object must
be declared or defined before it can be used in a statement. (Actually the
preprocess performs a pass through the program that handles the preprocessor
directives.) Notice that the function <CODE>OutSCI</CODE><FONT face=Monaco>
</FONT>was defined before it was used in the above <A
href="http://www.ece.utexas.edu/~valvano/embed/chap1/chap1.htm#LISTING">listing</A>.
The following alternative approach first declares the functions, uses them, and
lastly defines the functions:</P>
<DIR>
<P><CODE>/* Translates parallel input data to serial outputs */<BR>#define PORTC
*(unsigned char volatile *)(0x1003)<BR>#define DDRC *(unsigned char volatile
*)(0x1007)<BR>#define BAUD *(unsigned char volatile *)(0x102B)<BR>#define SCCR2
*(unsigned char volatile *)(0x102D)<BR>#define SCSR *(unsigned char volatile
*)(0x102E)<BR>#define SCDR *(unsigned char volatile *)(0x102F)<BR>void
OpenSCI(void);<BR>void OutSCI(unsigned char);<BR>void main(void){ unsigned char
Info;<BR> OpenSCI(); /* turn on SCI serial port
*/<BR> DDRC=0x00; /* specify Port C as input
*/<BR> while(1){<BR> Info=PORTC;
/* input 8 bits from parallel port C
*/<BR> OutSCI(Info);}} /* output 8 bits to serial
port */<BR>void OpenSCI(void) { <BR> BAUD=0x30; /* 9600 baud
*/<BR> SCCR2=0x0C;} /* enable SCI, no interrupts */<BR>/* Data
is 8 bit value to send out serial port */<BR>#define TDRE 0x80<BR>void
OutSCI(unsigned char Data){<BR> while ((SCSR & TDRE) == 0); /*
Wait for TDRE to be set */ <BR> SCDR=Data; } /* then output
*/</CODE></P></DIR>
<P><I>Listing 1-7: Alternate ICC11 Program</I></P>
<P>An object may be said to exist in the file in which it is defined, since
compiling the file yields a module containing the object. On the other hand, an
object may be declared within a file in which it does not exist. Declarations of
data structures are preceded by the keyword <B>extern</B>. Thus,</P>
<DIR>
<P><CODE>short RunFlag;</CODE></P></DIR>
<P>defines a 16 bit signed integer called <CODE>RunFlag</CODE>; whereas,</P>
<DIR>
<P><CODE>extern short RunFlag;</CODE></P></DIR>
<P>only declares the <CODE><B>RunFlag</B> </CODE>to exist in another, separately
compiled, module. We will use external function declarations in the ICC11/ICC12
VECTOR.C file when we create the reset/interrupt vector table. Thus the line</P>
<DIR>
<P><CODE>extern void TOFhandler();</CODE></P></DIR>
<P>declares the function name and type just like a regular function declaration.
The <B>extern</B><FONT face=Monaco> </FONT>tells the compiler that the actual
function exists in another module and the linker will combine the modules so
that the proper action occurs at run time. The compiler knows everything about
extern objects except where they are. The linker is responsible for resolving
that discrepancy. The compiler simply tells the assembler that the objects are
in fact external. And the assembler, in turn, makes this known to the
linker.</P>
<P><B><I><FONT face=Helvetica,Arial><A
name=FUNCTIONS></A>Functions</FONT></I></B></P>
<P>A <I>function</I> is a sequence of operations that can be invoked from other
places within the software. We can pass 0 or more parameters into a function.
The code generated by the ICC11 and ICC12 compilers pass the first input
parameter in Register D and the remaining parameters are passed on the stack. A
function can have 0 or 1 output parameter. The code generated by the ICC11 and
ICC12 compilers pass the return parameter in Register D (8 bit return parameters
are promoted to 16 bits.) The <CODE>add</CODE> function below has two 16 bit
signed input parameters, and one 16 bit output parameter. Again the numbers in
the first column are not part of the software, but added to simplify our
discussion.</P>
<DIR>
<P><CODE>1 short add(short x, short y){ short z;<BR>2
z=x+y; <BR>3
if((x>0)&&(y>0)&&(z<0))z=32767;
<BR>4
if((x<0)&&(y<0)&&(z>0))z=-32768;
<BR>5 return(z);} <BR>6 void main(void){
short a,b;<BR>7 a=add(2000,2000)<BR>8
b=0<BR>9 while(1){<BR>10
b=add(b,1);<BR>11
}</CODE></P></DIR>
<P><I>Listing 1-8: Example of a function call</I></P>
<P>The interesting part is that after the operations within the function are
performed control returns to the place right after where the function was
called. In C, execution begins with the <B>main</B> program. The execution
sequence is shown below:</P>
<DIR>
<P><CODE>6 void main(void){ short a,b;<BR>7
a=add(2000,2000); /*
call to add*/<BR>1 short add(short x, short y){ short z;<BR>2
z=x+y;
/*
z=4000*/<BR>3
if((x>0)&&(y>0)&&(z<0))z=32767;
<BR>4
if((x<0)&&(y<0)&&(z>0))z=-32768;
<BR>5 return(z);}
/*
return 4000 from call*/<BR>8 b=0<BR>9
while(1){<BR>10
b=add(b,1);
} /* call
to add*/<BR>1 short add(short x, short y){ short z;<BR>2
z=x+y;
/*
z=1*/<BR>3
if((x>0)&&(y>0)&&(z<0))z=32767;
<BR>4
if((x<0)&&(y<0)&&(z>0))z=-32768;
<BR>5 return(z);}
/*
return 1 from call*/<BR>11 }<BR>9
while(1){<BR>10
b=add(b,1);
} /* call
to add*/<BR>1 short add(short x, short y){ short z;<BR>2
z=x+y;
/*
z=2*/<BR>3
if((x>0)&&(y>0)&&(z<0))z=32767;
<BR>4
if((x<0)&&(y<0)&&(z>0))z=-32768;
<BR>5 return(z);}
/*
return 2 from call*/<BR>11 }</CODE></P></DIR>
<P>Notice that the return from the first call goes to line 8, while all the
other returns go to line 11. The execution sequence repeats lines
9,10,1,2,3,4,5,11 indefinitely.</P>
<P>The programming language Pascal distinguishes between functions and
procedures. In Pascal a function returns a parameter while a procedure does not.
C eliminates the distinction by accepting a bare or <CODE>void</CODE> expression
as its return parameter. </P>
<P>C does not allow for the nesting of procedural declarations. In other words
you can not define a function within another function. In particular all
function declarations must occur at the global level. </P>
<P>A function declaration consists of two parts: a <I>declarator</I> and a
<I>body</I>. The declarator states the name of the function and the names of
arguments passed to it. The names of the argument are only used inside the
function. In the add function above, the declarator is <B>(short x, short y)</B>
meaning it has two 16 bit input parameters. ICC11 and ICC12 accept both
approaches for defining the input parameter list. The following three statements
are equivalent:</P>
<DIR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -