2017-05-23 10 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 모드로 할 수 있습니다. 나는 그것을 전에했다. 아이디어는 순수한 440Hz 사인파의 양자화 된 버전을 만들기 위해 PWM과 로우 패스 필터를 사용하는 것입니다. 타이머를 사용하여 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을 사용했습니다).