安全・環境活動に役立つLEDイルミネーションの製作 Q&A
007. 乱数を作る方法はありませんか?
サンプルプログラムでは、オプションレジスタ(OPTION_REG)に80Hの値が設定されており、タイマ0(8ビットタイマモジュール)が既に動いています。このタイマ0のカウント値は、高速に変化しており、その値を適宜読み取って乱数を作る方法があります。
まず、タイマ0のカウンタ値を読み取り、8ビットレジスタの下位4ビットに詰めておきます。(下記のプログラムでは、読み取った値の上位4ビットと下位4ビットをSWAPF命令で入れ替え、AND演算で下位4ビットを残す方法をとっています。場合によって、残す位置を改める必要があります。) 次に、1から6までの乱数を発生させるには、残された値を6倍します。(実際には、足し合わせを6回行っています。) 6倍した後は、SWAPF命令で上位4ビットと下記4ビットの入れ替えを行い、AND演算で下位4ビットを残します。最後に1を加えて、1以上の数とします。この手順を具体的な例で表すと、次のようになります。
例1)
1-0) タイマ0のカウント値が 0000 1001B であったとする
1-1) SWAPF命令で入れ替えが行われて 1001 0000B
1-2) AND演算によって下位4ビットを取り出し 0000 0000B (10進で0)
1-3) 6倍して 0000 0000B (10進で0)
1-4) SWAPF命令で入れ替えを行って 0000 0000B
1-5) AND演算によって下位4ビットを取り出し 0000 0000B (10進で0)
1-6) 1を加算して 0000 0001B (10進で1)
例2)
2-0) タイマ0のカウント値が 1111 1001B であったとする
2-1) SWAPF命令で入れ替えが行われて 1001 1111B
2-2) AND演算によって下位4ビットを取り出し 0000 1111B (10進で15)
2-3) 6倍して 0101 1010B (10進で90)
2-4) SWAPF命令で入れ替えを行って 1010 0101B
2-5) AND演算によって下位4ビットを取り出し 0000 0101B (10進で5)
2-6) 1を加算して 0000 0110B (10進で6)
<乱数を発生させるためのサブルーチン例>
*動作の検証は行っていません。バグがありましたら連絡下さい。
RAND MOVLW D'6' ;1から6の乱数を発生させる場合、こちらで6を指定(最大15まで可能) MOVWF UA ;UA=6 SWAPF TMR0,0 ;タイマ0のカウンタ値上位4ビットと下位4ビットを入れ替え、Wレジスタに格納する ANDLW 0FH ;Wレジスタの下位4ビットを取り出し、Wレジスタに格納 CLRF UB ;UBをゼロクリア RAND02 ADDWF UB,1 ;UB=UB+W DECFSZ UA,1 ;UA=UA-1, UAが0でなければRAND02へジャンプ GOTO RAND02 SWAPF UB,1 ;UBの値上位4ビットと下位4ビットを入れ替え、Wレジスタに格納する ANDLW 0FH ;Wレジスタの下位4ビットを取り出し、Wレジスタに格納 ADDLW 01H ;Wレジスタに1を加える RETURN
実際にこのルーチンを利用するには、以下のようにCALL命令で先頭ラベルRANDを呼び出し、Wレジスタに格納された値を引き出します。
CALL RAND ;サブルーチンRANDの呼び出し MOVWF UC ;Wレジスタに格納された乱数がUCに格納される
Last Up Date: 2007/6/14