Per a la generació de números aleatoris podem fer servir la funció Random que dona resultats de 16 bits. En realitat, es tracta d'un generador de nombres pseudo-aleatoris, per tant comença amb un valor inicial (llavor) i va generant una seqüència a partir d'ella. El funcionament es basa en una rotació de LED cap a l'esquerra en la que, per la dreta, s'entra un bit que s'ha generat a partir dels bits de la llavor. El valor generat serà la llavor per a la següent vegada. El següent gràfic (on el símbol ⊕ representa la funció o exclusiva) ens mostra com funciona. La funció o exclusiva dona 1 si els dos bits d'entrada són diferents i zero si són iguals.

En el programa següent generem, a cada cicle, un valor aleatori i en mostrem els quatre bits menys significatius als LED.
PROCESSOR 16F690 #include <xc.inc> config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
Rand EQU 0x20 ; Dos bytes on guardarem el valor aleatori (2 bytes) Auxrand EQU 0x22 ; Variable auxiliar per a Random (2 bytes) Retard1 EQU 0x24 ; Variables de retard Retard2 EQU 0x25 Retard3 EQU 0x26
PSECT code, class=CODE, delta=2, abs main: bsf RP0 ; Tria el banc 1 movlw 11110000B ; Posa les potes que corresponen als LED com a sortida movwf TRISC ; la resta del port C com a entrada bcf RP0 ; Tria el banc 0 movlw 01010101B ; Agafa un valor concret movwf Rand ; Ho posa com a llavor movwf Rand+1 ; Ho posa com a llavor clrf PORTC ; Apaga els LED Bucle: call Random ; Genera un valor aleatori movf Rand,w ; Llegeix el valor aleatori movwf PORTC ; I ho posa als LED movlw 5 ; Retard d'1 s call Rets goto Bucle ; Repetim-ho...
;
; Funció que genera valors aleatoris
;
Random:
clrf Auxrand ; Posa a zero les variables auxiliars
clrf Auxrand+1 ; Posa a zero les variables auxiliars
; Rand+1: 15 14 13 12 11 10 9 8
; Rand: 7 6 5 4 3 2 1 0
rlf Rand+1,w ; Roda a l'esquerra i deixa el resultat a W
; Rand+1: 15 14 13 12 11 10 9 8
; W: 14 13 12 11 10 9 8 X
xorwf Rand+1,w ; Fa un xor amb l'original i deixa el resultat a W
movwf Auxrand+1 ; El bit de l'esquerra serà la xor del 14 i el 15
swapf Rand+1,f ; Permuta els nibbles
; Rand+1: 11 10 9 8 15 14 13 12
; Rand: 7 6 5 4 3 2 1 0
swapf Rand,w ; Guarda els nibbles permutats a W
movwf Auxrand ; Auxrand: 3 2 1 0 7 6 5 4
bcf CARRY ; Entrarem un zero
rlf Auxrand,f ; Hem rodat a l'esquerra, ara el bit 3 és a C
btfsc CARRY ; Si C és zero no fem res
bsf Auxrand,0 ; Si C és 1, activem el bit de la dreta
; Auxrand: 2 1 0 7 6 5 4 3
; Rand+1: 11 10 9 8 15 14 13 12
; Rand: 7 6 5 4 3 2 1 0
movf Auxrand,w ; Copia Auxrand a W
xorwf Rand+1,w ; El bit de la dreta de W serà la xor de 3 i 12
swapf Rand+1,f ; Ho torna a deixar com estava
; Rand+1: 15 14 13 12 11 10 9 8
; Rand: 7 6 5 4 3 2 1 0
andlw 00000001B ; Posa w a zero excepte el bit de la dreta
rlf Auxrand+1,f ; Agafem el bit de l'esquerra i el posem a C
; Aquest bit era la xor del 14 i el 15
rlf Rand,f ; Rodem Rand a l'esquerra entrant el bit que volem per la dreta
xorwf Rand,f ; Li fem una xor amb W que afecta només al bit de la dreta
rlf Rand+1,f ; Rodem Rand+1 a l'esquerra entrant el bit que ha sortit de Rand
return
Rets: ; Funció de retard de 0,2 W s
movwf Retard3
Bucles:
decfsz Retard1,f
goto Bucles
decfsz Retard2,f
goto Bucles
decfsz Retard3,f
goto Bucles
return
END main
Si provem el programa, hauríem d'obtenir una seqüència que pot semblar aleatòria però que és la mateixa cada cop que tornem a posar en marxa el microcontrolador. Això passa perquè aquesta funció el que fa és generar nombres pseudoaleatoris. Per aconseguir millors resultats, cal definir una llavor que sigui diferent cada vegada, així la seqüència serà diferent cada cop. El següent programa agafa com a llavor el valor de TMR0 que sempre està variant.
PROCESSOR 16F690 #include <xc.inc> config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
Rand EQU 0x20 ; Dos bytes on guardarem el valor aleatori (2 bytes) Auxrand EQU 0x22 ; Variable auxiliar per a Random (2 bytes) Retard1 EQU 0x24 ; Variables de retard Retard2 EQU 0x25 Retard3 EQU 0x26
PSECT code, class=CODE, delta=2, abs
main:
bsf RP0 ; Tria el banc 1
movlw 11110000B ; Posa les potes que corresponen als LED com a sortida
movwf TRISC ; la resta del port C com a entrada
movlw 10000000B ; Configuració de Timer0
; Com a temporitzador basat en rellotge
; 000 - Factor d'escala de 2
; I resistències de pull-up desactivades (valor per defecte)
movwf OPTION_REG ; Ho guarda
bcf RP0 ; Tria el banc 0
movf TMR0,w ; Agafa el valor de TMR0
movwf Rand+1 ; Ho posa com a llavor
swapf TMR0,w ; Agafa el valor permutat de TMR0
movwf Rand ; Ho posa com a llavor
clrf PORTC ; Apaga els LED
Bucle:
call Random ; Genera un valor aleatori
movf Rand,w ; Llegeix el valor aleatori
movwf PORTC ; I ho posa als LED
movlw 5 ; Retard d'1 s
call Rets
goto Bucle ; Repetim-ho...
;
; Funció que genera valors aleatoris
;
Random:
clrf Auxrand ; Posa a zero les variables auxiliars
clrf Auxrand+1 ; Posa a zero les variables auxiliars
; Rand+1: 15 14 13 12 11 10 9 8
; Rand: 7 6 5 4 3 2 1 0
rlf Rand+1,w ; Roda a l'esquerra i deixa el resultat a W
; Rand+1: 15 14 13 12 11 10 9 8
; W: 14 13 12 11 10 9 8 X
xorwf Rand+1,w ; Fa un xor amb l'original i deixa el resultat a W
movwf Auxrand+1 ; El bit de l'esquerra serà la xor del 14 i el 15
swapf Rand+1,f ; Permuta els nibbles
; Rand+1: 11 10 9 8 15 14 13 12
; Rand: 7 6 5 4 3 2 1 0
swapf Rand,w ; Guarda els nibbles permutats a W
movwf Auxrand ; Auxrand: 3 2 1 0 7 6 5 4
bcf CARRY ; Entrarem un zero
rlf Auxrand,f ; Hem rodat a l'esquerra, ara el bit 3 és a C
btfsc CARRY ; Si C és zero no fem res
bsf Auxrand,0 ; Si C és 1, activem el bit de la dreta
; Auxrand: 2 1 0 7 6 5 4 3
; Rand+1: 11 10 9 8 15 14 13 12
; Rand: 7 6 5 4 3 2 1 0
movf Auxrand,w ; Copia Auxrand a W
xorwf Rand+1,w ; El bit de la dreta de W serà la xor de 3 i 12
swapf Rand+1,f ; Ho torna a deixar com estava
; Rand+1: 15 14 13 12 11 10 9 8
; Rand: 7 6 5 4 3 2 1 0
andlw 00000001B ; Posa w a zero excepte el bit de la dreta
rlf Auxrand+1,f ; Agafem el bit de l'esquerra i el posem a C
; Aquest bit era la xor del 14 i el 15
rlf Rand,f ; Rodem Rand a l'esquerra entrant el bit que volem per la dreta
xorwf Rand,f ; Li fem una xor amb W que afecta només al bit de la dreta
rlf Rand+1,f ; Rodem Rand+1 a l'esquerra entrant el bit que ha sortit de Rand
return
Rets: ; Funció de retard de 0,2 W s
movwf Retard3
Bucles:
decfsz Retard1,f
goto Bucles
decfsz Retard2,f
goto Bucles
decfsz Retard3,f
goto Bucles
return
END main
Aquest programa va bé si reprogramem el microcontrolador sense desconnectar-lo. Però si desconnectem el microcontrolador i el tornem a connectar és probable que la seqüència es repeteixi. El motiu és que el temps que triga en fer les instruccions prèvies és sempre el mateix o sigui que si l'apago i el torno a engegar, el valor de TMR0 que dóno és sempre igual. En el programa següent afegim un detall que li dona una aleatorietat pràcticament total ja que no es llegirà el valor de TMR0 fins que l'usuari hagi premut el polsador i després l'hagi deixat anar. Hem afegit un retard abans de mirar el polsador ja que el programador (que comparteix pota amb el polsador) pot interferir amb la lectura del polsador durant els primers microsegons.
PROCESSOR 16F690 #include <xc.inc> config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
Rand EQU 0x20 ; Dos bytes on guardarem el valor aleatori (2 bytes) Auxrand EQU 0x22 ; Variable auxiliar per a Random (2 bytes) Retard1 EQU 0x24 ; Variables de retard Retard2 EQU 0x25 Retard3 EQU 0x26
PSECT code, class=CODE, delta=2, abs
main:
bsf RP0 ; Tria el banc 1
movlw 0xFF ; Posa l'acumulador a FFh (tot uns)
movwf TRISA ; Posa tots els bits del port A com a entrada
movlw 11110000B ; Posa les potes que corresponen als LED com a sortida
movwf TRISC ; la resta del port C com a entrada
movlw 10000000B ; Configuració de Timer0
; Com a temporitzador basat en rellotge
; 000 - Factor d'escala de 2
; I resistències de pull-up desactivades (valor per defecte)
movwf OPTION_REG ; Ho guarda
bcf RP0 ; Tria el banc 0
clrf PORTC ; Apaga els LED
movlw 10 ; Retard de 2 s
call Rets
btfsc PORTA,3 ; Mira si està desactivada l'entrada A3
; Si està desactivada, no fa la instrucció següent
; Fa la instrucció si l'entrada està activada
goto $-1 ; Si no està premut, espera
btfss PORTA,3 ; Mira si està activada l'entrada A3
; Si està activada, no fa la instrucció següent
; Fa la instrucció si l'entrada està desactivada
goto $-1 ; Si està premut, espera
movf TMR0,w ; Agafa el valor de TMR0
movwf Rand+1 ; Ho posa com a llavor
swapf TMR0,w ; Agafa el valor permutat de TMR0
movwf Rand ; Ho posa com a llavor
Bucle:
call Random ; Genera un valor aleatori
movf Rand,w ; Llegeix el valor aleatori
movwf PORTC ; I ho posa als LED
movlw 5 ; Retard d'1 s
call Rets
goto Bucle ; Repetim-ho...
;
; Funció que genera valors aleatoris
;
Random:
clrf Auxrand ; Posa a zero les variables auxiliars
clrf Auxrand+1 ; Posa a zero les variables auxiliars
; Rand+1: 15 14 13 12 11 10 9 8
; Rand: 7 6 5 4 3 2 1 0
rlf Rand+1,w ; Roda a l'esquerra i deixa el resultat a W
; Rand+1: 15 14 13 12 11 10 9 8
; W: 14 13 12 11 10 9 8 X
xorwf Rand+1,w ; Fa un xor amb l'original i deixa el resultat a W
movwf Auxrand+1 ; El bit de l'esquerra serà la xor del 14 i el 15
swapf Rand+1,f ; Permuta els nibbles
; Rand+1: 11 10 9 8 15 14 13 12
; Rand: 7 6 5 4 3 2 1 0
swapf Rand,w ; Guarda els nibbles permutats a W
movwf Auxrand ; Auxrand: 3 2 1 0 7 6 5 4
bcf CARRY ; Entrarem un zero
rlf Auxrand,f ; Hem rodat a l'esquerra, ara el bit 3 és a C
btfsc CARRY ; Si C és zero no fem res
bsf Auxrand,0 ; Si C és 1, activem el bit de la dreta
; Auxrand: 2 1 0 7 6 5 4 3
; Rand+1: 11 10 9 8 15 14 13 12
; Rand: 7 6 5 4 3 2 1 0
movf Auxrand,w ; Copia Auxrand a W
xorwf Rand+1,w ; El bit de la dreta de W serà la xor de 3 i 12
swapf Rand+1,f ; Ho torna a deixar com estava
; Rand+1: 15 14 13 12 11 10 9 8
; Rand: 7 6 5 4 3 2 1 0
andlw 00000001B ; Posa w a zero excepte el bit de la dreta
rlf Auxrand+1,f ; Agafem el bit de l'esquerra i el posem a C
; Aquest bit era la xor del 14 i el 15
rlf Rand,f ; Rodem Rand a l'esquerra entrant el bit que volem per la dreta
xorwf Rand,f ; Li fem una xor amb W que afecta només al bit de la dreta
rlf Rand+1,f ; Rodem Rand+1 a l'esquerra entrant el bit que ha sortit de Rand
return
Rets: ; Funció de retard de 0,2 W s
movwf Retard3
Bucles:
decfsz Retard1,f
goto Bucles
decfsz Retard2,f
goto Bucles
decfsz Retard3,f
goto Bucles
return
END main

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.