📄 timer.cpp
字号:
/* Timer.cpp
*
* Accurate timing.
*
* #define one of the following values to select the appropriate code
* based on your microcontroller and desired Timer/Counter (T/C) usage.
*
* define T/C
* --------- ---
* TIMER_0 0
* TIMER_2 2
*
* Valid combinations:
*
* ATmega CLOCK_ T/C
* ------ ------- ----
* 8 8M, 16M 2
* 16, 32 8M 0, 2
* 16M 2
* 644 8M 0, 2
* 16M 2
* 128 8M 0, 2
* 16M 0
*
* Revisions:
* 07-28-06 vectComp name change
* 07-13-06 included in LCDSample project
* 07-05-06 version 1 in master library
*
* Written by Cathy Saxton
* robotics@idleloop.com
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "Util.h"
#include "Timer.h"
/* Timer settings
*
* WGM (waveform generation mode) = CTC (Clear Timer on Compare Match)
* CS (clock select)
* choose prescale to result in 125 kHz
* 8 Mhz / 64
* 16 MHz / 128
* OCR (top/clear value) = 125 for match every 1 ms
*/
/* value to use for CS depends on uC, Timer/Counter, and uC clock speed */
#ifdef __AVR_ATmega8__
#ifdef TIMER_2
#ifdef CLOCK_8M
#define csTimer 0x04 // 100
#elif defined CLOCK_16M
#define csTimer 0x05 // 101
#endif // CLOCK
#endif // TIMER
#elif defined __AVR_ATmega16__ || defined __AVR_ATmega32__
#ifdef TIMER_0
#ifdef CLOCK_8M
#define csTimer 0x03 // 011
#endif // CLOCK
#elif defined TIMER_2
#ifdef CLOCK_8M
#define csTimer 0x04 // 100
#elif defined CLOCK_16M
#define csTimer 0x05 // 101
#endif // CLOCK
#endif // TIMER
#elif defined __AVR_ATmega644__
#ifdef TIMER_0
#ifdef CLOCK_8M
#define csTimer 0x03 // 011
#endif // CLOCK
#elif defined TIMER_2
#ifdef CLOCK_8M
#define csTimer 0x04 // 100
#elif defined CLOCK_16M
#define csTimer 0x05 // 101
#endif // CLOCK
#endif // TIMER
#elif defined __AVR_ATmega128__
#ifdef TIMER_0
#ifdef CLOCK_8M
#define csTimer 0x04 // 100
#elif defined CLOCK_16M
#define csTimer 0x05 // 101
#endif // CLOCK
#elif defined TIMER_2
#ifdef CLOCK_8M
#define csTimer 0x03 // 011
#endif // CLOCK
#endif // TIMER
#endif
#ifndef csTimer
#error "unsupported configuration for Timer"
#endif
#ifdef TIMER_0
#ifdef __AVR_ATmega644__
/*
* Timer/Counter 0 (compare A)
*
* WGM (CTC) = 010
*/
#define regTCNT TCNT0 // Timer/Counter register
#define regTIMSK TIMSK0 // interrupt mask register
#define bitOCIE OCIE0A // interrupt enable bit
#define vectComp TIMER0_COMPA_vect // interrupt vector for compare match
inline void Init2()
{
TCCR0A = 0x02; // 00 00 xx 10 (COMA, COMB, low 2 bits WGM)
TCCR0B = 0x00 | csTimer; // 00 xx 0 *** (misc, high bit WGM, CS)
OCR0A = 125;
}
#else // !mega644
/*
* Timer/Counter 0
*
* WGM (CTC) = 10
*/
#define regTCNT TCNT0 // Timer/Counter register
#define regTIMSK TIMSK // interrupt mask register
#define bitOCIE OCIE0 // interrupt enable bit
#define vectComp TIMER0_COMP_vect // interrupt vector for compare match
inline void Init2()
{
OCR0 = 125;
TCCR0 = 0x08 | csTimer; // 0 0 00 1 *** (FOC, WGM low, COM, WGM high, CS)
}
#endif // uC selection
#elif defined TIMER_2
#ifdef __AVR_ATmega644__
/*
* Timer/Counter 2 (compare A)
*
* WGM (CTC) = 010
*/
#define regTCNT TCNT2 // Timer/Counter register
#define regTIMSK TIMSK2 // interrupt mask register
#define bitOCIE OCIE2A // interrupt enable bit
#define vectComp TIMER2_COMPA_vect // interrupt vector for compare match
inline void Init2()
{
TCCR2A = 0x02; // 00 00 xx 10 (COMA, COMB, low 2 bits WGM)
TCCR2B = 0x00 | csTimer; // 00 xx 0 *** (misc, high bit WGM, CS)
OCR2A = 125;
}
#else // !mega644
/*
* Timer/Counter 2
*
* WGM (CTC) = 10
*/
#define regTCNT TCNT2 // Timer/Counter register
#define regTIMSK TIMSK // interrupt mask register
#define bitOCIE OCIE2 // interrupt enable bit
#define vectComp TIMER2_COMP_vect // interrupt vector for compare match
inline void Init2()
{
TCCR2 = 0x08 | csTimer; // 0 0 00 1 *** (FOC, WGM low, COM, WGM high, CS)
OCR2 = 125;
}
#endif // uC selection
#else
#error "unrecognized TIMER_* definition (see header comment)"
#endif
bool TIMER::s_fInit = fFalse;
/* this counts the number of milliseconds since Timer/Counter
was initialized (volatile to make sure loops work!) */
static volatile ulong s_msTimer = 0;
TIMER::TIMER()
{
if (!s_fInit)
Init();
}
/* sets up Timer/Counter (using defines above) */
void TIMER::Init()
{
s_fInit = fTrue;
/* start counting at 0 */
regTCNT = 0;
Init2();
/* set Compare Match Interrupt Enable */
SetBit(regTIMSK, bitOCIE);
/* set I-bit in SREG (global enable for interrupts) */
sei();
}
/* returns number of ms since Timer initialized */
ulong TIMER::MsCur() const
{
char sregSav;
ulong ms;
/* disable (delay) interrupts while we read
s_msTimer since it's 4 bytes and we don't
want it changing during the read! */
sregSav = SREG; // cache register holding Global Interrupt Flag
cli(); // clear Global Interrupt Flag
ms = s_msTimer;
SREG = sregSav; // restore register holding Global Interrupt Flag
return ms;
}
/* returns true if the specified number of milliseconds
has passed since the start time */
bool TIMER::FElapsed(ulong msStart, ulong msWait) const
{
return MsCur() - msStart > msWait;
}
/* waits (pauses) for the specified number of milliseconds */
void TIMER::WaitMs(uint ms) const
{
ulong msStart;
msStart = MsCur();
while (!FElapsed(msStart, ms))
;
}
/* this interrupt happens every ms, when the counter (TCNTn)
reaches the specified OCRn value */
ISR(vectComp)
{
++s_msTimer;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -