1kHzの正弦波をDDSで発生
アナデバのAD9833 を発注したんですが、手元にある部品だけでさっと作られないかと、試してみました。
ここで、DDSでの周波数関係を調べていると、「19.6608MHz」の水晶(シリアル通信ボーレート発生用として一般的)を使うと、「1Hz」単位の制御が割り切れるぞということが判明。
となります。
# ±120で作成 1024データ
BEGIN{
pai = atan2(0, -1) # π = 3.14の値
for(i = 0; i < 1024; i++){ # 1024データ
if((i % 10) == 0){ # 1行に10データ
n = i
c = 0
printf("\t")
}
printf("%4d,", 120*sin(((i / 1024) * 360) * pai / 180))
c++
if((i % 10) == 9){ # 10個目出力完了
printf("\t// %d\n", n)
}
}
while(c < 10){ # 最後の行
printf(" ")
c++
}
printf("\t// %d\n", n)
}
// 中央値:128 振幅±120
const PROGMEM int8_t sin_tbl[]={
0, 0, 1, 2, 2, 3, 4, 5, 5, 6, // 0
7, 8, 8, 9, 10, 11, 11, 12, 13, 13, // 10
14, 15, 16, 16, 17, 18, 19, 19, 20, 21, // 20
21, 22, 23, 24, 24, 25, 26, 27, 27, 28, // 30
29, 29, 30, 31, 32, 32, 33, 34, 34, 35, // 40
-10, -9, -8, -8, -7, -6, -5, -5, -4, -3, // 1010
-2, -2, -1, -0, // 1020
};
// DDD処理を実行
// dds_cntの上位16bit中10bitでサインテーブルを読み出す
SIGNAL(TIMER1_COMPA_vect)
{
int16_t d; // ±の値で
PB0_H; // (!!!) 14pin
dds_cnt += dds_step; // DDSカウンタをカウントアップ
d = (int16_t)((int8_t)pgm_read_byte(&sin_tbl[(dds_cnt >> 16) & 0x03FF]));
// 0~1023でsin波形テーブルをアドレス
d = d * dds_vol; // 出力ゲイン *0~*256
d = d / 256; // MSBを使う
PORTD = d + 128; // 128がD/A出力の中央値
PB0_L; // (!!!) 14pin
}
HになっているのがDDS処理の実行部分。
この割り込み処理、どんなふうにコード展開されているか見てみると・・・
668: 1f 92 push r1 PUSH,POPは2クロックで実行
66a: 0f 92 push r0
66c: 0f b6 in r0, 0x3f
66e: 0f 92 push r0
670: 11 24 eor r1, r1
672: 2f 93 push r18
674: 3f 93 push r19
676: 4f 93 push r20
678: 5f 93 push r21
67a: 6f 93 push r22
67c: 7f 93 push r23
67e: 8f 93 push r24
680: 9f 93 push r25
682: af 93 push r26
684: bf 93 push r27
686: ef 93 push r30
688: ff 93 push r31
------------------------------------------
68a: 28 9a sbi 0x05, 0 PB0テストパルス
68c: 80 91 11 01 lds r24, 0x0111 DDSカウント値
690: 90 91 12 01 lds r25, 0x0112
694: a0 91 13 01 lds r26, 0x0113
698: b0 91 14 01 lds r27, 0x0114
69c: 40 91 17 01 lds r20, 0x0117 DDSステップ値
6a0: 50 91 18 01 lds r21, 0x0118
6a4: 60 91 19 01 lds r22, 0x0119
6a8: 70 91 1a 01 lds r23, 0x011A
6ac: 84 0f add r24, r20 カウント値に
6ae: 95 1f adc r25, r21 ステップ値を加算
6b0: a6 1f adc r26, r22
6b2: b7 1f adc r27, r23
6b4: 80 93 17 01 sts 0x0117, r24
6b8: 90 93 18 01 sts 0x0118, r25
6bc: a0 93 19 01 sts 0x0119, r26
6c0: b0 93 1a 01 sts 0x011A, r27
6c4: cd 01 movw r24, r26 SIN波テーブルアドレス計算
6c6: aa 27 eor r26, r26
6c8: bb 27 eor r27, r27
6ca: 93 70 andi r25, 0x03
6cc: aa 27 eor r26, r26
6ce: bb 27 eor r27, r27
6d0: fc 01 movw r30, r24
6d2: e4 58 subi r30, 0x84
6d4: ff 4f sbci r31, 0xFF
6d6: 64 91 lpm r22, Z 8bit SIN波テーブル読み出し
6d8: 40 91 1f 01 lds r20, 0x011F
6dc: 50 91 20 01 lds r21, 0x0120
6e0: 64 03 mulsu r22, r20 VOLUME値を乗ずる
6e2: 90 01 movw r18, r0
6e4: 65 9f mul r22, r21
6e6: 30 0d add r19, r0
6e8: 11 24 eor r1, r1
6ea: 37 ff sbrs r19, 7
6ec: 02 c0 rjmp .+4 ;0x6f2
6ee: 21 50 subi r18, 0x01
6f0: 3f 4f sbci r19, 0xFF
6f2: 83 2f mov r24, r19
6f4: 80 58 subi r24, 0x80 +128して2.5V中心に出力
6f6: 8b b9 out 0x0b, r24 D/A出力
6f8: 28 98 cbi 0x05, 0 PB0テストパルス
------------------------------------------
6fa: ff 91 pop r31
6fc: ef 91 pop r30
6fe: bf 91 pop r27
700: af 91 pop r26
702: 9f 91 pop r25
704: 8f 91 pop r24
706: 7f 91 pop r23
708: 6f 91 pop r22
70a: 5f 91 pop r21
70c: 4f 91 pop r20
70e: 3f 91 pop r19
710: 2f 91 pop r18
712: 0f 90 pop r0
714: 0f be out 0x3f, r0
716: 0f 90 pop r0
718: 1f 90 pop r1
71a: 18 95 reti
| 固定リンク
| コメント (0)
| トラックバック (0)
最近のコメント