電子オルゴールサンプル
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#analog
#norelated
#contents
* 電子オルゴールサンプル [#u83badf4]
スピーカーを繋いで、タイマーによる周波数出力で音楽を演奏...
色々考えてみたけど、和音は一筋縄ではいかなさそうなので、...
** 回路図 [#xe36eef5]
#ref(BeepTest.png,left,nowrap,電子オルゴールサンプル)
基本的にはスピーカーのみの接続です。~
[[部品購入1回目]]で、秋月で買った圧電スピーカーね。~
後で、RTCと組み合わせたり、他のセンサと組み合わせることに...
** ソースコード [#x29c38ec]
いつものライブラリ。~
今回はユーティリティ(delay)のみ。~
&ref(util.h,left,nowrap,ユーティリティヘッダ);&ref(util.c...
まずは、音階の周波数定義と、音符の長さ定義用のファイルを...
内容は以下の通り。~
#ifndef MUSIC_DEF_H_
#define MUSIC_DEF_H_
typedef enum _tagNOTE_HZ{ // 音階リスト
NOTE_HZ_NONE,
NOTE_HZ_C3,
NOTE_HZ_C3S,
NOTE_HZ_D3,
NOTE_HZ_D3S,
NOTE_HZ_E3,
NOTE_HZ_F3,
NOTE_HZ_F3S,
NOTE_HZ_G3,
NOTE_HZ_G3S,
NOTE_HZ_A3,
NOTE_HZ_A3S,
NOTE_HZ_B3,
NOTE_HZ_C4,
NOTE_HZ_C4S,
NOTE_HZ_D4,
} NOTE_HZ;
typedef enum _tagNOTE_LEN{ // 音符リスト
NOTE_LEN_ZEN,
NOTE_LEN_2BU,
NOTE_LEN_2_BU,
NOTE_LEN_4BU,
NOTE_LEN_4_BU,
NOTE_LEN_8BU,
NOTE_LEN_16BU,
} NOTE_LEN;
typedef struct _tagNOTE{ // 音符データ構造体
uint8_t hz;
uint8_t len;
} NOTE;
uint8_t note_hz[] = { // 音階周波数リスト(CPUクロック1MH...
0, // 休符
( 1000000 / 2 / 8 ) / 261.62, // C3
( 1000000 / 2 / 8 ) / 277.18, // C3#
( 1000000 / 2 / 8 ) / 293.66, // D3
( 1000000 / 2 / 8 ) / 311.12, // D3#
( 1000000 / 2 / 8 ) / 329.62, // E3
( 1000000 / 2 / 8 ) / 349.22, // F3
( 1000000 / 2 / 8 ) / 369.99, // F3#
( 1000000 / 2 / 8 ) / 391.99, // G3
( 1000000 / 2 / 8 ) / 415.30, // G3#
( 1000000 / 2 / 8 ) / 440.00, // A3
( 1000000 / 2 / 8 ) / 466.16, // A3#
( 1000000 / 2 / 8 ) / 493.88, // B3
( 1000000 / 2 / 8 ) / 523.25, // C4
( 1000000 / 2 / 8 ) / 554.36, // C4#
( 1000000 / 2 / 8 ) / 587.32, // D4
};
uint16_t note_len[] = { // 音符長リスト
60000 / BPM * 4, // 全音符
60000 / BPM * 2, // 二分音符
60000 / BPM * 3, // 附点二分音符
60000 / BPM, // 四分音符
60000 / BPM * 1.5, // 附点四分音符
60000 / BPM / 2, // 八分音符
60000 / BPM / 4, // 十六分音符
};
#endif /* MUSIC_DEF_H_ */
見ての通り、音階リストの列挙型と音階周波数リストが、音符...
周波数リストは、CPUの周波数と、実際の音階周波数を元に算出...
今回、音をスピーカーから出力するために、8bitタイマの比較...
8bitタイマが0〜比較レジスタに格納した値までカウントを行い...
例えば、A3「ラ」の音の周波数は440Hzなので、ピンのON/OFF1...
ということは、ON/OFFの切り替えが実質2回の処理なので、1秒...
8bitタイマは、基本的には、CPUのクロックが0〜最大255回まで...
というわけで、タイマ機能の前置分周を8に設定し、CPUクロッ...
こうすれば、1136/8で142回となるので、8bitタイマの比較レジ...
まぁ、16bitタイマを使えば、前置分周とかは考えなくてもいい...
#ref(Timing.png,left,nowrap,タイミング)
あと、音符長リストには、BPMという定数を使った計算をしてい...
これは、後でメインソースの方で定義しますが、曲のテンポで...
1分間に四分音符が何個かという単位なので、それをミリ秒単位...
次に、楽譜ファイル。~
サンプルで作ってみたのは、「ドレミの歌」。~
music_def.hで定義した音符データ構造体の配列に、音階と音符...
#ifndef DOREMI_H_
#define DOREMI_H_
NOTE score[] ={ // ドレミの歌
{ NOTE_HZ_C3, NOTE_LEN_4_BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_4_BU },
{ NOTE_HZ_C3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4_BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_4_BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4_BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_4_BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4_BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_4_BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4_BU },
{ NOTE_HZ_C3, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4_BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3S, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4_BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3S, NOTE_LEN_8BU },
{ NOTE_HZ_G3S, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_C4, NOTE_LEN_2BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_A3S, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_C4, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_4BU },
{ NOTE_HZ_D3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_C4, NOTE_LEN_4BU },
{ NOTE_HZ_C4, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_D3, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_D3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_2BU },
{ NOTE_HZ_C3, NOTE_LEN_2BU },
{ NOTE_HZ_A3, NOTE_LEN_2BU },
{ NOTE_HZ_F3, NOTE_LEN_2BU },
{ NOTE_HZ_E3, NOTE_LEN_2BU },
{ NOTE_HZ_C3, NOTE_LEN_2BU },
{ NOTE_HZ_D3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_2BU },
{ NOTE_HZ_C3, NOTE_LEN_2BU },
{ NOTE_HZ_A3, NOTE_LEN_2BU },
{ NOTE_HZ_B3, NOTE_LEN_2BU },
{ NOTE_HZ_C4, NOTE_LEN_2BU },
{ NOTE_HZ_D4, NOTE_LEN_2BU },
{ NOTE_HZ_C4, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
};
#endif /* DOREMI_H_ */
そしてメイン関数。~
メインは短め。~
#include <avr/io.h>
#include "util.h"
#define BPM 140 // テンポ設定
#include "music_def.h"
#include "doremi.h"
int main( void )
{
uint8_t i = 0; // ループ変数
DDRD = 0b01000000; // PD6(OC0A)を出力に設定
PORTD = 0b00000000; // ポートDをLowに初期化
while( 1 ){
for( i = 0; i < sizeof( score ) / sizeof( NOTE ); i++ ){
if( NOTE_HZ_NONE == score[i].hz ){
TCCR0A = 0b00000000; // タイマー停止
} else {
OCR0A = note_hz[score[i].hz]; // 周波数設定
TCCR0A = 0b01000010; // 比較一致トグル出力
TCCR0B = 0b00000010; // 前置分周8
}
delay_ms( note_len[score[i].len] );
}
}
return 0;
}
BPM(テンポ)の定義をしてからmusic_def.hをincludeすることで...
先にincludeしてしまうと、定義が解決出来ないので注意。~
タイマの出力をピンに反映させるためには、ポート方向レジス...
ポートの初期化後に、メインループに入ります。~
無限ループ内に曲のループがあり、音符データ構造体を一つず...
休符設定の時は、タイマを止め、指定音符長だけ待ちます。~
それ以外の時は、比較レジスタ値を設定し、タイマを動作させ...
** 基本動作 [#k21d9ac5]
基本、楽譜通りに鳴らしているだけですが、同じ音が複数続い...
音符の合間で一旦止めているわけではないので当然ですが。~
今回鳴らす音が、次回鳴らす音と同じであれば、数ミリ秒演奏...
意図して繋げたい場合は、スラーを示すフラグを用意するとか…...
あと、もうひとつ、比較レジスタ値を途中で変えていますが、...
このため、場合によっては一瞬(半波長)だけ低い音の周波数の...
圧電スピーカーは音が甲高くて耳につきますね……。~
超小型スピーカーの方がよかったかも。~
終了行:
#analog
#norelated
#contents
* 電子オルゴールサンプル [#u83badf4]
スピーカーを繋いで、タイマーによる周波数出力で音楽を演奏...
色々考えてみたけど、和音は一筋縄ではいかなさそうなので、...
** 回路図 [#xe36eef5]
#ref(BeepTest.png,left,nowrap,電子オルゴールサンプル)
基本的にはスピーカーのみの接続です。~
[[部品購入1回目]]で、秋月で買った圧電スピーカーね。~
後で、RTCと組み合わせたり、他のセンサと組み合わせることに...
** ソースコード [#x29c38ec]
いつものライブラリ。~
今回はユーティリティ(delay)のみ。~
&ref(util.h,left,nowrap,ユーティリティヘッダ);&ref(util.c...
まずは、音階の周波数定義と、音符の長さ定義用のファイルを...
内容は以下の通り。~
#ifndef MUSIC_DEF_H_
#define MUSIC_DEF_H_
typedef enum _tagNOTE_HZ{ // 音階リスト
NOTE_HZ_NONE,
NOTE_HZ_C3,
NOTE_HZ_C3S,
NOTE_HZ_D3,
NOTE_HZ_D3S,
NOTE_HZ_E3,
NOTE_HZ_F3,
NOTE_HZ_F3S,
NOTE_HZ_G3,
NOTE_HZ_G3S,
NOTE_HZ_A3,
NOTE_HZ_A3S,
NOTE_HZ_B3,
NOTE_HZ_C4,
NOTE_HZ_C4S,
NOTE_HZ_D4,
} NOTE_HZ;
typedef enum _tagNOTE_LEN{ // 音符リスト
NOTE_LEN_ZEN,
NOTE_LEN_2BU,
NOTE_LEN_2_BU,
NOTE_LEN_4BU,
NOTE_LEN_4_BU,
NOTE_LEN_8BU,
NOTE_LEN_16BU,
} NOTE_LEN;
typedef struct _tagNOTE{ // 音符データ構造体
uint8_t hz;
uint8_t len;
} NOTE;
uint8_t note_hz[] = { // 音階周波数リスト(CPUクロック1MH...
0, // 休符
( 1000000 / 2 / 8 ) / 261.62, // C3
( 1000000 / 2 / 8 ) / 277.18, // C3#
( 1000000 / 2 / 8 ) / 293.66, // D3
( 1000000 / 2 / 8 ) / 311.12, // D3#
( 1000000 / 2 / 8 ) / 329.62, // E3
( 1000000 / 2 / 8 ) / 349.22, // F3
( 1000000 / 2 / 8 ) / 369.99, // F3#
( 1000000 / 2 / 8 ) / 391.99, // G3
( 1000000 / 2 / 8 ) / 415.30, // G3#
( 1000000 / 2 / 8 ) / 440.00, // A3
( 1000000 / 2 / 8 ) / 466.16, // A3#
( 1000000 / 2 / 8 ) / 493.88, // B3
( 1000000 / 2 / 8 ) / 523.25, // C4
( 1000000 / 2 / 8 ) / 554.36, // C4#
( 1000000 / 2 / 8 ) / 587.32, // D4
};
uint16_t note_len[] = { // 音符長リスト
60000 / BPM * 4, // 全音符
60000 / BPM * 2, // 二分音符
60000 / BPM * 3, // 附点二分音符
60000 / BPM, // 四分音符
60000 / BPM * 1.5, // 附点四分音符
60000 / BPM / 2, // 八分音符
60000 / BPM / 4, // 十六分音符
};
#endif /* MUSIC_DEF_H_ */
見ての通り、音階リストの列挙型と音階周波数リストが、音符...
周波数リストは、CPUの周波数と、実際の音階周波数を元に算出...
今回、音をスピーカーから出力するために、8bitタイマの比較...
8bitタイマが0〜比較レジスタに格納した値までカウントを行い...
例えば、A3「ラ」の音の周波数は440Hzなので、ピンのON/OFF1...
ということは、ON/OFFの切り替えが実質2回の処理なので、1秒...
8bitタイマは、基本的には、CPUのクロックが0〜最大255回まで...
というわけで、タイマ機能の前置分周を8に設定し、CPUクロッ...
こうすれば、1136/8で142回となるので、8bitタイマの比較レジ...
まぁ、16bitタイマを使えば、前置分周とかは考えなくてもいい...
#ref(Timing.png,left,nowrap,タイミング)
あと、音符長リストには、BPMという定数を使った計算をしてい...
これは、後でメインソースの方で定義しますが、曲のテンポで...
1分間に四分音符が何個かという単位なので、それをミリ秒単位...
次に、楽譜ファイル。~
サンプルで作ってみたのは、「ドレミの歌」。~
music_def.hで定義した音符データ構造体の配列に、音階と音符...
#ifndef DOREMI_H_
#define DOREMI_H_
NOTE score[] ={ // ドレミの歌
{ NOTE_HZ_C3, NOTE_LEN_4_BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_4_BU },
{ NOTE_HZ_C3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4_BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_4_BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4_BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_4_BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4_BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_4_BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4_BU },
{ NOTE_HZ_C3, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4_BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3S, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4_BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_F3S, NOTE_LEN_8BU },
{ NOTE_HZ_G3S, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_C4, NOTE_LEN_2BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_A3S, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_C4, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_4BU },
{ NOTE_HZ_D3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_C4, NOTE_LEN_4BU },
{ NOTE_HZ_C4, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_D3, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_E3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_D3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_F3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_A3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_B3, NOTE_LEN_4BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_C3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_E3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_D3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_F3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_A3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_B3, NOTE_LEN_8BU },
{ NOTE_HZ_NONE, NOTE_LEN_8BU },
{ NOTE_HZ_G3, NOTE_LEN_2BU },
{ NOTE_HZ_C3, NOTE_LEN_2BU },
{ NOTE_HZ_A3, NOTE_LEN_2BU },
{ NOTE_HZ_F3, NOTE_LEN_2BU },
{ NOTE_HZ_E3, NOTE_LEN_2BU },
{ NOTE_HZ_C3, NOTE_LEN_2BU },
{ NOTE_HZ_D3, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
{ NOTE_HZ_G3, NOTE_LEN_2BU },
{ NOTE_HZ_C3, NOTE_LEN_2BU },
{ NOTE_HZ_A3, NOTE_LEN_2BU },
{ NOTE_HZ_B3, NOTE_LEN_2BU },
{ NOTE_HZ_C4, NOTE_LEN_2BU },
{ NOTE_HZ_D4, NOTE_LEN_2BU },
{ NOTE_HZ_C4, NOTE_LEN_2_BU },
{ NOTE_HZ_NONE, NOTE_LEN_4BU },
};
#endif /* DOREMI_H_ */
そしてメイン関数。~
メインは短め。~
#include <avr/io.h>
#include "util.h"
#define BPM 140 // テンポ設定
#include "music_def.h"
#include "doremi.h"
int main( void )
{
uint8_t i = 0; // ループ変数
DDRD = 0b01000000; // PD6(OC0A)を出力に設定
PORTD = 0b00000000; // ポートDをLowに初期化
while( 1 ){
for( i = 0; i < sizeof( score ) / sizeof( NOTE ); i++ ){
if( NOTE_HZ_NONE == score[i].hz ){
TCCR0A = 0b00000000; // タイマー停止
} else {
OCR0A = note_hz[score[i].hz]; // 周波数設定
TCCR0A = 0b01000010; // 比較一致トグル出力
TCCR0B = 0b00000010; // 前置分周8
}
delay_ms( note_len[score[i].len] );
}
}
return 0;
}
BPM(テンポ)の定義をしてからmusic_def.hをincludeすることで...
先にincludeしてしまうと、定義が解決出来ないので注意。~
タイマの出力をピンに反映させるためには、ポート方向レジス...
ポートの初期化後に、メインループに入ります。~
無限ループ内に曲のループがあり、音符データ構造体を一つず...
休符設定の時は、タイマを止め、指定音符長だけ待ちます。~
それ以外の時は、比較レジスタ値を設定し、タイマを動作させ...
** 基本動作 [#k21d9ac5]
基本、楽譜通りに鳴らしているだけですが、同じ音が複数続い...
音符の合間で一旦止めているわけではないので当然ですが。~
今回鳴らす音が、次回鳴らす音と同じであれば、数ミリ秒演奏...
意図して繋げたい場合は、スラーを示すフラグを用意するとか…...
あと、もうひとつ、比較レジスタ値を途中で変えていますが、...
このため、場合によっては一瞬(半波長)だけ低い音の周波数の...
圧電スピーカーは音が甲高くて耳につきますね……。~
超小型スピーカーの方がよかったかも。~
ページ名: