2017-05-23 40 views
1

此代码会发出短促的声音。我怎样才能发出440hz的声音?avr如何定义一个440Hz的声音?

编辑: 或类似的东西:?我想我不想使用快速PWM。

#include <avr/io.h> 
#include <avr/interrupt.h> 

ISR(TIMER1_COMPA_vect) {  
    PORTB = 0; 
} 

ISR(TIMER1_OVF_vect) { 
    PORTB ^= 8; 
} 

int main(void) { 

    DDRB = 8; 
    PORTB = 0; 
    TCCR1B=(1 << CS10); // Prescaler: 1, Mode: 0 
    OCR1A = 9089.91; // (F_CPU/2/1/440) - 1; 

    TIMSK1 |= (1 << OCIE1A) | (1 << TOIE1); //Interrupt an 
    PCICR = 0x01; 
    sei(); // Interrupts global aktivieren 

    while(1) { 
     }; 
} 
+4

如果你想这样做,你需要调整延迟循环。更好的方法是使用硬件定时器。 –

+0

您正在使用数字输出端口吗? –

+0

是我使用数字输出端口 – Cashew

回答

1

您可以使用快速PWM模式。我以前做过。这个想法是使用PWM和一个低通滤波器来创建一个纯粹的440Hz正弦波的量化版本。这可以通过使用定时器来改变PWM和低通滤波器的占空比以隔离PWM的DC分量来完成。实际上用软件实现并不困难。第一步是取一个440Hz的正弦波并将其转换为一个无符号的8位值的数组。我已经做了这个给你,所以你定义的8位无符号整数数组,看起来像这样:

uint8_t wave[] = { 
    0x13, 0x00, 0x00, 0x00, 
    0x80, 0xab, 0xd1, 0xee, 
    0xfd, 0xfe, 0xf0, 0xd4, 
    0xaf, 0x84, 0x58, 0x31, 
    0x13, 0x03, 0x01, 0x0d, 
    0x28, 0x4d, 0x77 
}; 

正弦波是为了重建具有正弦波8000Hz的频率取样,所以PWM,你需要设置一个定时器,每秒触发一次中断8000次。该中断负责PWM的占空比变化的正弦方式数组中的下一个索引,这将是这个样子:

ISR(...) { 
    OCR1A = wave[index++]; 
    if (index == wave_array_length) { 
     index = 0; 
    } 
}  

如果你想播放音频与PWM一个真正的工作示例。我会发布一个链接(如果我没有记错,我使用了AT90USB647)。