根据频率可得方波周期:t = 1/频率*1000000 (US)
由于所输出的t(US)周期方波中,高/低电平各占50%,因此定时器定时(计数)长度为Count = t/2,即Count=1000000/2/频率
本例中将TCCR1A与TCCR1B分别设为0x00与0x09它们共周将WGM1[3:0]设为0100,使T/C1工作于CTC模式(即OCR1A/B与TCNT1比较匹配时清零T/C1,TCCR1B = 0x09还将TCNT1计数时钟设为使用1分频的系统时钟.
Proteus仿真结果:
Studio6.2 编译通过的截图:
以下是程序清单:
- /*
- * GccApplication8.c
- *
- * Created: 2014-11-3 18:53:36
- * Author: Administrator
- */
- #define F_CPU 1000000UL
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #include <stdint.h>
- #define K1_DOWN() ((PINB & _BV(PB0)) == 0x00)
- #define SPK() (PORTD^=_BV(PD0))
- #define Enable_TIMER1_OCIE() (TIMSK |= _BV(OCIE1A))
- #define Disable_TIMER1_OCIE() (TIMSK &=~_BV(OCIE1A))
- const uint16_t TONE_FRQ[] = {0,262,294,330,349,392,440,494,523,587,659,698,784,880,988,1046};
-
- int main()
- {
- uint8_t i;
- DDRB = 0x00; PORTB = 0xFF;
- DDRD = 0xFF; PORTD = 0xFF;
- TCCR1A = 0x00;
- TCCR1B = 0x09;
-
- sei();
- while(1)
- {
- while(!K1_DOWN());
- while(K1_DOWN());
- for(i=1;i<16;i++)
- {
- OCR1A = F_CPU/2/TONE_FRQ[i];
- TCNT1 = 0;
- Enable_TIMER1_OCIE();
- _delay_ms(200);
- Disable_TIMER1_OCIE();
- _delay_ms(80);
-
- }
- }
-
- }
- ISR(TIMER1_COMPA_vect)
- {
- SPK();
- }
|