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

📄 clock.cpp

📁 a program that generates a pulse-width modulated (PWM)signal.
💻 CPP
字号:
// Functions for handling time keeping for Borland C++ 4.5 and greater --
//    tested on v5.0
//  based control programs.  The timing modes are set by defines:
//      #define TIMEFREE  to use the free-running PC timer
//      #define TIMEINTERNAL to use internal calibrated time
//      #define TIME_NT to use WinNT's internal microsec. timer
//      #define ISR_SCHEDULING to use interrupt based scheduling and/or
//         timing.
//  These are usually defined in time_mod.h
// File:  clock.cpp
// Created 8/2/95 by Jason Jones
// Modified 9/25/95 to allow for more timing modes by DM Auslander
// Modified 8/13/96 to add WinNT timer, DM Auslander

#include <conio.h>
#include "time_mod.hpp"

#ifdef TIME_NT
#include <windows.h>   // To get WinNT timing functions


const double SEC_PER_OV = 3599.597124; //  Freq. at which 32-bit clock overflows
const double CK_FREQQ = 1193180.0;  //  Frequency of PC clock in Hz
static double StartingTime;        //  Time at which clock was started
#endif  //  end of TIME_NT


#ifdef ISR_SCHEDULING
#define USE_TIMER0
#else // ISR_SCHEDULING
#define USE_TIMER0
//#define USE_TIMER2
#endif // ISR_SCHEDULING

static double TotalTime = 0.0;
static double TickRate = TICKRATE;
//  Initialize to DOS default
static unsigned short TimerPreset = 0xFFFF;

#ifdef TIMEFREE
static unsigned short Last=0;   //  Time read in previous call
#endif

void StopControl(char *aMessage);

//-------------------------------------------------------
// Function: SetTickRate
//      Use this to change the tickrate
//      The default value (from the define symbol TICKRATE
//      will be used if this is never called

void SetTickRate(double Rate)
	 {
	 TickRate = Rate;
	 }

double GetTickRate(void)
	{
	return(TickRate);
	}

//-------------------------------------------------------
//  Function: SetupClock
//      Must be called once in order to set the
//  proper mode for the timer used to keep track of time
//      in TIMEFREE mode.  If TIMEFREE is not defined, then
//      this function does not need to be called.  Look in
//      clock.hpp for a more detailed desciption of what is
//      going on here with respect to the clock modes.

void SetupClock(double aPeriod)
	 {
	 #ifdef TIMEFREE
	 unsigned char  msb, lsb; //  Hold bytes from hardware
	 #endif // TIMEFREE
	 TotalTime = 0.0;    // Initialize running time
		  // Usual units are milliseconds
	 //  For free-running timer, set up the timer hardware
	 #ifdef TIMEFREE
	 #ifndef ISR_SCHEDULING
	 // For Timer0, there is no reason to use anything other than
	 //  the maximum clock period if we are not using interrupts
	 aPeriod = -1.0;
	 #endif // ISR_SCHEDULING
	 #ifdef USE_TIMER2
	 // For Timer2, there is no reason to use anything other than
	 //  the maximum clock period, so forget about the arguement
	 TimerPreset = 0xFFFF;
	 //  Set mode 0 and binary counter for timer 0 and signal
	 //	read/load cycle to start
	 DisableInterrupt ();
	 outp (TIMER_CTL, 0xB0);
	 //  Send LSB then MSB of counter value...
	 //  0xFFFF sets the 8253 to the maximum rollover of
	 //  65535 counts.  This corresponds to 54.9 ms
	 outp (TIMER0, 0xFF);
	 outp (TIMER0, 0xFF);
	 //  Enable counting by bringing gate to timer2 high
	 //  (on 8253 chip)
	 // turns off speaker ?
	 outp (0x61, inp (0x61) | 0x01);
	 // Measure current time to set 'Last' value
	 //  Latch current timer value
	 outp (TIMER_CTL, 0x84);
	 //  Read LSB of word in timer first
	 lsb = (unsigned char) inp (TIMER2);
	 //  and then MSB
	 msb = (unsigned char) inp (TIMER2);
	 #endif // USE_TIMER2
	 #ifdef USE_TIMER0
	 //  If argument's a valid time
	 if ((aPeriod > 0.0) && (aPeriod < (MAX_PER)))
		  {
		  //  calculate rate divisor
		  TimerPreset = (unsigned)((CK_FREQ * aPeriod) + 0.5);
		  //  Set mode 2 and binary counter for timer 0 and signal
		  //	read/load cycle to start
		  DisableInterrupt ();
		  outp (TIMER_CTL, 0x34);
		  //  Send LSB then MSB of counter value...
		  //  0xFFFF sets the 8253 to the maximum rollover of
		  //  65535 counts.  This corresponds to 54.9 ms
		  outp (TIMER0, (int)(TimerPreset & 0xFF));
		  outp (TIMER0, (int)((TimerPreset >> 8) & 0xFF));
		  }
	 else
		  {
		  TimerPreset = 0xFFFF;
		  //  Reset period an mode to supposed DOS default
		  //  Set mode 2 and binary counter for timer 0 and signal
		  //	read/load cycle to start
		  DisableInterrupt ();
		  outp (TIMER_CTL, 0x34);
		  //  Send LSB then MSB of counter value...
		  //  0xFFFF sets the 8253 to the maximum rollover of
		  //  65535 counts.  This corresponds to 54.9 ms
		  outp (TIMER0, 0xFF);
		  outp (TIMER0, 0xFF);
		  }
	 //  Latch current timer value
	 outp (TIMER_CTL, 0x04);
	 //  Read LSB of word in timer first
	 lsb = (unsigned char) inp (TIMER0);
	 //  and then MSB
	 msb = (unsigned char) inp (TIMER0);
	 #endif // USE_TIMER0
	 EnableInterrupt ();
	 //  Concatenate bytes together
	 Last = (short)lsb | ((short)msb  << 8);
	 #endif // TIMEFREE

    #ifdef TIME_NT  // To use the Win-NT timer
    unsigned long Ticks[2];    //  Holds large integers with tick count

    QueryPerformanceCounter ((LARGE_INTEGER *)Ticks);
    StartingTime = ((double)Ticks[1] * SEC_PER_OV) + ((double)Ticks[0] / CK_FREQQ);
    #endif  // End of Win-NT timer setup
	 }

//-------------------------------------------------------
//  Function: GetTimeNow
//      This function returns the current time as kept by
//      the 'real-time' clock (TIMEFREE mode) or the current
//      time as incremented by the user program (not TIMFREE
//      mode)

double GetTimeNow (void)
	 {
	 #ifdef TIMEFREE
	 unsigned short Current=0;//  Current ticks in 8253 chip
	 unsigned char  msb, lsb; //  Hold bytes from hardware
	 unsigned short Delta;    //  Time change since last read

	 //  Prevent interrupt while reading
	 DisableInterrupt();
	 #ifdef USE_TIMER2
	 //  Latch current timer value
	 outp (TIMER_CTL, 0x84);
	 //  Read LSB of word in timer first
	 lsb = (unsigned char) inp (TIMER2);
	 //  and then MSB
	 msb = (unsigned char) inp (TIMER2);
	 //  Concatenate bytes together
	 Current = (short)lsb | ((short)msb  << 8);
	 //  Calculate ticks since last read
	 Delta = Last - Current;
	 #endif // USE_TIMER2
	 #ifdef USE_TIMER0
	 //  Latch current timer value
	 outp (TIMER_CTL, 0x04);
	 //  Read LSB of word in timer first
	 lsb = (unsigned char) inp (TIMER0);
	 //  and then MSB
	 msb = (unsigned char) inp (TIMER0);
	 //  Concatenate bytes together
	 Current = (short)lsb | ((short)msb  << 8);
	 //  Calculate ticks since last read
	 if(Current < Last)
		{
		Delta = Last - Current;
		}
	 // In case of overflow, make correction.  No data has been
	 //  lost, however, if there is only one overflow.
	 else Delta = (TimerPreset - Current) + Last;
	 #endif // USE_TIMER0
	 //  Save current count for later
	 Last = Current;
	 //  Calculate and save the time from the number of
	 //  ticks since last measurement
	 TotalTime += ((double)Delta) / (double)CK_FREQ;

	 EnableInterrupt();  //  Done reading hardware, reEnableInterrupt interrupts
	 #ifndef ISR_SCHEDULING
	 //  If the number of ticks is greater than DELTA_LIMIT,
	 //  consider this an over-flow.  This is a statistical
	 //  error, since an overflow of certain values will not
	 //  be detected.  The max value can be changed if desired.
	 if (Delta > DELTA_LIMIT)
		  {
		  StopControl("Error: Free-running timer not read every 30ms\n");
		  return(-1.0);
		  }
	 #endif // ISR_SCHEDULING

	 return (TotalTime);
	 #endif  // TIMEFREE

	 #ifdef TIMEINTERNAL
	 return (TotalTime);
	 #endif

    #ifdef TIME_NT  // Compute time using the NT microsec timer
    unsigned long Ticks[2];  //  Holds large integers with tick count

    QueryPerformanceCounter ((LARGE_INTEGER *)Ticks);
    TotalTime = ((double)Ticks[1] * SEC_PER_OV) +
        ((double)Ticks[0] / CK_FREQQ) - StartingTime;
    return(TotalTime);
    #endif  // end of TIME_NT section

	 }

//-------------------------------------------------------
//  Function: IncrementTime
//      This function increments the "TotalTime".  It is for
//      cases where TIMEFREE is not defined.  If this function
//      is never called, time will change.  The function should
//      be called periodically, either in the background
//      scheduler loop (main function) or in tasks.  TICKRATE
//      should be defined in "tasks.hpp".

void IncrementTime (void)
	 {
	 #ifdef TIMEINTERNAL
	 TotalTime += TickRate;
	 #endif
	 }

//--------------------------------------------------------------
//  Function: SetAlarm
//      Function to set the rate at which the time of day clock
//      in the PC causes timer interrupts.  This clock runs at
//      about 1.19MHz and can count down from any 16-bit unsigned
//      int to zero.  When it reaches zero, it causes a timer
//      interrupt.  Call SetAlarm ('time') where 'time' is an
//      interval in seconds.  If 'time' is outside the allowable
//      range of intervals, the clock will be reset to the DOS
//    default value of ~54.9 ms, so call SetAlarm with a time
//      less than zero at the end of the program.  SetAlarm()
//      returns 0 if a non-DOS default time is set and FALSE
//      if the default is set (so that if the user wants to set
//      a non-default time, FALSE signifies an error).
//  Note:
//    For a maximum count of 0xFFFF, the time interval is about
//      0.0549 sec.
//  Version:
//    Original - from the lab of D.M.Auslander
//    12-13-94  JJ  Removed compiler specific macro and inout.h; changed all I/O bus
//                  functions to outp().  Changed scope of 'count' to local.
//    12-18-94  JR  Changed to C++; integrated into CTL_EXEC scheduler
//     2-02-95  JR  Moved into CTL_INTR.CPP but not changed

//-------------------------------------------------------
//  Function: TimerEOI
//      Must be called in the Interrupt Service Routine to signal
//      that another interrupt may be scheduled.  Until this
//      function is called, no other interrupts will occur on
//      this channel.
#ifdef ISR_SCHEDULING  // Only define this if needed
void TimerEOI(void)
	 {
	 outp(INTCTL0, TMREOI);
	 }
#endif

⌨️ 快捷键说明

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