📄 chapter5.htm
字号:
they should be changed within the #define statements shown earlier.
<p> The input-output control block pointer is given a value, and the parameters
call_complete and io_command are initialized. This component is used as an output only
so the command should never change during the program.
<p> An instance of a timer is needed with this program. The timer parameter block is
filled with the appropriate values. Timer number 3 is used, the tick value of
TIMECOUNT will provide 1 ms interrupts. There is no output compare 1 connection or
action with this timer object, and we will need an interrupt. The timer is then
instantiated as t3. We will then attach a pointer to the function count_ticks() to the
hook_method and a pointer to the memory location count to the hook_object in the
instance of the timer t3.
<p> In a final bit of initialization, the value of count is set to zero, and the system
interrupts are enabled. After this initialization, the system should be operating properly
with all interrupts enabled and occurring when called for.
<pre><code>
main()
{
/* initialize the program */
/* initialize the SIM registers */
SYNCR.X=ON; /* double the clock speed--16.00 mHz */
SYPCR.SWE=OFF; /* disable the watchdog */
CSORBT.DSACK=0; /* use zero wait states for now */
/* set up the serial communications */
sio=serial_io_(SERIO_BAUD_19200, /* set the baud rate */
SERIO_INT_VECTOR, /* interrupt vector */
SERIO_IARB, /* iarb */
SERIO_INT_LEVEL); /* and interrupt level */
/* set up the io block */
oob1=&ob1;
oob1->call_complete=TRUE; /* start with no message in progress */
oob1->io_command=OUTPUT; /* make this block for outputs */
/* set up the timer parameter structure */
tp.number=3; /* use output compare number 3 */
tp.tick=TIMECOUNT; /* 1 ms interrupts */
tp.action=0; /* no output action */
tp.OC1_connect=0; /* OC1 not connected to another OC */
tp.connect_data=0;
tp.interrupt=YES; /* need an interrupt here */
t3=timer_(&tp); /* instantiate the timer */
attach_object(t3,&count); /* attach object and method to timer*/
attach_method(t3,count_ticks);
/* initialize application program details */
count=0;
cli(); /* enable the system interrupts */
</code></pre><p>
The next program section is usually called the applications section. It is in this
section that all continuing business that must be executed by the program is processed.
In this case, the applications section is relatively simple. Note that, as usual, the
applications section is comprised of a code loop that executes FOREVER. That is not to
say that the code never exits this loop, but rather the loop is executed and interrupts will
remove control to the interrupt service routines within the program. When ever there is
no interrupt service being handled, control will be returned to the FOREVER loop.
<p> The code within the loop in this case will maintain a time-of-day clock.
Whenever the value stored in count exceeds or equals the value ONE_SECOND, count is
reset to zero and seconds is incremented. If the incremented value of seconds is greater
than or equal to 60, seconds is reset to zero and minutes is incremented. And so forth, for
the minutes and the hours. You will note that hours, minutes, seconds, and count are
each of the type WORD which is an unsigned integer. Therefore, these parameters can
never have a negative value. Also the test to determine the value in each case is greater
than or equal to. We should expect that these values will never exceed the test values
shown. However if any should by some accident, the greater than or equal along with the
use of the unsigned variable type will guarantee that the values of these parameters will
be kept within their acceptable ranges of values.
<p>The range of minutes and seconds is from zero to fifty-nine. If the value of either
of these variables is ever found to be sixty, it is reset to zero. The range of hours is from
one to twelve. Note that hours is reset to one whenever its incremented value becomes
thirteen or greater.
<p> Note that the code to keep the time is executed only when the value of count
becomes ONE_SECOND. Also, build_time() and output_time() are executed at this
time. Therefore, a new time will be sent to the serial port once each second.
<pre><code>
/* end of initialization and beginning of the applications
section of the program */
FOREVER
{
if(count>=ONE_SECOND)
{
count=0;
if(++seconds>=60)
{
seconds=0;
if(++minutes>=60)
{
minutes=0;
if(++hours>=13)
hours=1;
}
}
build_time();
output_time();
}
}
}
</code></pre><p>
The next portion of the program is the inclusion of the functions needed for the
applications portion of the program. There are three functions in this case. These
functions are output_time(), build_time(), and convert_itoa(). They are shown below.
Let us examine build_time() first. This function receives no arguments, but it uses the
values stored in the external variables hours, minutes, and seconds. These values are
integer values that must be converted to character values before they can be sent to the
serial port. A pointer to the message area pszMessage and the value of hours is sent to
the function convert_itoa(). This function converts the integer value to two characters
less than 100 and puts these characters in the memory area pointed to by the argument p.
A character ':' is then put into the message area, and the value of minutes is converted to
two characters and placed into the message area. Finally, this sequence is repeated for
the seconds, and the data are then ready to be sent to the serial port.
<p> The data are converted to character form by the function convert_itoa() This
function receives two parameters: first the value to be converted and second a pointer to
the memory area where the result is to be stored. The conversion merely evaluates the
number of tens in the value and adds a character zero to this value. It then evaluates the
number of units in the number and adds a character zero to the number of units. These
characters are put into the proper memory locations as they are calculated.
<p> The final function needed to complete the applications portion of the program is
called output_time(). This function first waits until there is no message being sent out
the serial port. When the serial port is available, new values are placed in the io
command block, and the output message is sent to the serial_io object. This object in
turn sends the message contained in pszMessage[] to the serial port.
<pre><code>
/* functions needed for the applications portion of the program */
/* send out the time message */
void output_time(void)
{
while(!oob1->call_complete)
; /* wait until any other message is out */
oob1->buffer=pszMessage; /* clear out the background */
oob1->buffer_length= sizeof pszMessage;
serial_io(sio,oob1); /* message to the i/o object */
}
/* This routine builds the time message to be sent out. */
void build_time(void)
{
BYTE *p=pszMessage;
convert_itoa(hours,p);
p+=2;
*p++=':';
convert_itoa(minutes,p);
p+=2;
*p++=':';
convert_itoa(seconds,p);
p+=2;
*p++='\r';
*p='\0';
}
/* This routine converts an unsigned integer, a, into an ascii
string of the value and puts the results into the string pointed
to by p. */
void convert_itoa(WORD a,BYTE *p)
{
*p++=(a/10)+'0';
*p=(a%10)+'0';
}
</code></pre><p>
There is only one function left that is needed to complete this program. Recall
that count_ticks() is attached to the hook of the timer object. In this case the hook
method is very simple. All it must do is to increment count and return. In later cases, the
hook method will be somewhat more complicated.
<pre><code>
/* function needed for the interrupt service routine */
/* the timer is interrupted each millisecond.
count_ticks keeps track of the number of
interrupts that have occurred. */
void count_ticks(WORD *a)
{
++*a;
}
</code></pre><p>
Usually when a program is shown in small pieces as was done above, the whole
program is listed immediately following the description. In this case, I plan to expand on
this program significantly in the next two programs. Therefore, the total listing of the
above program will not be included here, nor anywhere, but it will be replaced by a total
listing of one of the following programs. The above program shows the insertion of a
single function into the hook part of the timer object. The program that follows will
expand on that idea a little. In this case, rather than a single function being put into the
timer object, a linked list of several programs will be used. Each timer interrupt will
cause the several functions in the link list to be executed. Again the program will be
broken into small segments for descriptive purposes. The changes in this program are
incremental changes in the above program. Therefore, only the changes will be
examined. The changes will be highlighted so they can be easily seen.
<h3><a name="clock1">Clock1</a></h3>
<p> In this program, we are going to make use of the linked list developed in Chapter
3. Recall that the linked list hooked link objects together into a list. Each link object
contained a pointer to a single object. The linked list class contains a method called
walk_list(). When walk_list() is executed, the object method named exercise() is
executed for each object in the linked list. These capabilities can be used to advantage
when it is needed to have more than one distinct function executed at each timer
interrupt.
<p> The #include files needed for this program are shown in the program segment
below. The new files here are object.h, link.h and linklist.h. The class object differs
from the class object in that it allows the routine exercise to be specified as a parameter
to the constructor that creates the various instances of the type <a href="chapter7.htm#object">Object</a>. We saw
applications of <a href="chapter7.htm#link">link.h</a> and
<a href="chapter7.htm#link_list">linklist.h</a> in Chapter 3.
<pre><code>
#include "HC16Y1.H"
#include "gpt.h"
#include "mcci.h"
#include "scim.h"
#include "serio.h"
#include "timer.h"
#include "defines.h"
<strong>#include "object.h"
#include "link.h"
#include "linklist.h"</strong>
</code></pre><p>
The same #define constants are needed with this program. One additional piece
of business will be added to the program. Here we will have a timer function that will
cause a transaction to take place each half second. We must, therefore, add a value
named ONE_HALF_SECOND to our list of #defined constants as shown below. Also, a
function that is used to determine the occurrence of half second periods is needed. The
function prototype of this function is added to the function prototype list.
<pre><code>
#define SERIO_BAUD_19200 19200
#define SERIO_INT_VECTOR 0x40
#define SERIO_IARB 10
#define SERIO_INT_LEVEL 3
#define TIMECOUNT 4000
#define ONE_SECOND 1000
<strong>#define ONE_HALF_SECOND 500</strong>
/* function prototypes */
void output_time(void);
void build_time(void);
void convert_itoa(WORD a,BYTE *p);
<strong>void count_half_second_ticks(void);</strong>
void count_second_ticks(void);
</code></pre><p>
Some objects of the type <a href="chapter7.htm#object">Object</a>,
<a href="chapter7.htm#link">Link</a> and <a href="chapter7.htm#link_list">Link_list</a>
are needed for this program.
Pointers to variables of these types are defined in the external memory area below. There
will be two Object types that will be placed in the linked list. These objects are
identified as l1 and l2. Also, the linked list must be preloaded with a null object. This
object is called null. These objects are embedded in link objects named lnk1, lnk2 and
lnknull. Finally, they will all be hooked together in a single linked list named list1.
<pre><code>
BYTE pszMessage[]=" \r"; /* array to hold the time */
io_command_block *oob1,ob1;
WORD hours, minutes, seconds;
WORD count_half_seconds,count_seconds;
Boolean second_flag,one_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -