📄 timer.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 + -