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

📄 timer.c

📁 This ZIP file contains the support files for programming the Infineon C167CR CAN interface. Refer to
💻 C
字号:
/******************************************************************************
C167CR CAN Ap. Note project
Timing functions

This is an example program showing how to use the CAN interface on the Keil
MCB167 evaluation board.

Copyright (c) 1997 Keil Software
******************************************************************************/
#include <reg167.h>
#include <intrins.h>
#include "timer.h"

/* The following macro calculates the value to write to an interrupt control
   register.  The arguments are:
   ir:   Interrupt request (0 or 1)
   ie:   Interrupt enable (0 or 1)
   ilvl: Interrupt priority level (0, 1, ... 15)
   glvl: Group level (0, 1, 2, or 3)
*/
#define CALC_IC(ir,ie,ilvl,glvl) ((ir) << 7 | (ie) << 6 | (ilvl) << 2 | glvl)

static unsigned long timer_val;

/* The following three macros control the frequency of the timer interrupt.
   CPU_FREQUENCY_HZ must be the actual CPU frequency.
   The prescaler will divide this frequency by
   2 raised to the (PRESCALE_SELECTION + 2) power.  PRESCALE_SELECTION must be
   an integer >= 0 and <= 7.
   The timer counts down.  When it underflows from 0x0000 to 0xFFFF, it is
   reloaded with RELOAD_VALUE (It is reloaded from the CAPREL register,
   which has been initialized with RELOAD_VALUE.), and generates an interrupt.

   If you change the values of any of these macros, you need to also change
   TIMER_UNITS_PER_SECOND in timer.h to match the new timer interrupt
   frequency.  A compile-time check that TIMER_UNITS_PER_SECOND is the
   correct value follows these macros.
*/
#define RELOAD_VALUE 624            /* value for CAPREL register */
#define PRESCALE_SELECTION 3        /* value for T6I field of T6CON register */
#define CPU_FREQUENCY_HZ 20000000   /* CPU frequency in Hertz */

/* Check that the intended timer interrupt frequency, TIMER_UNITS_PER_SECOND,
   is equal to the calculated timer interrupt frequency.
   Generate an error message if it is not.
*/
#if CPU_FREQUENCY_HZ != \
    TIMER_UNITS_PER_SECOND * (4L << PRESCALE_SELECTION) * (RELOAD_VALUE + 1L)
#error TIMER_UNITS_PER_SECOND does not match calculated value.
#endif


/******************************************************************************
Initialize the timer.

Return: nothing.
-----------------------------------------------------------------------------*/
void
init_timer(void)
{
   CAPREL = RELOAD_VALUE;
   T6 = RELOAD_VALUE;
   T6CON = 0x80c0 | PRESCALE_SELECTION;

   /* interrupt set up */
   T6IC = CALC_IC(0, 1, 10, 0);  /* enable interrupt at priority level 10, group level 0 */
}


/******************************************************************************
Gets the timer value.

Returns: Elapsed time since the timer was initialized, in
         TIMER_UNITS_PER_SECOND * seconds.
-----------------------------------------------------------------------------*/
unsigned long
timer(void)
{
   long temp;

   /* This code was written for a 16-bit processor (Siemens C167CR), so the
      32-bit variable timer_val cannot be processed (copied, incremented, etc.)
      in a single machine instruction.  The _atomic_() and _endatomic_()
      "functions" tell the compiler to generate an ATOMIC machine instruction
      to protect the sequence of instruction processing timer_val from being
      interrupted.  If the timer interrupt (which increments timer_val) occurred
      after one word of timer_val had been copied but before the other word had
      been copied, the copied value could be erroneous.  The problem would
      probably occur only sporadicaly, and be maddeningly difficult to find.
   */

   _atomic_(0);
   temp = timer_val;
   _endatomic_();
   return temp;
}


/******************************************************************************
Interrupt service routine for the timer interrupt.
-----------------------------------------------------------------------------*/
void
timer_interrupt(void) interrupt 0x26
{
   /* See comment in timer() function above discussing interruptability of
      operations on timer_val.
      This operation (incrementing timer_val in the interrupt service
      routine) also needs to be uninterruptable, if any higher-priority
      interrupt handlers make use of the time.  Otherwise, such an interrupt
      could catch timer_val half-updated and get an erroneous time.
   */
   _atomic_(0);
   timer_val++;
   _endatomic_();
}

⌨️ 快捷键说明

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