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

📄 timer.c

📁 snake game in avr snake game in avr
💻 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 + -