AVR 112 :高周波信号を作る


高周波を作るのは無理か!

 avr単体で周波数を発生させるには「どの程度の周波数まで発生出来るのか」気になりましたので早速調べて見ました。
 これで再利用が出来ます。

 単にON-OFFの信号発生だけですからOUT命令2個とループ命令で実行出来ます。

FRE:
 OUT  PortB,TEMPA
 NOP
 NOP
 OUT  PortB,TEMPB
 RJMP FRE
 TEMPAに0、TEMPBに1を予め入れて置きます、RJMPは2クロック必要ですからデュテイ比が少し狂うのでNOP命令を入れます。

 これで信号は出るはです、全体で6クロックのループですからメインクロックが1MHzなら6μSつまり[166KHz]が信号として取り出せます(10MHzのクロックなら[1.6MHz]です)。

 このプログラムにNOP命令を一つづつ入れると8クロックで8μS(125KHz)が取り出せます。
 これをリストにすると次の様に間に入れるNOP命令を追加すれば、飛び々ですが色々な周波数を作れます。
6ck--166KHz(メインクロックが1MHz)
8ck--125KHz
10ck-100KHz
12ck--83KHz
14ck--71KHz

FRE:
  OUT  PortB,TEMPA	;1ck
  mov  tempc,floop	;1
F2:
  dec  tempc	;1
  brne  F2		;2/1
  NOP			;1
  NOP			;1
  OUT  PortB,TEMPB	;1
  mov  tempc,floop	;1
F3:
  dec  tempc	;1
  brne  F3		;2/1
  RJMP FRE		;2
多種類の周波数を出したい!

 レジスターを使って指定すると広範囲にコントロールが簡単になります、ただ処理スピードはその分低下します。

 実用的には右の様なプログラムが考えられます、基本は前記と同一ですが待ち時間の所をループにして時間調整をしています。

 最短の1(floop=1)が設定されると1回のループでは12クロックが必要になります、2の場合は18クロックとなります、以後6クロックづつ増加します

 このループは待ち時間で数が多いと周波数は下がります。6づつ変化するので初めは元々クロック数が少ないので周波数の決定に大きな影響を与えます。
 滑らかに変化しないのはこの為です、つまり「avrでは限界がある」という事でそれを知って利用すれば良いわけてす。
ループの設定と周波数の関係
FLOOPクロック数周波数(1MHz)
1 回12 (14)クロック83.3 (71.4)KHz
218 (20)55.5 (50.0)
324 (26)41.6 (38.4)
430 (32)33.3 (31.2)
536 (38)27.7 (26.3)
64223.8
74820.8
85418.5
96016.6
1066 (68)15.1 (14.7)
127812.8
149011.1
161029.80 KHz
181148.77
201267.93
301865.37
402464.06
503063.26
100606 (608)1.65 (1.64)
20012060.829 KHz
255 Max15360.651

FLOOPは待ち時間のループ数で周波数が決まります。
クロック数は1回のループで使う数を表します。
周波数=(1/(12+(Ln-1)*6))*メインクロック  :Ln=ループ
()表示の説明は下に入れてますが「特定の端子をアクセスする」場合です。
ここではクロック1MHzで設定しました、10MHzのクロックではこの10倍の周波数が取り出せます。

実用的な出口処理!

 プログラム中にNOPが2つありますがこれの代わりにSWのチエックをさせ、押されていればループを抜け出します。
 通常はSWが押されてないので[SBIS]は2クロックで次の命令を飛ばして進みます。ループを抜け出してもTEMPAに0が設定してあれば L出力でI/O端子には負担が掛からないと思います(必要なら逆にします)。
	SBIS	PinB,EX_SW	;SWのチエック
	rjmp	exit		;押されていれば終了
… 実用的なプログラム …
F1:	CBI  PortB,0		;2ck
	mov  temp,floop	;1
F2:	dec  temp		;1
	brne	F2		;2/1
	SBIS	PinB,E_SW	;2
	RJMP	exit
FRE:	SBI	PortB,0		;2
	mov	temp,floop	;1
F3:	dec	temp		;1
	brne	F3		;2/1
	RJMP	F1		;2
特定の端子をアクセスする場合(上の表カッコ内の数字)

 前記の例はI/Oポート全体を出力(OUT 命令)としてましたが特定の端子をアクセスするSBI/CBIを利用しても良い、この場合クロックは一つの命令に2クロック必要なので1ループで2クロック分増加します。
	CBI	PortB,OP	;クリヤ
	*
	SBI	PortB,OP	;セット
 始めの12クロックが14クロックとなります、こちらもループの設定は1回に対し同じ6クロックで次からも同じ増加です。
 この2クロック分は初め大きく影響しますが次第に変化量は低下し影は薄くなります。

 FREにジャンプすれば信号がPortBの0Bitに出ます、止めたい場合は1Bitに接続されているSW(E-SW)を押せば抜け出せます。
 なお正確に設定したい場合は計算が必要です(クロック数=14+(n-1)*6から逆算して下さい)。
このプログラムを実行させてみました

 手元のIC AT90S1200A(内部発振 5V)で試すと[floop=1の時77KHz](計算では1MHzの時71.4KHz)でした発振周波数が1MHzより少し高い(1.078)様です、[floop=100で1.78KHz](計算 1.64KHz)になりました。
 テスターにおまけとして付いている周波数カウンタで測定しています。
 結果を見ると、このプログラムは「音出し用として簡単な物に」使えます。

 使うにはサブルーチンとしての音出しでしようか、タイマー割込みを組合せて音を止めると複雑な事が出来そうですね。

低周波音の出力は!

 動作はデジタルのON-OFFだけなので高調波を多量に含みます、「低周波の発生器」という使い方は適さないと思いますが、使うには外部に「高調波除去フイルタ」が必要です。

 2004/SEP/12 

;-------------------------------------------------
;Title	:Signal Genarator TEST
;date	:2004/9/11 BY JA1HWO
;-------------------------------------------------
.include "C:\AVRTOOLS\APPNOTES\1200def.inc"

.equ	F_out	=0		;B0
.equ	E_SW	=1		;B1
.def	temp	=r16
.def	floop	=r17

.cseg			;code segment
.org	0
;**** Interrupt Vector Address	****
	rjmp	begin	; Reset
	reti		; Ex 0(input PD-2)
	reti		; Timer 0
	reti		; Analog Comparator
begin:	ldi	temp,1	;B Port set
	out	DDRB,temp	;
	ldi	temp,$FE
	out	PortB,temp	;Pull up

main:	ldi	floop,100	;TEST
	rjmp	FRE
exit:	rjmp	exit	;STOP

F1:	CBI	PortB,F_out	;2ck
	mov	temp,floop	;1
F2:	dec	temp	;1
	brne	F2	;2/1
	SBIS	PinB,E_SW	;2
	RJMP	exit
FRE:	SBI	PortB,F_out	;2
	mov	temp,floop	;1
F3:	dec	temp	;1
	brne	F3	;2/1
	RJMP	F1	;2

[もどる]もどる  [MAIN MENU

inserted by FC2 system