void init_timers () { // We use the 8 bit timer to generate the polling interrupt for notes. // It should interrupt often, like every 50 microseconds. TCCR0A = (1 << WGM01); // mode 010: CTC #if CPU_MHZ==4 TCCR0B = 1 << CS00; // clock select 001: no prescaling OCR0A = CPU_MHZ * POLLTIME_USEC; #elif CPU_MHZ==8 TCCR0B = 1 << CS01; // clock select 010: clk/8 prescaling OCR0A = CPU_MHZ/8 * POLLTIME_USEC; #else unusual frequency #endif // We use the 16 bit timer both for timing scores from the interrupt routine // and doing mainline code waits. It interrupts once a millisecond. TCCR1A = 0; // mode 0100: CTC TCCR1B = (1 << WGM12) | (1<<CS10); // clock select 001: no prescaling OCR1A = CPU_MHZ * 1000; tune_playing = false; scorewait_interrupt_count = 0; delaywait_interrupt_count = 0; TIMSK =(1<<OCIE0A) | (1<<OCIE1A); // turn on match A interrupts for both timers Interrupts(); // enable interrupts }
void tune_delay (unsigned duration) { boolean notdone; delaywait_interrupt_count = duration; do { // wait until the interrupt routines decrements the toggle count to zero noInterrupts(); notdone = delaywait_interrupt_count != 0; /* interrupt-safe test */ Interrupts(); } while (notdone); }
void delay_us(uint16_t us) { uint32_t systick = SysTick->VAL; uint16_t count; if(count == 0)return; count = us * 9; if(count>SysTickOverFlowValue - 1)count = SysTickOverFlowValue-1; noInterrupts(); if(systick < count) { count = ((SysTickOverFlowValue-5) + systick - count);/// while(SysTick->VAL <= count) { ; } if(count == 0) count = 1; while(SysTick->VAL > count) { ; } millisSeconds++;//矫正毫秒计数 } else { count = systick - count; if(count == 0) count = 1; while(SysTick->VAL > count) { ; } } Interrupts(); }