TODOPIC
Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: chicho en 26 de Mayo de 2010, 23:00:09
-
Hola a todos, me presento mi nombre es Nestor y soy aficionado principiante a la programacion de Pic.
Esoy queriendo dar mis primeros pasos en programar Pic y he comenzado por lo que creo es el inicio obligatorio del que no conoce nada, "Encender un Led usando un pulsador"
Tan mal no me fue ya que leyendo en el foro otros ejemplos creo haber comprendido las instrucciones minimas necesarias del Pic 16f84 como para logralo y simularlo en Proteus con exito.
Pero quise ir un poco mas alla y es entonces cuando se me presenta el siguiente problema, mi intencion es que el Led encienda recien despues de haber oprimido 10 veces el pulsador
por si no fui claro es algo asi: oprimo 1 ves no enciende, oprimo 2 veces no enciende, pero cuando oprima por decima ves si enciende.
Esto es lo que hice
Declare una variable en uno de los Registros de Propositos Generales
Cont equ 0x0C
Luego coloque un 10 en Cont
movlw .10
movwf Cont
Luego fui restando 1 a Cont en un bucle hasta llegar a cero
decfsz Cont, 1
El codigo quedo asi
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Led equ 0
Boton equ 0
Cont equ 0x0C ; Aqui declaro Cont
;**** Configuracion de puertos ***
Reset org 0x00
goto Inicio
org 0x05
Inicio bsf STATUS,RP0
movlw b'11111'
movwf TRISA
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0
movlw .10 ; Aqui cargo W con 10
movwf Cont ; Paso 10 a Cont
bcf PORTB,Led
;**** Control de Led ****
Bucle btfsc PORTA,Boton
goto Bucle
decfsz Cont,1 ; Decremento Cont en 1
goto Bucle ; Cont no es = 0
bsf PORTB,Led ; Cont = 0
end
Se que esta mal porque lo simulo en Proteus y no funciona como quiero, intente colocando una demora en el pulsador pero no funciono y la quite.
Estaria muy agradecido si alguien me puede orientar en cual es el error que cometi, desde ya muchas gracias.
Una pregunta mas "cuando se usa goto y cuando se usa call?"
-
Hola Nestor, lo primero bienvenido al foro, mira para empezar te dire que la temporizacion del pulsador no la puedes quitar a no ser que montes un circuito antirrebotes, ya que la vibracion de la lamina del pulsador la cuenta como pulsacion. Lo segundo ten en cuenta que la instruccion de exploracion del bit 0 de la puerta A no es lo mismo si estas esperando un 0 o un 1, por ejemplo la instruccion btfsc salta (brinca) si vale 0 depende del esquema que tengas montado, lo que seria lo mismo de si se enciende el led al darle los 5V o en cambio se enciende al darle 0V.
Saludos
Miquel_S
-
.
Antes que nada, permitime felicitarte porque aunque recién estás empezando, escribís programas muy claros :smiley:
El problema es este: cuando apretás un pulsador, aunque seas súmamente hábil con las manos, no hay forma de seas más rápido que el PIC.; entonces, si en el código no esperás a que el pulsador vuelva a su estado "no apretado" después de decrementar Cont, volvés a Bucle y te encontrás conque el pulsador sigue activado, entonces decrementás otra vez y así hasta que el led se enciende, y solo lo pulsaste una sola vez.
Entonces la solución es esperar a que el pulsador vuelva a estar en 1 lógico antes de cerrar el bucle. También con indispensables rutinas de retardo que mantengan ocupado al uC mientras pasan los rebotes, así que colocá unas de aprox. 50ms (podría ser menos, pero ya que en esta ocasión no es tan importante el control de tiempo, mejor asegurarse) antes leer el estado del pulsador.
-
como te dice mtristan, lo que tu debes verificar es el proceso de apretar y liberar el pulsador, y lo que actualmente haces es solo ver si esta pulsado.
Para hacer esto debes ayudarte de un bit auxiliar como si fuera una bandera que te indique el estado anterior del pulsador, y luego cuando vuelves a ver en que estado esta actualmente el pulsador lo comparas con esta bandera y si sigue igual es que no ha cambiado de estado, entonces solo cuando cambia de estado, ya sea porque lo pulsas o porque lo liberas (solo en una de las dos condiciones) ahi recien decrementas el contador.
Hace tiempo que no programo en ASM, despues si tengo un ratito veo si incluyo algo en el código que has hecho tu.
Con respecto al uso del "goto" y del "call", pues como regla practica que yo tengo, es tratar de no usar el goto, porque pierdes el hilo del programa.
Es mas aconsejable usar "call" para el llamado a subrutinas, pero recuerda que el stack es solo de 8 niveles.
Para el caso tuyo de este programita, esta bien el uso del "goto" porque es el bucle principal.
Tambien puedes usar "goto" si estas haciendo algun retardo.
-
Desde ya muchas gracias a "willynovi, mtristan y Miquel_S" por sus consejos y por responder tan pronto.
Ya estoy trabajando en el nuevo código y ni bien lo tenga probado y simulado lo subire para pedir nuevos consejos si es que algo me sale mal.
Nuevamente agradezco la colaboración del foro.
-
Bueno, gracias a los acertados consejos aportados por "willynovi, mtristan y Miquel_S" he salido adelante con los problemas que se habian presentado en este código.
En la rutina agregue algunas lines de código para generar una demora despues de oprimir el pulsador para eliminar el efcto rebote del pulsador y algunas lineas mas para
testear no solo si el pulsador se oprimio sino tambien para saber si lo solte.
La rutina de la demora es del tipo anidada y quedo asi:
Declaro 2 variables para poder lograr una demora de 50 milisegundos
Temp1 equ 0x0D
Temp2 equ 0x0E
;**** Control de Demora ****
Demora movlw .255 ; Cargo W con 255 en decimal (1 ciclo de maquina)
movwf Temp1 ; Muevo 255 a Temp1 (1 ciclo de maquina)
Dloop1 movlw .65 ; Cargo W con 65 en decimal (1 ciclo de maquina)
movwf Temp2 ; Muevo 65 a Temp2 (1 ciclo de maquina)
Dloop2 decfsz Temp2,1 ; Decremento en 1 Temp2 (si Temp2 >0 1 ciclo, si Temp2 =0 2 ciclos)
goto Dloop2 ; Temp2 >0 entonces vuelvo a Dloop2 (2 ciclos de maquina)
decfsz Temp1,1 ; Decremento en 1 Temp1 (si Temp1 >0 1 ciclo, si Temp1 =0 2 ciclos)
goto Dloop1 ; Temp1 >0 entonces vuelvo a Dloop1 (2 ciclos de maquina)
return ; Vuelve al control del Led (2 ciclos de maquina)
Según mis calculos esta es una demora de 50 milisegundos aproximadamente, me gustaria si alguien puede calcularla nuevamente para saber si es correcta.
Y este es el código terminado y simulado correctamente en Proteus.
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Boton equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
Cont equ 0x0C ; Asigno a Cont la posicion 0x0C del Registro de Propositos Generales
Temp1 equ 0x0D ;
Temp2 equ 0x0E ;
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Cargo 11111 en W.-
movwf TRISA ; Muevo 11111 a TRISA.-
movlw b'11111110' ; Cargo 11111110 en W
movwf TRISB ; Muevo 11111110 a TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
movlw 0x0A ; Cargo 10 en W
movwf Cont ; Muevo 10 a Cont
bcf PORTB,Led ; Comienza apagado.-
;**** Control de Led ****
Bucle btfsc PORTA,Boton ; Preguntamos si esta en 0 logico (si esta pulsado).-
goto Bucle ; Esta a 1 logico (no esta pulsado).-
call Demora ; llamo a una demora de 50 ms
btfss PORTA,Boton ; Preguntamos si esta en 1 logico (si ya lo solte)
goto Bucle
decfsz Cont,1 ; Decremento Cont hasta que llegue a 0 y salte a encender el Led
goto Bucle
bsf PORTB,Led ; Enciendo el Led
goto Bucle
;**** Control de Demora ****
Demora movlw .255 ; Cargo W con 255 en decimal (1 ciclo de maquina)
movwf Temp1 ; Muevo 255 a Temp1 (1 ciclo de maquina)
Dloop1 movlw .65 ; Cargo W con 65 en decimal (1 ciclo de maquina)
movwf Temp2 ; Muevo 65 a Temp2 (1 ciclo de maquina)
Dloop2 decfsz Temp2,1 ; Decremento en 1 Temp2 (si Temp2 >0 1 ciclo, si Temp2 =0 2 ciclos)
goto Dloop2 ; Temp2 >0 entonces vuelvo a Dloop2 (2 ciclos de maquina)
decfsz Temp1,1 ; Decremento en 1 Temp1 (si Temp1 >0 1 ciclo, si Temp1 =0 2 ciclos)
goto Dloop1 ; Temp1 >0 entonces vuelvo a Dloop1 (2 ciclos de maquina)
return ; (2 ciclos de maquina)
end
Bueno, no me queda mas que agradecer y seguir practicando para aprender.
Muchas gracias a todos. :-/
-
Felicidades, ya has dado otro paso en la programacion de Pic,s
Sigue adelante y a por otro proyecto.
Miquel_S