This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

how to generate random number?

Does anybody know how to generate random number using 8051?

  • From the keil help books/files:-

    #include <stdlib.h>
    int rand (void);
    Description:
    The rand function generates a pseudo-random number between 0 and 32767.

    Return Value:
    The rand function returns a pseudo-random number.

    Is this what you want? if not it should be fairly easy for you to scale the returned value to whatever range you need. Alternativly for eg. go here http://www.agner.org/random/ for further info/theory/code on coding a pseudo random number generator or http://www.programmersheaven.com/zone5/cat27/30104.htm seems to have code for an asm version which you may find useful.

    Mark :-)

  • You might find this thread helpful:

    http://www.keil.com/forum/docs/thread3202.asp

    I understand that the very latest version of Keil rand() is based on this method.

    Of course, no pseudo-random number generation method is truly random and each method has advantages and disadvantages. Perhaps you could tell us a little more about what you need your random numbers for.

  • Thanks for giving advice.
    However my code runs on 8051 and i just want to generate an integer from 1 to 127. Since there are many methods to do that and my MCU is out of code memory, is there a shortest code that can do it? Thanks very much.

  • Here is a very small 16-bit LFSR based pseudo random number generator and it is about as basic as you can get.

    #include <REG52.H>
    
    //
    //  Masks for 8-bit galios LFSR maximum run length generator
    //
    //  8 stages, 4 taps:  (6 sets)
    //
    //  [8, 7, 6, 1]
    //  [8, 7, 5, 3]
    //  [8, 7, 3, 2]
    //  [8, 6, 5, 4]
    //  [8, 6, 5, 3]
    //  [8, 6, 5, 2]
    //
    //  [8, 7, 6, 1] =
    //
    //    3                   2                   1                   0
    //  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    //  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1
    //
    //  0 0 0 0 0 0 0 0  = 0xE1
    //
    //  Masks for 16-bit galios LFSR maximum run length generator
    //
    // 16 stages, 8 taps:  (406 sets)
    //
    //  [16, 15, 14, 13, 12, 11, 10, 4]
    //  [16, 15, 14, 13, 12, 11, 9, 8]
    //  [16, 15, 14, 13, 12, 11, 9, 6]
    //  [16, 15, 14, 13, 12, 11, 9, 5]
    //  [16, 15, 14, 13, 12, 11, 8, 2]
    //  [16, 15, 14, 13, 12, 11, 5, 2]
    //  [16, 15, 14, 13, 12, 10, 9, 5]
    //  [16, 15, 14, 13, 12, 10, 5, 1]
    //  [16, 15, 14, 13, 12, 9, 8, 7]
    //  [16, 15, 14, 13, 12, 9, 7, 1]
    //  [16, 15, 14, 13, 12, 9, 6, 3]
    //  [16, 15, 14, 13, 12, 9, 6, 2]
    //  [16, 15, 14, 13, 12, 9, 3, 2]
    //  [16, 15, 14, 13, 12, 8, 4, 1]
    //  [16, 15, 14, 13, 12, 7, 6, 4]
    //  [16, 15, 14, 13, 12, 6, 5, 3]
    //  [16, 15, 14, 13, 12, 6, 5, 2]
    //  [16, 15, 14, 13, 12, 6, 3, 2]
    //  [16, 15, 14, 13, 12, 5, 4, 3]
    //  [16, 15, 14, 13, 12, 5, 3, 2]
    //  [16, 15, 14, 13, 11, 10, 8, 4]
    //  [16, 15, 14, 13, 11, 10, 6, 1]
    //  [16, 15, 14, 13, 11, 10, 5, 4]
    //  [16, 15, 14, 13, 11, 10, 3, 1]
    //  [16, 15, 14, 13, 11, 9, 8, 5]
    //  [16, 15, 14, 13, 11, 9, 8, 2]
    //  [16, 15, 14, 13, 11, 9, 7, 4]
    //  [16, 15, 14, 13, 11, 9, 7, 3]
    //  [16, 15, 14, 13, 11, 9, 6, 5]
    //  [16, 15, 14, 13, 11, 9, 6, 4]
    //  [16, 15, 14, 13, 11, 9, 6, 1]
    //  etc...
    //
    //  [16, 15, 14, 13, 11, 9, 6, 1] =
    //
    //    3                   2                   1                   0
    //  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    //  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 1 0 0 1 0 0 0 0 1
    //
    //  1 1 1 1 0 1 0 1  = 0xF5
    //  0 0 1 0 0 0 0 1  = 0x21
    //
    
    #pragma ASM
    
    $REGUSE small_rand( PSW, A, R7 )
    
    #pragma ENDASM
    
    static data unsigned int lfsr = 0xA5A5;
    
    unsigned char small_rand()
    {
    
        #pragma ASM
                                        ;
            MOV     R7,#8               ;
                                        ;
    ?random_loop:                       ;
                                        ;
            CLR     C                   ;
            MOV     Acc,lfsr+0          ;
            RRC     A                   ;
            MOV     lfsr+0,A            ;
            MOV     Acc,lfsr+1          ;
            RRC     A                   ;
            MOV     lfsr+1,A            ;
                                        ;
            JNC     ?random_x           ;
                                        ;
            XRL     lfsr+0,#0xF5        ;
            XRL     lfsr+1,#0x21        ;
                                        ;
    ?random_x:                          ;
                                        ;
            DJNZ    R7,?random_loop     ;
                                        ;
        #pragma ENDASM
    
        return( (unsigned char) lfsr );
    }
    
    And a test harness:
    extern unsigned char small_rand();
    
    main()
    {
        data  unsigned int loop;
    
        data  unsigned int v,target;
    
        xdata unsigned int a[256];
    
        loop = 256;
    
        do
        {
    
             a[ loop ] = 0;
    
        } while( --loop != 0 );
    
        target = small_rand();
    
        loop = 0;
    
        do
        {
    
            v = small_rand();
    
            a[ v % 256 ]++;
    
            if( v == target )
            {
                target = v;
            }
    
        } while( ++loop != 0 );
    }
    
    I have not had time to test this fully, but it seems to work OK.

    It is possible to have an LFSR that is just 8-bits long, but the shorter the LFSR the less random the results are. If you let us know what the numbers are needed for, we may be able to offer more helpful advice.

    The LFSR implemented above is a 16-bit Galois implementation. See here for a very helpful web-site: http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm#Table%20of%20M-Sequence%20Feedback%20Taps

  • "my MCU is out of code memory"

    Would simply using the time be sufficently "random" for your purpose?

    Is there some external event/signal that would give you an essentially random number?
    eg, the time a user presses some button (any button - doesn't have to be a "generate random number" button), or the instantaneous value of some analogue signal, or some unrelated count, or...

  • I have had a quick look at the pseudo-random number generator here: http://www.programmersheaven.com/zone5/cat27/30104.htm

    It looks as if it is a Fibonacci implementation of a 32-bit LFSR. Fibonacci implementations are common in hardware, but in software they are more complex (and slower) than Galois (prononced Gal-whar) implemenations.

    In software, Fibonacci implementation become more complex as the number of taps increases whereas Galios implementation can implement any number of taps without any extra complexity. In general, a large number of taps is desirable because it makes the output "more random".

  • As you just want numbers 0..127, why not just use a lookup table - so each "call" to rand() just returns the next entry?

  • As you just want numbers 0..127, why not just use a lookup table - so each "call" to rand() just returns the next entry?

    But, Ivan said that he was out of code memory.

    Ivan: if you are really desparate for space, it would be possible to implement an 8 or 7 bit LFSR. The advantage of a 7-bit LFSR is that it would give you values in the range 1..127 without any further processing. On the other hand the sequence would not be very random - you will get all the values 1..127 exactly once before the sequence repeats. If that is what you want, I can probably write a generator in about five minutes!