安全・環境活動に役立つ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に格納される

<Index>

Last Up Date: 2007/6/14