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

📄 chapter5.htm

📁 嵌入式软件开发.rar
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<head>
<title>Timers</title>
</head>
<body>
<h1>Chapter 5   Timers</h1>
<p>	The timer subsystem on the M68HC16Y1 consists of two parts.  The first is the 
General Purpose Timer, <a href="appendxb.htm#gpt_h">GPT</a>, and the second is the Timer Processor Unit, TPU.  This 
chapter is devoted to the use of the GPT.   The GPT has four output compare units, three 
input capture units and one timer that can be programmed as either.  We shall write a 
code module that provides program access to all four input captures and also, code will 
be written that permits input capture system measurement of relative event times.  Input 
capture control code will be written to cover the three independent input capture timer 
subsystems.  The single timer that can be programmed as either an input capture or an 
output compare will not programmed.  It is an easy matter to add this channel to either 
input or output classes depending on the system need.  This addition can be done by 
inheritance.

<h3><a name="output_compare_subsystem">Output Compare Subsystem</a></h3>

<p>	Operation of an output compare timer is simple.  The basic timer has a free-
running counter that is being clocked at some fraction of the system clock frequency.  
This register is called the Timer Counter Register, or the <a href="appendxb.htm#tcnt">TCNT</a> and is used as a time 
base for the entire timer subsystem.  A value is placed in one of several output compare 
registers.  These registers are given the names <a href="appendxb.htm#ocrs">OC1,...OC4</a>.  With only minor exceptions, 
these registers are the same in both function and operation.  When the content of the 
TCNT matches the value in the output compare register, several things can happen 
depending upon the set-up of the system.  An internal flag is set to indicate that the 
output compare has occurred.  This flag can be polled by the program to determine 
whether the output compare event has occurred,  the corresponding output pin can 
change to a programmed state, and if properly enabled, an interrupt can be requested.  All 
of these events happen synchronous with the match of the <a href="appendxb.htm#tcnt">TCNT</a> contents with that of the 
appropriate OCx register.  
<p>	Both the <a href="appendxb.htm#tcnt">TCNT</a> and the OCx registers are sixteen bit registers.  The timer 
subsystem prescaller can cause the <a href="appendxb.htm#tcnt">TCNT</a> to be incremented at any binary division of the 
system clock frequency between 4 and 256.  The default prescaller value is 4.  There is 
only one TCNT, so all clocking functions for the General Purpose Timer subsystem must 
work from the same time base.  
<p>	OC1 has some unique properties.  This subsystem can be coupled to any other 
output compare.  When OC1 occurs in these cases, the coupled OCx pin will go to a 
programmed state.  This type of operation is very convenient for operations like a pulse 
width modulator.  In this case, OC1 will be used to establish the base time period of the 
PWM system, and the coupled output compare will be used to determine the duty factor.  
With this arrangement, output pulses as small as one timer clock cycle can be created.  
<p>	Here is a case where there are several on-board devices that all operate similarly, 
and a class can be created that will allow the programmer to make use of any selected 
output compare subsystem.  This choice is made by making an appropriate constructor 
call.  Remember in Chapter 4, we saw a case where there were several similar peripheral 
components on the microcontroller.  It was there decided that a special class should be 
written for each of the two SCI interfaces rather than attempt to create a single class that 
could create instances of either of the two hardware serial ports.  Here, all of the 
components are set-up by a single class.  The timer class will embody the complete 
output compare system and will demonstrate that a class can provide complete coverage 
and control of a peripheral.

<h3><a name="timer_class">Timer Class</a></h3>

 <p>	What are we going to do with these timers?  I do not know now, and in fact, there 
is no way to know, so an approach must be used that will allow for very flexible 
extension of the basic timer classes.  This flexibility will permit the connection of objects 
instantiated from other classes, or perhaps standard applications code created by the 
programmer.  This flexibility is implemented by the inclusion of two attributes in the 
timer object.  One is a call to an external function and the other is a parameter to be 
passed to this function.  With these external accesses, the actions that can be performed 
by the timer during an interrupt service routine is essentially unlimited.  	
 <p>	Shown below is the header file for the class timer. Six parameters must be passed 
to the timer constructor.  These parameters are all pulled together into a single structure 
type and a pointer to this structure will be passed to the constructor.  The five parameters 
found in the Timer_parameter structure are all that are needed to set-up completely any 
of the four output compare subsystems.  The first value, number, is simply the number of 
the timer and it can have a value between 1 and 4.  The second parameter, tick, is the 
value that is added to the specific output compare register whenever there is an interrupt 
caused by an output compare.  The next parameter determines the output that will occur 
whenever an output compare on OC2 through OC4 happens.  The table below is taken 
from (1) and it summarizes the possible actions that can occur.  The contents of action 
will be given a value of 0 through 3 and the proper bits in the timer registers will be set to 
cause the action shown in the table to occur.
<table>
<th>	OMx-OLx	 <th>	Action taken on compare	<tr><tr>

<td>	  00  <td>			Timer disconnected from output  (Default)<tr>
 <td>	  01		<td>	Toggle OCx line	  <tr>
 <td>	  10	<td>		Clear OCx line to zero <tr>
 <td>	  11	   <td>		Set OCx line to 1 <tr>
</table>  
<p><h4>    Table 5.1 OMx,OLx Bits</h4>
	
<p>	The contents of the above table are collected into an enumeration in the header 
file so that the programmer can use mnemonic descriptions of the output rather than 
trying to remember the meanings of the seveal numbers above.
<p>	Output compare 1 works somewhat differently from the remainder of the output 
compares.  OC1 can be connected to any other output compare, and when OC1 occurs, 
the connected output compare will go to a designated state.  The parameter OC1_connect 
will be give a value of 0 to 4.  If the value is 0, the OC1 is connected to neither an output 
nor another output compare.  If it is 1, OC1 is connected to its own output pin.  
Otherwise, the number is the output compare to which OC1 is connected.  The 
connect_data input will be given a value of ON or OFF which is the state that the 
connected output compare will go to when OC1 occurs.
<p>	The last entry in the type Timer_parameters is a Boolean value named interrupt.  
This parameter can have a value of TRUE or FALSE, or YES or NO as defined in the 
defines.h file.  If the value is YES, an interrupt will be set-up to occur when the proper 
output compare occurs.  Otherwise, there will be no interrupt, and either the program or 
perhaps the external hardware must respond to the occurrence of the output compare.  
<p>	The timer class is derived from the error handler, and it has three attributes: 
who_am_I, ms_tick and a pointer to a type void called a hook_object.  There are two 
class methods. The first is identified as a pointer to hook_method and the second is a 
pointer to an internal function called reset.  The timer class is defined as Timer, and it 
has both a constructor and a destructor. The constructor requires a parameter that is a 
pointer to a type Timer_parameters. 
<p>	There are two methods needed to assign values to hook_object and hook_method.  
These functions are created as macros which are included in the header file.  As such, the 
two assign functions will always be used as inline code rather than function calls.  In 
addition to the usual two functions, the constructor and the destructor, there is needed an 
additional class method.  This method, reset(), will be used to reset a particular timer so 
that the output compare will occur a specified time after the current time.  The reset also 
forces an output event to the outside world, if it is set up to be delivered to the outside, 
when the reset method is executed.  It does not cause the output compare flag to be set or 
an output compare interrupt to occur.
<pre><code>  
	#ifndef TIMER_H
	#define TIMER_H

	#include "defines.h" 
	#include "error.h"

	#ifndef GPT_IARB
		#define GPT_IARB 12    /* iarb value of 12 for the GPT */   
		#define GPT_VBA 5     /* GPT vectors start at 0x50 */
		#define GPT_LEVEL 6   /* use interrupt level 6 */
	#endif

	typedef enum BYTE 
	{
		DISCONNECT,
		TOGGLE,
		CLEAR,
		SET
	}Output;	
	enum output_compares(OC1=1,OC2,OC3,OC4);
	typedef struct
	{
		WORD   number,  
		       tick;    
		Output action;  
	   	BYTE   OC1_connect, 
		       connect_data;						    
		Boolean  interrupt;
	}  Timer_parameters;

	#define TIMER_CLASS \
		  ERROR_HANDLER  \
		  WORD  who_am_I;\    
	        WORD  ms_tick; \
		  void  (*reset)(struct time *); \
	        void  *hook_object;\
	        void  (*hook_method)(void*);
	    
	typedef struct time
	{
	    TIMER_CLASS
	}Timer;

	#ifndef ATTACH
	#define ATTACH
		#define attach_object(a,b) ((a)->hook_object=(b))
		#define attach_method(a,b) ((a)->hook_method=(b))
	#endif

	Timer* timer_(Timer_parameters *);
	void timer__(Timer*);                          
	#endif
</code></pre>
<h4><pre>
	Listing 5.1 Timer Class Definition File
   </pre></h4>
<p>	There are several pieces of business that must be completed whenever the timer 
subsystem is to be used.  The interrupt arbitration level, the vector base address and the 
interrupt level have all been seen before.  It was decided in this case that these values 
would be assigned specific values.   If this approach is not acceptable, it is an easy matter 
to expand the number of parameters passed to the constructor to include these values.  It 
is important to note that these three values must remain the same for each of the different 
timers, so perhaps, it is best to preassign these values and not worry about them any 
further.   There are four interrupt service routines, each named OCxIsr().  There is also a 
static function named do_hook().  The prototypes for these several functions are listed 
next in the file below.
<pre><code>
	#include "hc16y1.h"
	#include "gpt.h"
	#include "timer.h"

	#define GPT_IARB 12	   /* iarb value of 12 for the GPT */	
	#define GPT_VBA 5     /* GPT vectors start at 0x50 */
	#define GPT_LEVEL 6   /* use interrupt level 6 */
	#define OC1_offset 4   /* output compare vector offsets */
	#define OC2_offset 5
	#define OC3_offset 6
	#define OC4_offset 7

	@port void OC1Isr(void);
	@port void OC2Isr(void);
	@port void OC3Isr(void);
	@port void OC4Isr(void);
	static void do_hook(Timer *);
</code></pre><p>
	The reset function is shown below.  Each of the four timers, if instantiated as 
objects, can be reset.  A reset will cause an output compare to occur if an external 
connection between the output compare and its output pin is set-up, or there is a 
connection between OC1 or any other output compare.  Also, a reset will calculate a new 
value that is equal to the current content of the timer counter register plus the object 
specified tick value and place this value in the proper output compare register.  The code 
to implement these operations is shown below.
<pre><code>
	static void reset(Timer *this)
	{
		switch(this->who_am_I)
		{
	        	case 1 : TOC1=TCNT+this->ms_tick; /* restart output 			
								comp count */
			         CFORC.FOC1=ON;   /* and force an output 		
								compare */
			         break;
		      case 2 : TOC2=TCNT+this->ms_tick;
		               CFORC.FOC2=ON;
				   break;
	            case 3 : TOC3=TCNT+this->ms_tick;
				   CFORC.FOC3=ON;
				   break;
	            case 4 : TOC4=TCNT+this->ms_tick;
			         CFORC.FOC4=ON;
				   break;
		}
	}
</code></pre><p>
	The constructor for the output compare subsystem is shown below.  There are 
four pointers to the type Timer defined as external variables.  These variables will hold 
pointers to the four possible instances of timer objects.  They are needed to implement 
the basic interrupt service routines that follow.  The first executable code in the 
constructor is a series of tests that check for appropriate parameter values.  If a parameter 
is found that is out of the acceptable range, a FALSE value is returned to the calling 
program indicating that there has been a program error.  Memory is allocated to hold the 
new object; an error object is instantiated; the error object is copied onto the new timer 
object, and the error object is destroyed.  The preassigned values or IARB, LEVEL and 
VBA are placed in the appropriate registers in the timer subsystem.  Note in the 
preceding listing that copies of hc16y1.h and gpt.h were included.  It is in these files that 
the parameters such as GPT_MCR, IARB, etc. are defined.  The parameters passed as 
arguments to the constructor are next put into the attributes locations.  Here number is 
the number of the output compare and can have a value of 1 through 4.  The value ticks is 
the number that is added to the content of the output compare register with each 
interrupt.  This number sets the basic timing of the timer being instantiated.  If it is 
intended to connect the output of OC1 to another timer, this connection is made, and the 
output action of the connection is put into place at this point in the code. The parameters 
hook_object, a pointer to a type void, and hook_method, a pointer to a void function, are 
each assigned the value of a NULL which is a pointer with a value zero.  These 
parameters will be changed when it is necessary to connect an applications function to 
the timer.  
<pre><code>
	Timer *OC1_T,*OC2_T,*OC3_T,*OC4_T;

	Timer* timer_(Timer_parameters *tp)
	{
	    Timer* this;
	    Error_handler *temp = error_();

⌨️ 快捷键说明

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