|
发表于 2018-3-3 23:42:49
|
显示全部楼层
本帖最后由 shouzama 于 2018-3-4 17:03 编辑
當初庫相衝時,我也發現了是它們動用到同一個計時器所造成,
要重寫 IR_REMOTE 或 TONE? 我覺得應該是 TONE 比較簡單,
上網找了一些資料後(因為資料比較雜,已記不得資料來源),
我自己寫了個函式,並且跟 TONE 進行比較,微調常數、修改程式...
反覆測試多次後,完成了取代 TONE 的自製函式
以下是我的測試程式(程式碼是基於 TONE 的範例程式進行修改
做成),可以在 BZ 硬體接線完成的狀態下,先上傳這個程式試試看
自製函式跟 TONE 函式聲音是否明顯不同(我是聽不出來有明顯差別 ^^" ):
==========================
#include <Pitches.h> //這份 .h 的音符定義檔我有重新改過,必要時請修改 melody 陣列定義內容
//定義 NOP (虛工指令)
#define NOP do { __asm__ __volatile__ ("nop"); } while (0)
#define SPEAKER 11 //定義喇叭接腳
//小蜜蜂 = 62
int melody[]= { Note_G5, Note_E5, Note_E5, 0, Note_F5, Note_D5, Note_D5, 0,
Note_C5, Note_D5, Note_E5, Note_F5, Note_G5, Note_G5, Note_G5, 0,
Note_G5, Note_E5, Note_E5, 0, Note_F5, Note_D5, Note_D5, 0,
Note_C5, Note_E5, Note_G5, Note_G5, Note_E5, 0,
Note_D5, Note_D5, Note_D5, Note_D5, Note_D5, Note_E5, Note_F5, 0,
Note_E5, Note_E5, Note_E5, Note_E5, Note_E5, Note_F5, Note_G5, 0,
Note_G5, Note_E5, Note_E5, 0, Note_F5, Note_D5, Note_D5, 0,
Note_C5, Note_E5, Note_G5, Note_G5, Note_C5, 0 };
int noteDurations[]={ 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 2, 2,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 2, 2 };
//撰寫自己的延時函式(以奈秒計)
void delayNANO( unsigned long NANO ) //無回傳值,引數 NANO 為延時奈秒值
{
for (unsigned long I=0; I< (unsigned int) (NANO*1.3) ; I++)
{ NOP; }
}
//撰寫自己的響音函式,引數:喇叭接腳定義 SPEAKER_PIN,音頻定義 FREQUENCY,節拍定義 TEMPO
void sz_tone( int SPEAKER_PIN, int FREQUENCY, unsigned long TEMPO )
{
pinMode( SPEAKER_PIN, OUTPUT); //定義喇叭接腳為輸出用
unsigned long CYCLE = 1000000/FREQUENCY; //一開始CYCLE*1000倍提高換算精確度,算出週期時間
unsigned long LOOP = ( TEMPO*1000 / CYCLE); //迴圈數(多=時間長)=分子*1000倍調回正常比例
if ( FREQUENCY == 0) //若頻率值為 0 (休止符)則延遲 TEMPO 時間不發聲
delay( TEMPO );
else //若頻率值不為 0 (非休止符) 則發聲
{
for ( unsigned long I=0; I < LOOP; I++ ) //發聲時間長短由 LOOP 設定
{
digitalWrite( SPEAKER_PIN, HIGH ); //發聲音
delayNANO( CYCLE/2 ); //延時1/2週期
digitalWrite( SPEAKER_PIN, LOW ); //不發聲音
delayNANO( CYCLE/2 ); //延時1/2週期
}
}
delay( int ( TEMPO*0.3 )); //暫停(音符間的區隔)
}
void setup()
{
}
void loop()
{
//先用自己寫的函式演奏小蜜峰,共 62 音符(含休止符)
for (int thisNote = 0; thisNote < 62; thisNote++)
{
int noteDuration = 1000 / noteDurations[thisNote];
sz_tone(SPEAKER, melody[thisNote], noteDuration); //函式內已內建音符區隔的暫停
}
delay(2000);
//再用標準 tone 函式演奏
for (int thisNote = 0; thisNote < 62; thisNote++)
{
// to calculate the note duration, take one second divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / noteDurations[thisNote];
tone( SPEAKER, melody[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(SPEAKER);
}
delay(2000);
}
==========================
函式已實測修正過 ^^ |
|