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.
See this thread also: http://www.keil.com/forum/docs/thread2325.asp
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 ); }
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 ); }
"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!