微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 8位单片机随机数

8位单片机随机数

时间:12-03 来源:互联网 点击:
8位单片机很多地方需要随机数,比如游戏的洗牌,可在timer中取数,但是随机数质

量不高。随机数是一个既简单又复杂的问题,这里的例子使用了众所周知的线性叠加法,没

有完美的方法产生随机数,不过线性叠加法是一个合适的方法,彻底解决8位机随机数的问

题。

伪随机数函数总是返回可预知的数字,像抛骰子,如果抛足够多次,那么我们得到了一

个足够长的数字序列,

3,1,5,1,4,6,5,4,6,5,4,5,6,1,3,2,1,6,4,6,5,4,3,2,1,3,2,1,4,2,3,1,3......

如果从序列中一个接一个的取出数字,那么数字就看似随机。

问题的关键是从这序列的哪个点(数字)开始取数?这个开始的点(数字)叫做种子。

注意,如果从相同的点(种子)开始,将会得到相同的数字,这是因为我们是从固定的序

列中取数字(所以叫伪随机)。但这却是一个有用的特性,我们可以每次从不同的点取数,即

改变种子!

在6502上,8位或16位随机数是最常用的,函数返回一个32位的数字,范围0~2^32。名

词"线性叠加"听起来容易范晕, 其实只涉及二个内容:乘法和加法。三个步骤:

1. 为了取得新的种子(也就是从序列开始的那个点的数字),旧的种子和一个常数A相乘,

2. 所得结果然后和第二个常数c相加。

3. 新的种子是结果的低32位(记住,这个函数返回32位数字)。保留低32位很重要,用来获

得下一个种子。

计算公式:

种子 = A * 种子 + C

此公式在几何图中表示一条直线,而且新种子由旧种子反复相加得来,所以叫线性叠加。

随机数函数的关键在于选择优秀的"常数A"(也叫乘数A),其实也就是选择了一个固定

的数字序列。"常数c",不像乘数A那样重要,但是它一定是个奇数。事实上, c可选1,而

且这是例程所使用的,因为它会简化计算。

注意,奇数(旧的种子)乘奇数(乘数A)是奇数,再加奇数(常数c)将会是一个偶数;偶数

(旧的种子)乘奇数(乘数A),加奇数(常数c)将会是一个奇数。如此种子将会在奇数和偶数之

间转变。因为种子的变化足够随机,所以新种子的值可以作为8位或16位随机数。

子程序F_RandomSeed,计算 "种子 = 乘数 * 种子+1" (记得,c=1)。有三个版本:

(1) 快速版本, 速度快,但占用Rom多。

(2) 兼顾版本,速度和占用Rom适中,空间和速度是在另外二个版本之间。

兼顾版B, 使用了另一个神奇的数字66066(10进制).

(3) 最小版本,速度慢,但占用Rom小。

三个版本中使用的乘数1664525(10进制)=19660D(16进制),是从计算机程序的艺术,

第2册>>一书中选出,这是一个神奇的数字,经过论证和测试,这个数字对产生随机数至

关重要。想进一步研究的朋友可以阅读原著(参考资料2),书中以特别专业的数学方法讨论

了随机数问题。这里只是应用了其中的两个常数1664525(10进制)和69069(10进制),这里不

作讨论,因为篇幅问题是借口,其实自己没弄懂。

;==============================================================================

; 快速版本

;==============================================================================

丰收先要选好种子,育种很重要,同样,获得随机种子是重要的一步。

种子变量设定在零页RAM可以提高速度。

程序F_RandomSeed计算 1664525*种子,需要5个字节(R_Seed0~R_Seed3,R_Temp)。

F_GeneratTables预先计算1664525*X(x=0~255),生成四个256字节的列表T3,T2,T1,T0.

T3,X = 表T3的第X字节 = 1664525 * X的第31~24位(X = 0 to 255)

T2,X = 表T2的第X字节 = 1664525 * X的第23~16位(X = 0 to 255)

T1,X = 表T1的第X字节 = 1664525 * X的第15~ 8位(X = 0 to 255)

T0,X = 表T0的第X字节 = 1664525 * X的第 7~ 0位(X = 0 to 255)

对于单片机来说 使用1K RAM很夸张,也可以不用F_GeneratTables,直接把随机数表存

在ROM中。

;==============================================================================

; 伪随机数函数的线性叠加

; 计算 Seed = 1664525 * Seed + 1

;------------------------------------------------------------------------------

; 输入:

; R_Seed0 --- 种子0

; R_Seed1 --- 种子1

; R_Seed2 --- 种子2

; R_Seed3 --- 种子3

; 回返:

; 种子0 ---> R_Seed0

; 种子1 ---> R_Seed1

; 种子2 ---> R_Seed2

; 种子3 ---> R_Seed3

; 重写

; R_Temp

;------------------------------------------------------------------------------

; 为提高速度R_Seed0,R_Seed1,R_Seed2,R_Seed3,R_Temp选零页Ram

; 每张列表从Rom地址 xx00h 处开始 或在Rom中

;------------------------------------------------------------------------------

; 空间: 程序58个字节

;

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top