??? 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. |