⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter5.htm

📁 嵌入式软件开发.rar
💻 HTM
📖 第 1 页 / 共 5 页
字号:
        return this;
    }
</code></pre><p>
	The delay destructor is a little different from most destructors seen so far in this 
discussion.  Of course, the memory allocated to the delay must be released back to the 
system by execution of the free(this) function.  Also, semaphore attached to the delay 
object must be released so that the calling function will be able to proceed.  Finally, since 
this delay will no longer exist after execution of the destructor, it is important to remove 
its presence from the timer object to which it was attached.  The two calls 
attach_method(this->Time,NULL) and attach_object(this->Time,NULL) replace the data 
stored in hook_object and hook_method within the timer object with NULL which is a 
pointer to a nonexistant memory location.  When the timer interrupt service routine is 
executed, the value of hook_method is tested and there is no attempt to execute this 
function if it contains a NULL.
<pre><code>
    void delay__(Delay *this)
    {
        release_semaphore(this->semaphore); /* Release the semaphore */
        attach_method(this->Time,NULL);     /* release timer */
        attach_object(this->Time,NULL);
        free(this);
    }
</code></pre><p>
	We will next demonstrate the use of the delay class in a very simple program.  
This program will start execution, delay operation for 10 seconds and quit.  It will run on 
an <a href="appendxb.htm#hc16y1_h">M68HC16Y1</a> chip.  This chip has a general purpose timer so the timer class that we 
wrote earlier can be executed.  We include the standard header files which include 
hc16y1.h and scim.h, which are chip related headers along with the delay.h, the 
semaphor.h, the timer.h and the delay.h headers which are class header files.  
<p>	The next two lines of code define TIMECOUNT as 4000 and DELAY_TIME as 
10000.  TIMECOUNT is the number of timer clock cycles that will be executed prior to 
each timer interrupt.  DELAY_TIME is the number of interrupts that will occur during 
the total delay.  One millisecond requires 4000 timer clock cycles.   Therefore, there will 
be a timer interrupt each millisecond.  The delay time of 10000 interrupts will expire in 
10 seconds.  
<pre><code>
    #include "hc16y1.h"
    #include "semaphor.h"
    #include "timer.h"
    #include "delay.h"
    #include "scim.h"
    #include "defines.h"

    #define TIMECOUNT 4000
    #define DELAY_TIME 10000
</code></pre><p>
	When running a timer, we must control the basic clock frequency of the system if 
the timing is to be accurate.  This control is through the Clock Synchronization Register 
which is a part of the SCIM--Single Chip Integration Module.  The 
<a href="appendxb.htm#syncr">SYNCR</a> controls the 
operation of a frequency synthesizer.  This synthesizer locks a high frequency oscillator 
to the phase of a low frequency crystal oscillator and allows the programmer or hardware 
engineer wide flexibility in choice of a system frequency.  The 
<a href="appendxb.htm#syncr">SYNCR</a> register is shown 
below.  The important bit fields in this register are the 
<a href="appendxb.htm#syncrbits">W, X, and Y</a> fields.  Depending 
upon the crystal frequency, there are two equations that can be used to calculate the 
system frequency.  When the crystal frequency, or the reference frequency, is between 25 
and 50 kilohertz, the following equation is used to determine the system frequency.
<pre><code>
	FSYSTEM  =  FREFERENCE ( 4 ( Y+1 )( 2 2W+X ))
</code></pre><p>
where W, X and Y are the values contained in the corresponding bit fields.  The most 
common crystal used in this frequency range is a watch crystal which runs at 32768 Hz.  
The default condition of these bit fields, after reset, are shown in the register description 
below.  Note both W and X contain a  value 0 and Y contains a value 63.  Therefore, if 
the crystal frequency is 32768, the system frequency will be 32768*256 or  8388608.  If 
the operation requires a frequency near 16 mHz, this value must be doubled.  It can be 
doubled easily by placing a value of 1 in the X bit field of the SYNCR.  This setup will 
cause the system frequency to be 16.777216 mHz.  
<p>	Alternatively, it is possible to use a higher frequency crystal.  In this case, the 
equation to determine the system frequency is given by 
<pre><code>
    FSYSTEM =  ( 4 ( Y+1 )( 2 2W+X ))FREFERENCE /128
</code></pre><p>
This equation holds for reference frequencies between 3.2 and 6.4 mHz.  You can think 
of the operation as being the same with either range of frequencies with the higher 
frequency being divided by 128 prior to the adjustment by the frequency synthesizer.  
The hardware automatically determines the when the division by 128 is needed.  The 
development board used to test programs for this book is the MC68HC16Y1MPB.  This 
board uses a 4.00 mHz crystal oscillator.  Therefore, if the value of the X bit is set to 1, 
the system frequency should be 16.00 mHz.  
<p>	Also, the default timer clock prescaler is set to a value of 4.  Thus, the input to the 
GPT should be running at a frequency of 4.00 mHz when the reference frequency is 4.00 
mHz, the X bit of the SYNCR register is set to 1, and the Y field in this register has its 
default value.
<p>	There are two popular development boards that you will find for the M68HC16 
family of components.  The one mentioned above supports the larger HC16Y1 chip.  
Alternatively, the MC68HC16Z1EVB supports the HC16Z1 chip.  This chip has different 
on-board peripheral components.  The board itself has a 32768 Hz crystal to provide the 
reference frequency for the chip.  In that case, with the same set-up discussed above, the 
input to the GPT will be 4.194304 mHz rather than 4.00 mHz.  This difference in system 
frequency will cause significant differences in any delay or clock operation that you 
might program into the part.

<p><img align=middle src="fig5-1.jpg">
<p>	The main program here is relatively simple once the various classes are properly 
created.  The first three instructions define pointers to a Timer, a Semaphore, and a Delay 
object.  A timer parameter block is also created.  The <a href="appendxb.htm#scim_h">SIM</a>--System Integration Module--
registers are set-up.  The clock speed is set to 16.00 mHz, the watch dog is disabled and 
the built-in wait state generator for the boot memory chip select is set to 0 wait states.  
The system interrupts are then enabled.
	The timer parameter block is properly filled.  I arbitrarily chose the output 
compare number 3 to be the timer for this system.  The tick count is set to provide 1 ms 
interrupts.  There is no external action when these interrupts occur.  Also, OC1 is not 
being used with this program.  We will need an interrupt to occur.  These appropriate 
values are placed in the timer parameter block, and a pointer to this block is sent to the 
timer constructor.
	The program then gets an instance of a semaphore and creates an instance of the 
delay component.  The delay constructor receives pointers to the timer, the semaphore 
and the delay time as arguments.  The operation of this program returns the value from 
delay_(), but the semaphore is attached to delay.  Therefore, the wait_for_semaphore() 
call will lock up the operation of the program until the semaphore is released by the 
object d.  When the semaphore is released by delay, it is destroyed, and the timer object 
is also destroyed.  Recall that it is not necessary to destroy the delay because the exercise 
program contained within the delay takes care of this little piece of business. 
<pre><code>
    #include "hc16y1.h"
    #include "semaphor.h"
    #include "timer.h"
    #include "delay.h"
    #include "scim.h"
    #include "defines.h"

    #define TIMECOUNT 4000
    #define DELAY_TIME 10000


    main()
    {
        Timer *t;
        Semaphore *sem;
        Delay *d;
        Timer_parameters tp;
     
        /* initialize the SIM registers */
        /* set the clock to 16.00 mHz, disable the watchdog, and 0 		  
        wait state */
        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 */              
        cli();          /* enable the system interrupts */
       
        tp.number=3;    /* set up the timer parameter structure */
        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 */
        t=timer_(&tp);	  
        sem=semaphore_();   /* make the semaphore */
        d=delay_(t,sem,DELAY_TIME);
        wait_for_semaphore(sem);
        semaphore__(sem);
        timer__(t);
    }
</code></pre>
<h4><pre>
    	Listing 5.4 Delay Test Program
</pre></h4>
<p>	The above program demonstrates the operation of the timer, the semaphore, and 
the delay objects.  Shown below is a series of programs.  These programs will show the 
operation of a timer component in a slightly more complicated operation.  The program 
is written is three phases.  These phases, clock, clock1 and clock2, first build a simple 
time of day clock.  There is only one piece of business processed with each timer 
interrupt.  The time output is sent out of the computer through the serial port.  There is no 
provision that allows setting the clock from the external system.  In other words, the only 
way that the clock can be set to a specific time is to modify the time values in memory 
with a debug system.  We will start with this simple system and later add more features 
that will make our clock more useful.

<h3><a name="clock">Clock</a></h3>

<p>	The routine clock is a simple clock that cannot do much more than tell time.  In 
clock2, this routine is expanded to allow two distinct operations to be executed during 
the interrupt service routine of the timer.  These two operations are contained on a linked 
list, and if more items were needed, the linked list could be extended.  Finally, in clock3, 
it is shown how to add the capability of setting the clock through the keyboard.  
<p>	The header files for the program are listed below.  The first four header files has 
to do with the chip.  The <a href="appendxb.htm#hc16y1_h">M68HC16Y1</a>
 chip contains, among other modules, the general 
purpose timer, <a href="appendxb.htm#gpt_h">GPT</a>,
 the multichannel communications interface, <a href="appendxb.htm#mcci_h">MCCI</a>, and the single 
chip integration module, <a href="appendxb.htm#scim_h">SCIM</a>.  These headers are each included.  We will also make 
use of the serial input/output object along with the timer object.  These headers are also 
included along with the usual defines.h header.  
<pre><code>
    #include "HC16Y1.H"
    #include "gpt.h"
    #include "mcci.h"
    #include "scim.h" 
    #include "serio.h"
    #include "timer.h"
    #include "defines.h"
</code></pre><p>
	Next follows a series of definitions needed by the program.  You will remember 
that the hardware parameters for the serial i/o operation are all determined by the 
program.  These same parameters were locked into specific values in the timer object.  
There is no correct or incorrect approach to where the system parameters are delivered to 
the program.   The parameters must be provided.  In the case of the timer class, the 
programmer has no choice as to the location of the interrupt vector, the IARB and the 
interrupt level.  These parameters are established within the class definition.  In the case 
of the serial i/o class, the interrupt parameters along with the serial i/o baud rate must be 
passed to the class as arguments to the class constructor.  The set of defines that establish 
these values are shown below.  Remember, it is always better to use a series of defines or 
an enumerate statement to create these values for the program rather than to use the 
actual numbers within the function calls.  Such numbers used as function arguments and 
so forth, are called magic numbers.  When inserted as numbers, there is no connection to 
their real meaning.  When defined, all numbers are inserted into the program as 
mnemonics with some program meaning.  
<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
</code></pre><p>
	The next program items are the function prototypes.  There are only four 
functions used for this program.  The first count_ticks() is a simple function that merely 
increments the content of the address passed to the function as a parameter.  This 
function is quite important because it is the another example of use of the do_hook 
approach that we use to add a function to the interrupt service routine of an instance of 
the timer class.  The remaining three functions are used to convert the integer type data 
stored in memory into an character form that can be sent to the serial port.  This function 
is convert_itoa().  build_time() creates a complete message to be sent to the serial port 
and uses convert_itoa() and output_time() sends the message to the serial port.  
<pre><code>
    /* function prototypes */

    void count_ticks(WORD *);
    void output_time(void);
    void build_time(void);
    void convert_itoa(WORD a,BYTE *p);
</code></pre><p>

	Next to follow in the program are the variable definition statements.  The first is a 
string variable in which the message to be sent to the serial port is placed.  This string is 
followed by parameter blocks, and pointers to objects needed for the program.  Also, the 
variables hours, minutes, seconds, and count are defined as external variables to the 
program.
<pre><code>					           
    BYTE pszMessage[]="         \r"; /* a place to store the time */
    io_command_block *oob1,ob1;      /* i/o command block */
    Timer_parameters tp;             /* timer parameter block */
    WORD hours, minutes, seconds;
    WORD count;
    Serial_io *sio;              
    Timer *t3;
</code></pre><p>

	The main() function starts with the usual initialization routines.  The <a href="appendxb.htm#scim_h">SIM</a> is 
initialized to give a 16.00 mHz  system clock frequency, the watchdog is disabled and the 
memory wait states associated with the boot chip select are set to zero.  Any other 
initialization needed within the <a href="appendxb.htm#scim_h">SIM</a> will use the default, reset value, values.  
<p>	The serial input/output is then set-up.  The object sio is a pointer to a type 
Serial_io.  This pointer is given a value by the call to the serial_io_() constructor.  Note 
that the arguments passed to this constructor are all defined earlier, so that anybody who 
is reading the program should be able to understand which argument is given the specific 
value.  It is not really important to the program at this point the values assigned to these 
parameters.  However, if it is necessary at some time later to change any of these values, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -