2017-01-31 11 views
1

수동적 인 여름을 통해 출력 할 sin-waves를 생성하는 프로그램을 만들려고합니다. 따라서 버튼을 누르면 사운드가 재생됩니다.PIC32 - PWM과 Sin-wave

PWM을 사용할 수 있고 상수 값을 사용하여 메모를 재생할 수 있지만 상수 대신 Sin-waves를 사용하고 싶습니다.

는 Heres는 지금까지 가지고 올 필자 코드 : 내가 버튼을 누르면

#include <pic32mx.h> 
#include <stdint.h> 

extern void _enable_interrupt(); 

//Change length of the Steps. 
#define step 0.00000000000000000001 


struct Note{ 
int number; 
int freq; 
double A; 
double x; 
int play; 
}Note; 

struct Note array[12]; 

void gen(int i){ 
float pi = 3.141592; 
double x = array[i].x; 
double freq = array[i].freq; 
double A = sin(freq*x*step*2*pi); 
x++; 
array[i].A = A; 
array[i].x = x; 
} 

void initNotes(){ 



struct Note C = {0, 200, 0.0, 0.0, 0}; 
struct Note Ciss = {1, 200, 0.0, 0.0, 0}; 
struct Note D = {2, 200, 0.0, 0.0, 0}; 
struct Note Diss = {3, 4100, 0.0, 0.0, 0}; 
struct Note E = {4, 3900, 0.0, 0.0, 0}; 
struct Note F = {5, 3700, 0.0, 0.0, 0}; 
struct Note Fiss = {6, 3500, 0.0, 0.0, 0}; 
struct Note G = {7, 3300, 0.0, 0.0, 0}; 
struct Note Giss = {8, 3100, 0.0, 0.0, 0}; 
struct Note B = {9, 2900, 0.0, 0.0, 0}; 
struct Note Biss = {10, 2700, 0.0, 0.0, 0}; 

array[0] = C; 
array[1] = Ciss; 
array[2] = D; 
array[3] = Diss; 
array[4] = E; 
array[5] = F; 
array[6] = Fiss; 
array[7] = G; 
array[8] = Giss; 
array[9] = B; 
array[10] = Biss; 


} 
void initSynth() { 
for(;;) { 
    int btns = getBtns(); 

    // Check buttons. If button is pressed, corresponding note's play-value will be set to 1 (true) 
    if((PORTD & 0b000000100000) == 0b000000100000){ 
     array[0].play = 1; 

    }else{ 
     array[0].play = 0; 
    } 
    if((PORTD & 0b000001000000) == 0b000001000000){ 
      array[1].play = 1; 
    } 
    else{ 
     array[1].play = 0; 
    } 
    if((PORTD & 0b000010000000) == 0b000010000000){ 
      array[2].play = 1; 
    }else { 
     array[2].play = 0; 
    } 
    // Check note-array for notes with play-value 1 (true). These are added together. 

    int c; 
    int nr; 
    int i; 
    for(i = 0; i < 11; i++){ 
    if(array[i].play == 1){ 
    c = c + array[i].A; 
    gen(i); 
    nr++; 
    } 
     } 

    // Set PWM to previously calculated value. 
    if((c/nr) > 0){ 
     setPwm((c/nr), 50); 
    } else setPwm(0,0); 
} 
} 

int getBtns(void) { 
    return((PORTD >>5) &0x7); /* Port D bits 5 through 8 is used for the Buttons and is set to 1 (input) */ 
} 

int getSwitches(void) { 
    return((PORTD>>8) &0xF); /* Port D bits 8 through 12 is used for the Switches and is set to 1 (input) */ 
} 

int getbtn(void) { 
    return(PORTD &0x1); 
} 


void initPwm(){ 
T2CON = 0x070; // Clear timer2, prescale at 1:1 
TMR2 = 0x0; // Timer2 value starts at 0 
OC1CON = 0x0000; // Turn off and clear pwm 
OC1R = 0x0001; 
OC1RS = 0; // Dutycycle 
OC1CON = 0x0006; // Configure for PWM mode without Fault pin 
PR2 = 0; // Set dutycycle, HÄR ÄNDRAR MAN TONER! 
IECSET(0) = 0x0100; // Enable T2 interrupt 
IPCSET(2) = 0x01C; // Set T2 interrupt priority to 7 
enable_interrupt(); 
OC1CONSET = 0x08000; // Enable OC1 
T2CONSET |= 0x08000; // Enable Timer2 
} 

void setPwm(int pwm, int duty){ 
    int dutycycle = 0xFFFFFFFF * (duty/100); 
OC1RS = duty; 
PR2 = pwm; 
} 

int main(void) { 
TRISE = 0x00; /* Port E bits 0 through 7 is used for the LED and is set to 0 (output) */ 
PORTE = 0x00; 
initNotes(); 
initPwm(); 
initSynth(); 
return 0; 
} 

void user_isr(void) { 
if((IFS(0)&0x0100)==0x0100){ 
    IFSCLR(0) = 0x0100; 
} 
} 

여름 버즈와 다른 속도로 내가 버튼을 누를 때마다 체크하기 시작합니다. 때로는 깨끗한 색조를 얻으므로 솔루션에 다소 가깝다고 느끼게됩니다. 컴퓨터가 번갈아 진행되는 문제입니까? 어쩌면 해결책이 어딘가에 다른 타이머를 추가하는 것일까 요?

답변

1

가청음을 얻기에 충분히 빠른 속도로 PIC를 실행하지는 않습니다. 당신은 PWM 속도가 아마도 낮은 kHz 또는 Hz 범위에 있으므로 소리가 끔찍합니다. OSC 제품군 참조 매뉴얼을 읽고 설정 비트를 사용하여 80MHz 용 PIC를 설정하십시오 (PIC32MX를 사용하는 경우). http://ww1.microchip.com/downloads/en/DeviceDoc/61112H.pdf