2017-07-05 80 views
0

私はArduinoプログラミングにはかなり新しいです。私はしばらくの間コーディングしています。私は現在、Arduino IDEとDigispark Attiny85開発ボードを使って多声ピアノをコーディングしようとしています。一度に複数の音符を再生するには、サインテーブルと高速PWMを使用しています。これは私のコードです:Attiny85タイマ割り込みでグローバル変数を使用する

int val = 1; 
uint8_t C = 0; 
uint8_t D = 0; 
uint8_t E = 0; 
uint8_t F = 0; 
uint8_t G = 0; 
uint8_t A = 0; 
uint8_t B = 0; 

static uint8_t sin_C[123] = {16,16,17,18,19,20,20,21,22,23,23,24,25,25,26,27,27,28,28,29,29,30,30,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30,29,29,28,28,27,27,26,25,25,24,23,23,22,21,20,20,19,18,17,16,16,15,14,13,12,11,11,10,9,8,8,7,6,6,5,4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,6,6,7,8,8,9,10,11,11,12,13,14,15,15}; 
static uint8_t sin_D[110] = {16,16,17,18,19,20,21,22,23,23,24,25,26,26,27,28,28,29,29,30,30,30,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30,29,29,28,27,27,26,25,25,24,23,22,21,20,20,19,18,17,16,15,14,13,12,11,11,10,9,8,7,6,6,5,4,4,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,5,5,6,7,8,8,9,10,11,12,13,14,15,15}; 
static uint8_t sin_E[98] = {16,17,18,19,20,21,22,23,23,24,25,26,27,27,28,29,29,30,30,31,31,31,31,31,31,31,31,31,31,31,30,30,30,29,28,28,27,26,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,5,4,3,3,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,4,5,6,7,8,8,9,10,11,12,13,14,15}; 
static uint8_t sin_F[92] = {16,17,18,19,20,21,22,23,24,25,26,27,27,28,29,29,30,30,31,31,31,31,31,31,31,31,31,31,30,30,30,29,28,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,3,2,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,4,5,6,7,8,9,10,11,12,13,14,15}; 
static uint8_t sin_G[82] = {16,17,18,19,20,22,23,24,25,26,27,28,28,29,30,30,31,31,31,31,31,31,31,31,31,30,30,29,29,28,27,26,25,24,23,22,21,20,19,17,16,15,14,12,11,10,9,8,7,6,5,4,3,2,2,1,1,0,0,0,0,0,0,0,0,0,1,1,2,3,3,4,5,6,7,8,9,11,12,13,14,15}; 
static uint8_t sin_A[73] = {16,17,18,20,21,22,24,25,26,27,28,29,29,30,31,31,31,31,32,31,31,31,31,30,29,29,28,27,26,25,24,22,21,20,18,17,16,14,13,11,10,9,7,6,5,4,3,2,2,1,0,0,0,0,0,0,0,0,0,1,2,2,3,4,5,6,7,9,10,11,13,14,15}; 
static uint8_t sin_B[65] = {16,17,19,20,22,23,24,26,27,28,29,30,30,31,31,31,32,31,31,31,30,30,29,28,27,26,24,23,22,20,19,17,16,14,12,11,9,8,7,5,4,3,2,1,1,0,0,0,0,0,0,0,1,1,2,3,4,5,7,8,9,11,12,14,15}; 

ISR(TIMER0_COMPA_vect) { 
    C++; 
    D++; 
    E++; 
    F++; 
    G++; 
    A++; 
    B++; 
    if(C>122) { 
    C = 0; 
    } 
    if(D>109) { 
    D = 0; 
    } 
    if(E>97) { 
    E = 0; 
    } 
    if(F>91) { 
    F = 0; 
    } 
    if(G>81) { 
    G = 0; 
    } 
    if(A>72) { 
    A = 0; 
    } 
    if(B>64) { 
    B = 0; 
    } 
    int values[7] = {sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]}; 
    OCR0A = values[val]; 
} 

void setup() { 
    DDRB |= (1<<PB0); 
    TCNT0 = 0; 
    TCCR0A=0; 
    TCCR0B=0; 
    TCCR0A |=(1<<COM0A1); 
    TCCR0A |=(1<<WGM01); 
    TCCR0A |=(1<<WGM00); 
    TCCR0B |= (1 << CS00); 
    OCR0A=254; 
    TIMSK |= (1<<OCIE0A); 
} 

void loop() { 
} 

は現在、私は、この行は、それがコンパイルされていても動作しません。つまり、私が果たすべき注意かを制御するために変数を使用することはできませんよ。

OCR0A = values[val]; 

valは私が設定したグローバル変数です。

これを行うか、私はライン以前Attiny85はそれのようなDの和音がすべき出力1を述べたため

OCR0A = values[1] + values[3] + values[5]; 

に置き換える場合と同じ効果を達成するために特定の方法がある場合、私は思ったんだけど。しかし、私はノートがボタンによって制御されるようにしたいので、プログラムが実行されているときにそれらを変更できるようにする必要があり、グローバル変数がそれを考える唯一の方法です。どんな解決策も大いに感謝されるでしょう。

+0

誰かが尋ねる前に何も変わらない揮発性タグを追加しようとしました。 – Mattasdqwe

答えて

0

グローバル変数を使用することは、メインプログラムループと割り込みハンドラ間でデータをやりとりする唯一の方法です。

この回答を書いているうちに、サインテーブルで符号付きの値を使用することを検討する必要があることがわかりました。数学が正しく機能するためには署名付き加算が必要です。

このライン:

OCR0A = values[val]; 

のみモノラルサウンドを作り出すことができます。

あなたはこれで正しい道にいる:しかし

int values[7] = {sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]}; 

だから、はい、別のグローバルVaRはトリックを行う必要があります:私はOCR_RANGEとOCR_ZEROを追加しました

ISR(TIMER0_COMPA_vect) 
{ 
    //... 

    int values[7] = {sin_C[C],sin_D[D],sin_E[E],sin_F[F],sin_G[G],sin_A[A],sin_B[B]}; 

    int ocr_value = 0; 
    for (unsigned char mask = 1, i = 0; mask < 0x80; mask <<= 1, ++i) 
    { 
     if (mask & note_played) 
      ocr_value += (signed char)(values[i] - 16); // hints that using signed values 
                 // in sine tables may be more 
                 // efficient. 
    } 

    // need to 'clip' OCR here? 
    if (ocr_value < -(OCR_RANGE/2)) 
     ocr_value = -(OCR_RANGE/2); 
    if (ocr_value > (OCR_RANGE/2)) 
     ocr_value = (OCR_RANGE/2); 

    OCRA0 = (unsigned char)((ocr_value + OCR_ZERO) & 0xFF); 
} 

、AC電圧範囲に制御します

unsigned char notes_played; // bits 0-7 map C-D notes 

そして、あなたのISRで

フィルタリングされた出力の範囲:0〜255。 (OCR_RANGE = 256がオーバーフローする可能性があります)。 OCR_ZEROはミッドレンジポイント(通常は127)を制御しますので、setup()で初期OCRA0をOCR_ZEROに設定する必要があります。

最後のメモ。本当に音質に大きな違いを作ることができますできるだけ速く、できるだけ大きな正弦テーブルを作る

static uint8_t sin_B[65] =  //... This gets store in data space, which is limited 
static const uint8_t sin_B[65] = //... This gets stored on flash, which has plenty of room. 

、および割り込み:あなたのサインテーブルを宣言するとき。

関連する問題