본문 바로가기
코스웨어/15년 스마트컨트롤러

20150915-14번-박제혁 일일업무일지 - PWM을 이용한 멜로디 연주

by 알 수 없는 사용자 2015. 9. 16.
728x90
반응형



오늘의 성과


스피커를 통해 도미솔 멜로디가 출력되게 했습니다.


 main.c 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <project.h> 
 
void Init(void)
{
    PWM2_Init();
    TIMER_Init();
}
 
int main(void)
{    
    Init();
    
    while(1)
    {
        SetDuty(5731);    //5옥타브 도
        ms_delay(1000);
 
        SetDuty(4549);    //5옥타브 미
        ms_delay(1000);
 
        SetDuty(3825);    //5옥타브 솔
        ms_delay(1000);
    }
 
    return 0;
}
 
cs



 계산법 

예)

MCK = 48000000
분주비 = 32
PWM주파수 = 659.255   (5 옥타브 '미' 의 주파수)

CPRD값 (period) = CDTY * 2
CDTY값 (duty)   = ( MCK / (분주비 * PWM주파수) ) - 1

즉,
MCK = 48000000, 분주비 = 32 일 때, CPRD에 4549(4548.591)를 넣고, CDTY에 2274(2274.2956)를 넣으면

5 옥타브 '미' 가 출력됩니다.





멜로디를 바꾸는 법  

 첫번째 방법 


 1  PWM2_Init 함수 안에서 AT91C_PWMC_CH2_CMR 레지스터 세팅을 할 때,
CPD 비트에다가 1을 넣어주므로 period를 실시간( 실제로는 그 다음 PWM주기부터 적용 )으로 변경할 수 있도록 세팅합니다

1
2
3
4
5
6
*AT91C_PWMC_CH2_CMR = 
        AT91C_PWMC_CPRE_MCKA     //clk A
        & (~AT91C_PWMC_CALG)     //Left alignment
        & (~AT91C_PWMC_CPOL);    //PWM 파형이 Low 로 시작
        
*AT91C_PWMC_CH2_CMR |= (AT91C_PWMC_CPD);//CPD가 0이라면 duty cycle 업데이트,    1이면 period 업데이트
cs



 2  AT91C_PWMC_CH2_CDTYR (duty cycle) 값을 1000으로 고정시킵니다.

*AT91C_PWMC_CH2_CDTYR = 1000;



 3  SetDuty 함수가 호출될 때마다 period 값을 새로 고치게 합니다. (CPD가 1로 세팅되어 있으므로)

1
2
3
4
void SetDuty(int X2)
{
    *AT91C_PWMC_CH2_CUPDR = X2;
}
cs



즉, CDTY를 1000으로 고정시킨 상태에서 CPRD만 바꾸는 코드입니다.

period 값을 고치므로 pwm 파형의 주파수가 변하게 되어 다른 소리를 출력하게 됩니다.

듀티비가 50%는 아니더라도 멜로디 연주에 문제가 없는 걸 확인했습니다.

왜 그런지는 잘 모르겠습니다.. 알려주시면 감사하겠습니다~








멜로디를 바꾸는 법  

 두번째 방법 

PWM2_Init 함수를 건드리지 않습니다.
SetDuty 함수는
1. 잠시 PWM 2채널을 disable 시킵니다.
2. CDTY와 CPRD값을 다른 값으로 초기화 시킵니다.
3. PWM 2채널을 enable 합니다.

1
2
3
4
5
6
7
void SetDuty(int X2)
{
    *AT91C_PWMC_DIS = AT91C_PWMC_CHID2;
    *AT91C_PWMC_CH2_CPRDR = X2;
    *AT91C_PWMC_CH2_CDTYR = X2/2;
    *AT91C_PWMC_ENA = AT91C_PWMC_CHID2;
}

cs


CDTY와 CPRD 값은 PWM이 사용중일때는 새로운 값을 못쓰기 때문에

disable 시킨 후, 값을 쓰고, 다시 enable 하도록 했습니다.

듀티비는 50%를 유지합니다.





 참고 

1. AT91C_PWMC_CH2_CMR 레지스터는 PWM 2채널이 disable되어 있을 때 값이 써지는 것 같습니다.

2. 도솔을 1ms 딜레이로 빠르게 출력시켜도 화음처럼 들리지는 않았습니다 ㅠ

3. 이번 업무일지 작성에 남수진 누나의 도움을 받았습니다. 감사합니다~


728x90