×
单片机 > 单片机程序设计 > 详情

用AVR单片机8位数据产生随机数

发布时间:2020-05-28 发布时间:
|

源程序:SLAVR737.ASM
用AVR 单片机 8位数据产生随机数,由PORTA 口及PORTC 口输出随机数,在8X8 LED上显示,硬件接线电路见“7.3.8按钮猜数”。随机数的种子由程序设定(也可外接开关设定),启动种子后,由移位寄存器以互斥的异或逻辑组合返回循环产生。

 

.include"8515def.inc"
    rjmp    RESET    
.def    temp    =r16        ;暂存器
.def    temp1    =r17        ;暂存器1
.def    udata    =r21        ;存随机数送A口
.def    ddata    =r22        ;存随机数送C口
.cseg
.org    0x10
RESET:    ldi    temp,high(RAMEND);设堆栈指针
    out    SPH,temp             
    ldi    temp,low(RAMEND)     
    out    SPL,temp
      
        ldi     temp,0xff        ;设A口、C口为输出
        out     ddra,temp        ;送方向寄存器A
        out     ddrc,temp        ;送方向寄存器C
start:  wdr                        ;关看门狗
        ldi     udata,0x6a        ; 设置随机数初值
        ldi     ddata,0x3c        ; 
startp: out     porta,udata        ;输出到A口
        out     portc,ddata        ;输出到C口
        ldi     temp,0x80        ;设延时常数
        rcall   delay            ;调用延时子程序
        rcall   randm            ;调用十六位随机数子程序
        rjmp    startp  
delay:                    ; 通用延时子程序    从略
....
16位移位产生随机数原理图
8~16位移位寄存器产生随机数循环组合
位 数    循环输入组合 S=2^n-1 Qn XOR Qm
   8    Q2 ⊕ Q3 ⊕ Q4 ⊕ Q8 (现程序按钮猜数采用8位数)
   9    Q5 ⊕ Q9
  10    Q7 ⊕ Q10
  11    Q9 ⊕ Q11
  12    Q2 ⊕ Q10 ⊕ Q11 ⊕ Q12
  13    Q1 ⊕ Q11 ⊕ Q12 ⊕ Q13
  14    Q2 ⊕ Q12 ⊕ Q13 ⊕ Q14
  15    Q14 ⊕ Q15
  16    Q4 ⊕ Q13 ⊕ Q15 ⊕ Q16

randm:                            ;产生十六位随机数子程序
   mov   temp,udata        ;产生A口随机数
          mov   temp1,udata        ; 
          rol   temp                ;通过进位位左循环移位
          eor   temp1,temp        ;异或
          rol   temp            ; 通过进位位左循环移位
          rol   temp            ; 通过进位位左循环移位
          eor   temp1,temp    ;异或
          mov   temp,ddata    ; 产生C口随机数
          swap  temp            ; 通过进位位左循环移位
          eor   temp,temp1    ;异或通过进位位左循环移位
          rol   temp            ; 通过进位位左循环移位
          rol   ddata        ; 通过进位位左循环移位
          rol   udata        ; 通过进位位左循环移位
          ret                  ;子程序返回
7.3.8    按钮猜数程序
源程序:SLAVR738.ASM
许多场合如按钮猜数(电脑摇奖,电脑选出幸运号),游戏开始按钮等待一个不规则且不定序的数据产生,即须要随机数发生器。随机数的种子由程序设定(也可外接开关设定),启动种子后,由移位寄存器以互斥的异或逻辑组合返回循环产生。产生随机数的原理图如下:
16位移位产生随机数原理图
8~16位移位寄存器产生随机数循环组合
位 数    循环输入组合 S=2^n-1 Qn XOR Qm
   8    Q2 ⊕ Q3 ⊕ Q4 ⊕ Q8 (现程序按钮猜数采用8位数)
   9    Q5 ⊕ Q9
  10    Q7 ⊕ Q10
  11    Q9 ⊕ Q11
  12    Q2 ⊕ Q10 ⊕ Q11 ⊕ Q12
  13    Q1 ⊕ Q11 ⊕ Q12 ⊕ Q13
  14    Q2 ⊕ Q12 ⊕ Q13 ⊕ Q14
  15    Q14 ⊕ Q15
  16    Q4 ⊕ Q13 ⊕ Q15 ⊕ Q16


以8X8 LED阵列,开机时为了避免被使用者预测出压按时间对应随机数的变化值,故LED字幕以广告动画画面显示,并令随机数随着变化使无法预测随机数起始值,广告动画面共有四张,每张有8位数据。见”org   dpfstb”;

由按钮(PD1)按下,AVR用8位数据产生随机数,由PORTA 口及PORTC 口输出随机数,在8X8 LED上显示好玩的真实的按钮猜数。
.include "8515def.inc"
.def    peed    =r16
.def    DSPn    =r17   ;存显示初始动画次数
.def    temp2   =r18
.def    temp1   =r19
.def    temp    =r20
.def    scndp   =r21 
.def    cnt     =r22
.def    rdata   =r23        ;存随机种子数
.def    rdata9  =r24
.equ    dpfstb  =0x01e0     ;大小矩形图表首址
.equ    randtb  =0x0210     ;随机数种子表首址
.equ    numbertb=0x0240     ;0-9数字表首址
.org  $0000
    rjmp    RESET        ;Reset Handle
.cseg
.org $0010
RESET:  ldi     peed,high(RAMEND)   ;设置堆栈$25F,见器件配置文件"8515def.inc"
        out     SPH,peed
        ldi     peed,low(RAMEND)
        out     SPL,peed
        ldi     peed,0xff    ;对口初始化, 
        out     ddra,peed    ;设A口为输出
        out     ddrc,peed    ;设C口为输出
        ldi     peed,0xfd    ;PD1作输入,且接内部上拉电阻
        out     ddrd,peed    ;PD1为输入,其余为输出
        ldi     peed,0xff    ;关D口
        out     portd,peed
        ldi     peed,0x13    ;显示画面次数
start:  ldi     dspn,0x06    ;显示初始动画
        ldi     zh,high(dpfstb*2)  
        ldi     zl,low(dpfstb*2)  
dspFM:  rcall   ldtb8        ;调用程序区数送到内存RAM
        ldi     temp2,0xa0    ;显示动画面次数
dspfm1: rcall   sCAN1        ;调用从内存取数显示一次
        sbis    PINd,01        ;I/O口的位被置位跳行,检测到PD1按下否
        rjmp    getseed     ; 检测到PD1按下转
        dec     temp2        ;-1
        brne    dspfm1        ;不为0转
        dec     dspn        ; 初始画面次数-1
        brne    dspfm        ; 不为0转
        rjmp    start        ;转到显示初始动画
getseed:inc     temp        ;+`1,根据PD1按下的时间,选择随机数种子
        sbis    pind,01        ; I/O口的位被置位跳行,检测到PD1按下否
        rjmp    getseed        ; 检测到PD1按下,继续计数
        andi    temp,0x1f    ;按钮松开,取随机数种子与0X0F加
        ldi     zh,high(randtb*2)
        ldi     zl,low(randtb*2)
        add     zl,temp
        lpm
        mov     rdata,r0    ;得到随机数种子
next:   ldi     dspn,0x08   ;显示8个不同的随机数;
repeet: rcall   randm        ;调用产生随机数子程序
        rcall   dspnumber    ;调用显示8个不同的随机数
        dec     dspn        ;-1
        brne    repeet        ;dspn不为0转
        rcall   randm        ; 调用产生随机数子程序
guess1: rcall   dspnumber   ;调用显示同一随机数,直到有键按下
        sbIC    pind,01     ;松开后再往下执行(I/O口清零跳行)
        rjmp    guess1         ;转显示同一随机数,直到有键按下
wait:   rcall   dspnumber    ;
        sbis    pind,01
        rjmp    wait         ;等待按钮按下
        ldi     rdata9,0x03         ;显示动画三次
start0: ldi     dspn,0x06           ;每次显示六幅画面
        ldi     zh,high(dpfstb*2)  
        ldi     zl,low(dpfstb*2)  
dspfm0: rcall   ldtb8            ;调用从Z指向的程序区取数据送到内存0080-0087中
        ldi     temp2,0xa0        ;显示次数
dspfm1a:rcall   scan1            ;调用从内存0080-0087中取数据显示一次
        dec     temp2            ;-1
        brne    dspfm1a            ;不为0转
        dec     dspn            ;显示初始动画次数-1
        brne    dspfm0            ;不为0转
        dec     rdata9            ;显示动画三次-1
        brne    start0            ;不为0转
        rjmp    next                ;转显示8个不同的随机数
dspnumber:                         ;显示一个0-9数字的子程序
        ldi     zh,high(numbertb*2)
        ldi     zl,low(numbertb*2)
        add     zl,rdata9
        rcall   ldtb8            ;取数
        ldi     temp2,0xa0       ;该数字重复显示A0H次
dspn1:  rcall   scan1
        dec     temp2
        brne    dspn1
        ret
scan1:  push    xl                 ;从内存0080-0087中取数据显示一次
        ldi     temp,0b01111111
        mov     scndp,temp
        ldi     cnt,0x08
col1:   out     portc,scndp       ;显示屏幕的一列
        ld      r1,x+
        out     porta,r1
        rcall   delay
        sec
        ror     scndp
        dec     cnt
        brne    col1
        pop     xl
        ret
ldtb8:  ldi    xl,0x80     ;从Z指向的程序区取数据送到内存0080-0087中
        ldi    xh,0x00
        ldi    temp1,0x08
        push   xl  
nexld1: lpm
        st     x+,r0
        ld     r0,z+
        dec    temp1
        brne   nexld1
        pop    xl
        ret
delay:           ;通用延时子程序从略
....
randm:  mov    temp,rdata    ;产生8N(0≤N≤9)随机数子程序
        mov    temp1,rdata
        swap   temp1
        eor    temp,temp1
        rol    temp1
        eor    temp,temp1
        rol    temp1
        eor    temp,temp1
        rol    temp
        rol    rdata
        mov    rdata9,rdata
        andi   rdata9,0x0f
        cpi    rdata9,0x0a
        brsh   randm         ;产生了一个0≤RDATA9≤9的随机数
        lsl    rdata9
        lsl    rdata9
        lsl    rdata9
        ret

.cseg
.org      dpfstb;            ;大小方框字形表
;small  o
.db       0b00000000,0b00000000,0b00000000,0b00011000
.db       0b00011000,0b00000000,0b00000000,0b00000000
.db       0b00000000,0b00000000,0b00111100,0b00100100
.db       0b00100100,0b00111100,0b00000000,0b00000000
.db       0b00000000,0b01111110,0b01000010,0b01000010
.db       0b01000010,0b01000010,0b01111110,0b00000000
;big   o
.db       0b11111111,0b10000001,0b10000001,0b10000001
.db       0b10000001,0b10000001,0b10000001,0b11111111
.db       0b00000000,0b01111110,0b01000010,0b01000010
.db       0b01000010,0b01000010,0b01111110,0b00000000
.db       0b00000000,0b00000000,0b00111100,0b00100100
.db       0b00100100,0b00111100,0b00000000,0b00000000
.cseg
.org      randtb               ;随机数种子表
.db       0x5a,0x7b,0x5b,0x4f,0x66,0x6d,0x7d,0x07
.db       0x3b,0x8c,0x67,0x9a,0x99,0x7e,0x2d,0x3e
.db       0x5c,0x6d,0x5b,0x7e,0xf6,0xe7,0x4c,0xc8
.db       0x69,0x9c,0xe2,0x75,0x6c,0xd3,0xe8,0x9a
.cseg
.org      numbertb              ;0-9数字字形表
;0
.db       0b00111000,0b01000100,0b01000100,0b01000100
.db       0b01000100,0b01000100,0b01000100,0b00111000
;1
.db       0b00010000,0b00011000,0b00010000,0b00010000
.db       0b00010000,0b00010000,0b00010000,0b00111000
;2
.db       0b00011100,0b00100010,0b00100000,0b00010000
.db       0b00001000,0b00000100,0b00000010,0b00111110
;3
.db       0b00111100,0b00010000,0b00001000,0b00010000
.db       0b00100000,0b00100000,0b00100010,0b00011100
;4
.db       0b00100000,0b00110000,0b00101000,0b00100100
.db       0b00100010,0b11111110,0b00100000,0b00100000
;5
.db       0b01111110,0b00000010,0b00111110,0b01000000
.db       0b01000000,0b01000000,0b01000010,0b00111100
;6
.db       0b00110000,0b00001000,0b00000100,0b00111100
.db       0b01000100,0b01000100,0b01000100,0b00111000
;7
.db       0b01111100,0b01000000,0b00100000,0b00010000
.db       0b00001000,0b00001000,0b00001000,0b00001000
;8
.db       0b00111000,0b01000100,0b01000100,0b00111000
.db       0b01000100,0b01000100,0b01000100,0b00111000
;9
.db       0b00111000,0b01000100,0b01000100,0b01111000
.db       0b01000000,0b01000000,0b01000100,0b00111000


关键字:AVR单片机  8位数据  随机数 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法