📄 timer.c
字号:
/*
** timer.c
**
** Written by Peter Sutton - October 2004
*/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
volatile unsigned int time;
unsigned int time_period;
volatile unsigned int sleep_timer;
volatile int8_t period_over_flag;
/*
** Set up timer 0 (8 bit timer) so that we get a regular interrupt
** (every 10 milliseconds, i.e. every 40000 clock cycles or
** 100 times per second). We will use this as our timebase and can set
** a target time at which time a flag will be set.
**
** Timer 0 can only generate an interrupt on overflow and we want to
** count 156 * 256 clock cycles, we therefore reset the counter value
** to be 100. (A count of 156 takes it up to 256, i.e. overflow.)
*/
void init_timer(int period) {
/*
** Turn off interrupts whilst we initialise the timer.
** (There is a chance they were off to start with, so
** we keep track of this.)
*/
int8_t interrupts_enabled = bit_is_set(SREG, SREG_I);
cli();
/*
** Initialise our time variables
*/
time = 0;
sleep_timer = 0;
period_over_flag = 0;
time_period = period;
/*
** Enable timer 0 overflow interrupt. (Global interrupts will
** need to be enabled for this to trigger.)
*/
TIMSK |= (1<<TOIE0);
/*
** Clear the overflow flag (we do this by writing a one to it)
*/
TIFR &= (1 << TOV0);
/*
** Initialise the timer value
*/
TCNT0 = 100;
/*
** Set timer to count on clock divided by 256
*/
TCCR0 = (1<<CS02);
/*
** If interrupts were enabled, reenable them
*/
if(interrupts_enabled) {
sei();
}
}
int8_t is_period_over(void) {
int8_t result;
/* We're dealing with quantities that may change in
** an ISR - turn off interrupts while we access them.
*/
int8_t interrupts_enabled = bit_is_set(SREG, SREG_I);
cli();
result = period_over_flag;
period_over_flag = 0;
/*
** If interrupts were enabled, reenable them
*/
if(interrupts_enabled) {
sei();
}
return result;
}
void sleep_until_period_over(void) {
while(!period_over_flag) {
/* Do nothing until period_over_flag is true
*/
}
period_over_flag = 0;
}
void sleep(unsigned int delay_milliseconds) {
/*
** If global interrupts are off, we return
** immediately, because otherwise we would
** block forever
*/
int8_t interrupts_enabled = bit_is_set(SREG, SREG_I);
if(!interrupts_enabled) {
return;
}
/* Turn off interrupts.
*/
cli();
/*
** Set our sleep timer to 0. (The timer is updated in the
** timer interrut service routine, which is why we
** turn off interrupts before changing this value.)
*/
sleep_timer = 0;
/*
** Turn interrupts back on.
*/
sei();
/*
** Wait for time to pass
*/
while(sleep_timer < delay_milliseconds) {
/* Do nothing - ISRs will be run, but nothing else.
** The timer ISR will increment the sleep_timer
** value.
*/
}
}
void pause_timer(void) {
TCCR0 = 0;
}
void restart_timer(void) {
TCCR0 = (1 << CS02);
}
/*
** Interrupt handler for timer 0 overflow. The CPU will clear the
** overflow flag (TOV0) on calling this handler.
*/
SIGNAL(SIG_OVERFLOW0) {
/*
** Reset the timer so the next interrupt happens
** at an appropriate time (i.e. in 10ms)
*/
TCNT0 = 100;
/*
** Update our global time variable and our sleep timer.
** (We don't care if the sleep timer overflows.)
*/
time+=10;
sleep_timer+= 10;
/*
** If our time value has reached its target, set the flag and
** start counting again.
*/
if(time >= time_period) {
period_over_flag = 1;
time = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -