課題4-11 解答例

#define F_CPU 16000000UL //16MHz動作

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

/*
 * 音階データの定義(PWM値)
 * 16000000Hz / 256 / 周波数
 */
#define    C0      478
#define    C0S     451
#define    D0      426
#define    D0S     402
#define    E0      379
#define    F0      358
#define    F0S     338
#define    G0      319
#define    G0S     301
#define    A0      284
#define    A0S     268
#define    B0      253

#define    C1    239
#define    C1S     225
#define    D1     213
#define    D1S     201
#define    E1      190
#define    F1     179
#define    F1S     169
#define    G1     159
#define    G1S     150
#define    A1     142
#define    A1S     134
#define    B1      127

#define    C2     119
#define    C2S     113
#define    D2     106
#define    D2S     100
#define    E2      95
#define    F2     89
#define    F2S     84
#define    G2     80
#define    G2S     75
#define    A2     71
#define    A2S     67
#define    B2      63

#define    P   0  // 休符

/*
 * 音符の長さ
 */
#define T16        80
#define T8        160
#define T4        320
#define T2        640
#define T1        1280    


void hw_init()
{
// PWM
    DDRD |= 0b00000001; //PD0を出力に(OC0B)
    DDRB |= 0b10000000; //PB7を出力に(OC0A)
    PORTD = 0b00000001;
    PORTB = 0b10000000;

    TCCR0A = 3;                     // 高速PWMモード(モード7)に設定
    TCCR0B |= _BV(WGM02);   // TOPをOCR0Aの値 (モード7)

    TCCR0A |= _BV(COM0B1);  // OC0Bを出力
    TCCR0B |= _BV(CS02) ;    // 周波数設定(PWMの一周期) (TCNT:8bit)
                            // システムクロックが16MHzでTCNTがリセットされる値がOCR0A(上限値)であるため、
                            // 16000000 / 分周比 / OCR0AがPWMの一周期となる。
                            // (分周比が1なら62500Hz→16uS)
}


//int doremi[] = {B0,C1,C1S, D1, D1S, E1, F1, F1S, G1, G1S, A1, A1S, B1, C2, C2S, D2, D2S,
//                     E2, F2, F2S, G2, G2S, A2, A2S, B2};

/*
 * 楽譜データ ~君をのせて(天空の城ラピュタ)~
 */
int doremi[][2] = {
                  {E1,T8}, {F1S,T8},
                  {G1,T4+T8}, {F1S, T8}, {G1, T4}, {B1, T4},
                  {F1S, T2}, {P, T4}, {B0, T4},
                  {E1, T4+T8}, {D1, T8}, {E1, T4}, {G1, T4},
                  {D1, T2}, {P, T4}, {B0, T8}, {B0, T8},

                  {C1, T4+T8}, {B0, T8}, {C1, T8}, {G1, T4+T8},
                  {B0, T2}, {P, T8}, {G1, T8}, {G1, T8}, {G1, T8},
                  {F1S, T4+T8}, {C1S, T8}, {C1S, T4}, {F1S, T4},//
                  {F1S, T2}, {P, T4}, {E1, T8}, {F1S, T8},
                  
                  {G1, T4+T8}, {F1S, T8}, {G1, T4}, {B1, T4},
                  {F1S, T2}, {P, T4}, {B0, T8}, {B0, T8},
                  {E1, T4+T8}, {D1, T8}, {E1, T4}, {G1, T4},
                  {D1, T2}, {P, T4}, {P, T8}, {B0, T8},
                  
                  {C1, T4}, {G1, T8}, {F1S, T8}, {F1S, T4}, {G1, T4},
                  {A1, T8}, {A1, T8}, {B1, T4}, {G1, T4}, {P, T4}, // 5?
                  {G1, T8}, {F1S, T8}, {E1, T8}, {E1, T8}, {F1S, T4}, {D1S, T4},
                  {E1, T2}, {P, T4}, {G1, T8}, {A1, T8},
                  
                  {B1, T4+T8}, {A1, T8}, {B1, T4}, {D2, T4},
                  {A1, T2}, {P, T4}, {D1, T8}, {D1, T8},
                  {G1, T4+T8}, {F1S, T8}, {G1, T4}, {B1, T4},
                  {B1, T2+T4}, {P, T4},
              
                  {E1, T8}, {F1S, T8}, {G1, T4}, {F1S, T8}, {G1, T8}, {A1, T8}, {A1, T8},
                  {G1, T4+T8} , {D1, T8}, {D1, T4}, {P, T4},
                  {C2, T4}, {B1, T4}, {A1, T4}, {G1, T4},
                  {B1, T1},
                  {B1, T2}, {P, T4}, {B1, T4},
                  
                  {E2, T2}, {D2, T4+T8}, {D2, T8},
                  {B1, T8}, {A1, T8}, {G1, T2}, {P, T8}, {G1, T8},
                  {A1, T4}, {G1, T8}, {A1, T8}, {A1, T8}, {D2, T4+T8},
                  {B1, T2}, {P, T4}, {B1, T4},
                  
                  {E2, T2}, {D2, T2},
                  {B1, T8}, {A1, T8}, {G1, T2}, {P, T8}, {G1, T8},
                  {A1, T4}, {G1, T8}, {A1, T8}, {A1, T4}, {F1S, T4},
                  {E1, T2}, {P, T4}
              };

// PWMの切り替えと音の長さ
void sound(int f, int t)
{
       OCR0A = f;
       OCR0B = f >> 1;  // デューティを1/2に設定
      _delay_ms(t);  // 音符の長さ

     OCR0A = 0;  // 音符の区切り
     OCR0A = 0;
    _delay_ms(3); 
}

int main()
{
    int i;

    CLKPR = 0x80; CLKPR = 0;    // 16MHz動作のための設定
 
    hw_init();  // PWMの設定

    DDRB = 0b11111111;  // デバッグ用の設定(無くて良し)

    while(1) {
        for (i=0; i < sizeof(doremi)/4; i++) {
            PORTB = i;  // デバッグ用の設定(無くて良し)
            sound(doremi[i][0], doremi[i][1]);

        }
    }
}

 

最終更新:2015年06月23日 16:09