| ??? 11/12/06 04:06 Read: times |
#127800 - Pseudo-Random Number Generator Strangeness |
I'm working on a small project that requires a random number to be generated using the ATMEL AT89C2051 chip. Rather than going ahead and coding/finding an actual pseudo-random number generator I made a realization: I only needed a random number to be generated after a user turned on a pushbutton switch. Therefore, I thought, since the amount of time between each push of the switch will always vary, I could simply keep timer 0 on and read TL0 (only 3 random bits are actually needed) once the user pushes the button. To test my theory I wired up the microcontroller to 3 7-segment displays which would be used to display the random value once a user pushes a switch (P3.0). Here is the code that I made:
#include "8051equ.inc"
.org 00h
ajmp start
.org 0bh
reti
.org 13h
reti
.org 1bh
reti
.org 23h
reti
.org 25h
initialize:
; start timer 0 - 16 bit timer mode
mov TMOD, #01h
setb TR0
mov PSW, #00h
mov IE, #00h
ret
; delay for 1 ms (11.0592 MHz crystal)
delay_ms:
mov r7, #00h
loop_1:
inc r7
mov a, r7
cjne a, #0ffh, loop_1
ret
; 8-bit binary to bcd converter
; a - input value
; r2 - output digit 1
; r3 - output digit 2
; r4 - output digit 3
bin_to_bcd:
mov r2, #00h
mov r3, #00h
mov r4, #00h
mov B, #010d
div ab
mov r4, B
mov B, #010d
div ab
mov r3, B
mov B, #010d
div ab
mov r2, B
ret
display_0:
mov P1, #00001001b
ret
display_1:
mov P1, #11101011b
ret
display_2:
mov P1, #01000101b
ret
display_3:
mov P1, #01100001b
ret
display_4:
mov P1, #10100011b
ret
display_5:
mov P1, #00110001b
ret
display_6:
mov P1, #00010001b
ret
display_7:
mov P1, #01101011b
ret
display_8:
mov P1, #00000001b
ret
display_9:
mov P1, #00100011b
ret
; displays 3 digit BCD number in A register
display_bcd:
cjne a, #00h, check1
acall display_0
ret
check1:
cjne a, #01h, check2
acall display_1
ret
check2:
cjne a, #02h, check3
acall display_2
ret
check3:
cjne a, #03h, check4
acall display_3
ret
check4:
cjne a, #04h, check5
acall display_4
ret
check5:
cjne a, #05h, check6
acall display_5
ret
check6:
cjne a, #06h, check7
acall display_6
ret
check7:
cjne a, #07h, check8
acall display_7
ret
check8:
cjne a, #08h, disp9
acall display_8
ret
disp9:
acall display_9
ret
start:
acall initialize
; set P3.0 to be used as an input
setb P3.0
; wait until switch is pressed
jb P3.0, $
random:
mov a, TL0
; wait for switch to be released
jnb P3.0, $
acall bin_to_bcd
display_loop:
mov a, r2
acall display_bcd
; turn on 7-segment display 1
setb P3.3
acall delay_ms
clr P3.3
mov a, r3
acall display_bcd
; turn on 7-segment display 2
setb P3.4
acall delay_ms
clr P3.4
mov a, r4
acall display_bcd
; turn on 7-segment display 3
setb P3.5
acall delay_ms
clr P3.5
; display same number until switch is pressed
jb P3.0, display_loop
ajmp random
.end
This actually worked. Every time I hit the pushbutton switch connected to P3.0, a new number (between 0 and 255) appeared on the 3 7-segment displays. However, I realized that there was something wrong after pushing the button several (hundred) times. EVERY single number that was displayed was an even number. The first and second 7-segment displays showed both even and odd values but that last one (the LSB) was always 0,2,4,6, or 8. Why is this? Is it just a horrible coincidence (I have pushed the damn thing hundreds of times and it is ALWAYS an even number), or is there something wrong? Thanks in advance for the help and keep in mind that I have only been working with 8051 for ~4 days so go easy. |



