# Generar numero aleatorio (0-F) y mostrarlo en display



## bugmenot (May 19, 2008)

Buenas !

Estoy intentando hacer un ejercicio con el 16F84 en el que tengo que generar un numero aleatorio entre 0 y F y que este aparezca en un display...y estoy hecho un lio.

Parece que puede ser algo parecido al dado electronico, pero en vez de entre 1 y 6, debe aparecer entre 0 y F.

Haber si me podeis ayudar un poquilllo, o darme alguna pista para poder conseguirlo.

Muchas gracias !


----------



## Eduardo (May 19, 2008)

Si se trata generar *un* numero a partir de un evento 'humano' (alguien que apreta un pulsador)  lo mas comodo y verdaderamente es tener un contador de frecuencia alta y leerlo cuando se produce el evento.

Si se trata de generar toda una secuencia, generalmente se hace una multiplicacion o division recurrente con numeros grandes, podes sacar algo de las notas de aplicacion de Microchip.


----------



## nichita (May 19, 2008)

Una forma sencilla sería que hagas correr el Timer0 y sólo tomes los 4 primeros bits (0 a F) con una máscara (operación AND 11110000)


----------



## pepechip (May 19, 2008)

Realizas una rutina que te valla sumando de 0 a F, repitiendo indefinidamente este ciclo.
Al accionar un pulsador empieza la secuencia de sumar, y al soltarlo se detiene.
Por lo tanto el numero representado dependera del tiempo que mantegas presionado el pulsador.
Como supongo que el micro correra a 4Mhz, la actuacion del pulsador te provocara un valor aleatorio. No tienes que corregir los rebotes provocados por el pulsador.


----------



## Meta (May 19, 2008)

Deberíamos hacer un recopilatorio de ejercicios con 16F84A para ponerlo todo en un mismo tema.


----------



## bugmenot (May 20, 2008)

Hola de nuevo!

Buff...parece que ando algo perdidillo en el tema, no entiendo muy bien vuestras sugerencias ops:  ops:  ops:  ops:  ops:  ops:  

Partiendo del dado electronico es posible conseguirlo mas facil? o deberia empezar desde 0?

Por cierto, lo tengo que hacer con el simupic (sim84)

De todos modos, muchas gracias por respoder e intentar ayudar

Gracias!


----------



## Vick (May 20, 2008)

Simple, inicias un contador que valla de 0 a F (o de F a 0 que es lo mismo) y cada vez que termine la cuenta vuelva a comenzar, es decir que siempre este corriendo, mediante un pulsador lees el valor que tenga tu contador en el momento que lo presionaste y pasas ese valor al display, como la frecuencia es muy alta (supongo 4MHz) el valor que tenga el contador al momento de presionar el pulsador es totalmente aleatorio.

Puedes hacerlo de varias formas, con un contador programado, con el TMR0, el pulsador mediante  interrupciones...

Saludos.


----------



## bugmenot (May 21, 2008)

Buenas!

He empezado a hacerlo como me a aconsejado Vick. El contador me ha quedado asi: 

;----------------------------------------------------------------------------
    LIST    P=16F84
    RADIX   HEX
;----------------------------------------------------------------------------

    W       EQU     0x00    ; Comienzo del campo de etiquetas.
    F       EQU     0x01
    PUERTAB EQU     0x06
    ESTADO  EQU     0x03
    CONTA   EQU     0x0C

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

    ORG     0               ; El programa comienza en la dirección 0 y
    goto    inicio          ; salta a la dirección 5 para sobrepasar
    ORG     5               ; el vector de interrupción.

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

    inicio  bsf     ESTADO,5    ; Seleciona el banco 1
        movlw   0x00            ; Se configura PuertaB como salida
        movwf   PUERTAB
        bcf     ESTADO,5        ; Selección del banco 0

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

    clrf    CONTA           ; CONTA = 0
    bucle1  incf  CONTA,F   ; CONTA + 1 --> CONTA
        movf    CONTA,W         ; CONTA se carga en W
        movwf   PUERTAB         ; W se carga en el registro de datos PB
        movlw   0xff            ; W <-- 0xff
        subwf   CONTA,W         ; CONTA - W --> W
        btfss   ESTADO,2        ; Explora Z y si vale 1 se produce "brinco"
    goto    bucle1          ; Si Z = 0 se vuelve a bucle1

    bucle2  goto    bucle2  ; si Z = 1 se produce un bucle infinito
    end

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

Tengo un par de dudas, como ago para que cuando termine la cuenta vuelva a empezar?

Como le pongo el pulsador y como lo configuro? Como puedo visualizar ese numero "aleatorio" en el simupic (sim84), con un registro mediante Dir. Hex., o como?

Siento molestar y hacer tanta pregunta, pero estoy mu verde y es un ejercicio que necesito resolver de alguna manera.. ops: 

Muchas gracias a todos!


----------



## Vick (May 21, 2008)

me surge la duda:

¿el ejercicio es generar un número aleatiorio mediante un pulsador o sin intervención del usuario o como?


----------



## bugmenot (May 22, 2008)

Hola!

En principio deberia ser mediante un impulso con el interruptor (I0).

Gracias!


----------



## pic-man (May 22, 2008)

Ese es un ejercicio sencillo. Yo lo haría de la siguiente manera:
-Configuro el timer 0 en modo temporizador, sin precarga y sin preescalador
-Deshabilitar interrupcion de timer 0 (que por default esta deshabilitada) ya que no la necesitamos
-Leer el valor de un interruptor, con btfss es suficiente
-Si se pulsa el interruptor se lee el registro TMR0 (movf TMR0,w) y se enmascara el nibble bajo (andlw 0x0F), con eso ya tomaste el valor del número aleatorio de 0 a F
-Por ultimo decodificas el numero para desplegarlo en un display o LCD o lo que sea que ocupes para mostrar el numero.

Tal vez te puedan servir estos enlaces, el primero es para usar y configurar el timer 0 y el segundo es para controlar un display de 7 segmentos:

http://micropic.wordpress.com/2007/06/24/temporizador-timer-0/
http://micropic.wordpress.com/2007/02/26/displays-de-7-segmentos/

Suerte con tu proyecto!


----------



## bugmenot (May 22, 2008)

pic-man dijo:
			
		

> Ese es un ejercicio sencillo. Yo lo haría de la siguiente manera:
> -Configuro el timer 0 en modo temporizador, sin precarga y sin preescalador
> -Deshabilitar interrupcion de timer 0 (que por default esta deshabilitada) ya que no la necesitamos
> -Leer el valor de un interruptor, con btfss es suficiente
> ...



Iep!

Voy a probar tambien esta opcion que me das...a ver si consigo algo. Que estoy intentando seguir vuestros consejos en diferentes formas de hacerlo, pero en todas me quedo atascado sin saber que hacer y no soy capaz de conseguirlo de ninguna de ellas.

A ver si le empiezo a dar caña, que lo tengo para el lunes y como no me espabile la liare..jeje
Por lo menos gracias a vosotros puedo intentarlo y tener alguna idea de hacerlo...sino...

Muchas gracias!


----------



## Vick (May 22, 2008)

Si estas comenzando con los pics te recomendaría no usar el timer ya que es un poco más dificil, si debes usar un pulsador entonces es bastante facil:

- Inicializa los puertos, el pin RA0 como entrada, que es donde conectaras el pulsador con su resistor de pull-up.
- El puerto B como salida que es donde conactarás el display.
- Inicializa una variable "contador" al cual le cargarás el valor h'0F'
- Crea un bucle en el cual irás decrementando el "contador" y a su vez leeras el valor de RA0 para ver si se ha presionado el pulsador.
- Si se ha presionado el pulsador (si tiene el valor cero) saltará a una subrutina para enviar el valor que tenga "contador" en ese momento al display.
- Mientras no se presione el pulsador (habra un uno en RA0) se sigue decrementando "contador" hasta que llegue a cero, cuando llegue a cero se recarga con h'0F' y así creas un bucle infinito que solo saldrá cuando se presione el pulsador.

Saludos.


----------



## bugmenot (May 23, 2008)

Hola Vick
He decidido pornerme ya ha hacerlo que se me acaba el tiempo, a ver si lo puedo conseguir con tu ayuda.Aqui va lo que he llegado a enterder de lo que me as dicho:

                LISTP=16F84
                RADIX HEX

                PORTA   EQU  0X05  ;PUERTO A
                PORTB   EQU  0X06  ;PUERTO B



			
				Vick dijo:
			
		

> - Inicializa los puertos, el pin RA0 como entrada, que es donde conectaras el pulsador con su resistor de pull-up.
> - El puerto B como salida que es donde conactarás el display.



                BSF                   ESTADO,5         
                MOVWL             B'00000001'     
                MOVWF             PORTA               
                CLRF                 PORTB               
                BCF                   ESTADO,5




			
				Vick dijo:
			
		

> - Inicializa una variable "contador" al cual le cargarás el valor h'0F'


No se como hacerlo.



			
				Vick dijo:
			
		

> - Crea un bucle en el cual irás decrementando el "contador" y a su vez leeras el valor de RA0 para ver si se ha presionado el pulsador.



SALTAR       BTFSS                 PORTA,0
                  GOTO DISPLAY
                  GOTO SALTAR
(Algo mas?)



			
				Vick dijo:
			
		

> - Si se ha presionado el pulsador (si tiene el valor cero) saltará a una subrutina para enviar el valor que tenga "contador" en ese momento al display.
> - Mientras no se presione el pulsador (habra un uno en RA0) se sigue decrementando "contador" hasta que llegue a cero, cuando llegue a cero se recarga con h'0F' y así creas un bucle infinito que solo saldrá cuando se presione el pulsador.


Todavia no lo he hecho, cuando tenga lo anterior bien, seguire con esto, sino me pierdo.

A ver si me puedes ayudar a seguir con ello y puedo conseguir acabarlo para el domingo...

Gracias, muchas gracias!


----------



## Airoa Airon (May 23, 2008)

Tengo este programa que hace eso, con un display anodo comun, es parecido o igual a las recomendaciones que te dieron, date una idea e intenta reescribirlo tu entendiendo lo que dice cada linea.


----------



## bugmenot (May 23, 2008)

Airoa Airon dijo:
			
		

> Tengo este programa que hace eso, con un display anodo comun, es parecido o igual a las recomendaciones que te dieron, date una idea e intenta reescribirlo tu entendiendo lo que dice cada linea.



Buenas Airoa Airon!

En principio al abrir este post nunca fue mi objetivo que alguien me lo diera hecho, pero viendo que el tiempo se me viene encima y que no tengo los suficientes conocimientos como para conseguirlo...te lo agradezco, de verdad, MUCHAS GRACIAS !

Por cierto, al ensamblarlo me salen 2 errores:

Error[125]   C:\...\ANONIMO.ASM 1 : Illegal condition (EOF encountered before END or conditional end directive)
Error[131]   C:\...ANONIMO.ASM 1 : Processor type is undefined

Sobre el 1º he leido algo pero soy incapaz de encontrar el error, el 2º no se a que se refiere..

Ayyy, a ver si lo consigo y dejo de molestaros ya... ops: 

Muchas gracias!


----------



## Vick (May 23, 2008)

Dado que queda poco tiempo te dejo aquí el que yo tengo, hace unas dos semanas acabo de diseñar un dado electrónico con un PIC16F84A y solo tuve que hacer algunas modificaciones para que funcione para tu proyecto.

En este ejemplo tengo el pulsador en el pin RA0 de tal forma que al presionarlo en ese pin habrá un cero y sin presionar un uno.

He utilizado yo un display de cátodo común, aunquue si tienes el de ánodo común solo hay que cambiar los códigos. El display esta conectado a las primeras siete líneas del puerto B.

En el asm estan los comentarios que explican el funcionamiento del programa, si tienes alguna duda dimelo. La simulación la hice en Proteus dado que no tengo ningún PIC en este momento.

Saludos.


----------



## Airoa Airon (May 23, 2008)

No se por que te den esos errores yo lo compile y lo probe y no habia ningun error, debe ser tu compilador y la forma en que hiciste tu proyecto

usas mplab?


----------



## eidtech (May 23, 2008)

hazle el favor completo y mandale el .hex


----------



## bugmenot (May 24, 2008)

Holaa!

Me estoy volviendo loco, uso el simupic(sim84).

Ahora no se que le pasa al programa que al ensamblar me dice:
Checking C:\....\archivo.asm for symbols

y abajo del todo pone:
DOS error: File not found. <0000:014A)

Haber si alguien sabe a que se debe esto...

Muchas gracias a todos!


----------



## bugmenot (May 24, 2008)

Hola de nuevo!

Ya he conseguido medio solucionar el problema

Ya tengo los dos programas, el de Airoa Airon y el de Vick sin ningun error al ensamblar.

He conseguido ver que el contador funciona, poniendo un registro Mediante Dir.Hex. en 0C, segun pasa el tiempo va contando entre 0 y F sin ningun problema. Hasta ahi perfecto!

La cuestion ahora es, como puedo demostrar que funciona correctamente con el simupic? Como va a funcionar eso de darle al pulsador, es decir, como o donde voy a poder darle para que el contador pare y aparezca el numero aleatorio?

Como puedo demostrar que ese numero aleatorio se visualizaria en el display? (No se, el simupic este es muy simple, pero eso de que no sea nada visual hace que me lie)


Bueno, a ver si solucionando estas dudas, lo tengo ya funcionando sin problemas

Graciassssssss!


----------



## bugmenot (May 25, 2008)

bugmenot dijo:
			
		

> Hola de nuevo!
> 
> Ya he conseguido medio solucionar el problema
> 
> ...



Ya he conseguido averiguar como utilizar el pulsador, los pulsadores se encuentran en F1, F2, F3...Al darle se para en el numero aleatorio y al darle otra vez continua la cuenta, hasta volver a pulsar. Perfecto!

Ya se tambien como saber si se visualizaria en el display. Perfecto!

El unico fallo que veo (he usado el programa de Vick arreglando varias cosillas que me daban algun fallo no se porque) es que cuando sale un numero aleatorio (por ejemplo 0011, que seria 3) luego las salidas que activaria en el display son (11011010, que en el display seria 2). Es muy raro,  tiene que ser un error pequeño, pero no averiguo cual puede ser..

Graciaaaaaaaas!


----------



## Vick (May 25, 2008)

Olvidé mencionar ese detalle, el valor de contador si te fijas se inicializa en h'10' (16 decimal) dado que al llegar a cero se recarga inmediatemente, si hubiera inicializado el contador en h'0F' nunca obtendrías el cero, debido a esto.

Así inicializandolo en 10h y al obtener el equivalente en 7 segmentos se decrementa el valor en uno, de esa forma los valores obtenidos van de 0 a F, es por eso que el contador tiene uno más que el valor mostrado en el display, ya que el valor del contador quedará siempre entre 1h y 10h.

Al decrementar el contador en la subrutina siete_seg el valor se almacena directamente en W para enviarlo al puerto B, si quieres obtener el mismo valor en el display y en contador, cambia esta línea de la subritina siete_seg:

*decf contador, 0*

Por:

*decf contador, 1
movf contador, 0*

Saludos.


----------



## bugmenot (May 26, 2008)

Vick dijo:
			
		

> Olvidé mencionar ese detalle, el valor de contador si te fijas se inicializa en h'10' (16 decimal) dado que al llegar a cero se recarga inmediatemente, si hubiera inicializado el contador en h'0F' nunca obtendrías el cero, debido a esto.
> 
> Así inicializandolo en 10h y al obtener el equivalente en 7 segmentos se decrementa el valor en uno, de esa forma los valores obtenidos van de 0 a F, es por eso que el contador tiene uno más que el valor mostrado en el display, ya que el valor del contador quedará siempre entre 1h y 10h.
> 
> ...



Perfecto! Todo funciona bien, muchisimas gracias Vick por toda tu ayuda, sin ti no hubiera conseguido lograrlo

Gracias tb a los demas que han intentado ayudar.

Gracias!


----------



## Vick (May 26, 2008)

Me alegra que por fin pudiste hacerlo funcionar en el simulador que utilizas, realmente no era muy complicado el ejercicio, solo hay que practicar un poco con la programación.

Si tienes más dudas del funcionamiento del programa dinos.

Saludos.


----------

