Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: pizz en 14 de Septiembre de 2011, 04:22:04
Título: pregunta de novato
Publicado por: pizz en 14 de Septiembre de 2011, 04:22:04
Hola a todos. Antes de nada, quería agradecerles por toda la información que aquí he venido leyendo desde hace muchísimo tiempo y debo decir que además los tutoriales que he encontrado aquí en assembler han sido muchísimo más fáciles de entender que cualquiera que haya visto en cualquier otro sitio, incluido el libro que me compré y que también gozaba de buena fama. Después de mucho tiempo he decidido empezar activamente a intentar programar algo por mí mismo pero ya me he topado con problemas. El ejemplo es para hacer parpadear un led en el puerto A del 16F84A. Si programo el pic con este programa tal cual está, no hay problema y funciona perfecto. Pero decidí experimentar con los retardos generados por el programita PicDelay y ahí empezaron los problemas porque nunca se apagaba. Así que decidí hacer algo más sencillo que era encender el led, esperar un tiempo y luego apagarlo y que se quedara apagado. Pero nunca se apaga y siempre está encendido. Quisiera que me echaran una mano a ver dónde puedo estar fallando. Muchas grancias de antemano por su tiempo.
Primero les pongo el programa original que hace que el led parpadee:
;*****Establecimiento constantes **** STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro triestado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. CONTADOR1 equ 08h ; Primer contador para nuestros bucles de retardo. CONTADOR2 equ 09h ; Segundo contador para nuestros bucles de retardo. ;;****Configuración del Puerto**** bsf STATUS,5 ; Cambiamos al banco 1Switch to Bank 1 movlw 00h ; Ponemos los pines del puerto A ... movwf TRISA ; ...como salidas. bcf STATUS,5 ; Volvemos al Banco 0. ;;****Encendido del LED **** Inicio movlw 02h ; Encendemos el LED poniendo primero el valor... movwf PORTA ; ... en el registro w y después al puerto; ;****Inicio del buble de retardo 1**** Bucle1 decfsz CONTADOR1,1 ; Restamos 1 a 255. goto Bucle1 ; Si CONTADOR es cero, continuamos. decfsz CONTADOR2,1 ; Restamos 1 a 255 goto Bucle1 ; Volvemos al inicio de nuestro bucle ; Este retardo cuenta hacia atrás ... ; ...desde 255 a 0, 255 veces. ;;****Retardo terminado, ahora apagamos el LED **** movlw 00h ; Apaga el LED poniendo primero el valor ... movwf PORTA ; ... en el registro w y después al puerto
;;****Añadimos otro retardo**** Bucle2 decfsz CONTADOR1,1 ; Este segundo bucle mantiene el LED... goto Bucle2 ; ...apagado el tiempo suficiente... decfsz CONTADOR2,1 ; ...para que lo veamos goto Bucle2 ; ;;****Ahora volvemos al inicio del programa goto Inicio ; Vuelve al principio y enciende el LED... ; ...de nuevo. ;****Termina el Programa**** end ; Algunos compiladores necesitan esta instrucción. ; y también por si acaso olvidamos poner... ; ... la instrucción 'goto'.
=========== Como les digo, este programa anterior funciona perfecto pero si ahora lo único que quiero es que se encienda, cuente un tiempo y al apagarse se quede apagado no soy capaz de hacerlo funcionar. Siempre se queda encendido. Como verán, la única diferencia con el otro, es que cuando acaba de contar el tiempo de encendido, directamente le pongo "end" y el resto del contador de apagado lo dejo comentado con " ; ". A ver qué les parece:
;*****Establecimiento constantes **** STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro triestado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. CONTADOR1 equ 08h ; Primer contador para nuestros bucles de retardo. CONTADOR2 equ 09h ; Segundo contador para nuestros bucles de retardo. ;;****Configuración del Puerto**** bsf STATUS,5 ; Cambiamos al banco 1Switch to Bank 1 movlw 00h ; Ponemos los pines del puerto A ... movwf TRISA ; ...como salidas. bcf STATUS,5 ; Volvemos al Banco 0. ;;****Encendido del LED **** Inicio movlw 02h ; Encendemos el LED poniendo primero el valor... movwf PORTA ; ... en el registro w y después al puerto; ;****Inicio del buble de retardo 1**** Bucle1 decfsz CONTADOR1,1 ; Restamos 1 a 255. goto Bucle1 ; Si CONTADOR es cero, continuamos. decfsz CONTADOR2,1 ; Restamos 1 a 255 goto Bucle1 ; Volvemos al inicio de nuestro bucle ; Este retardo cuenta hacia atrás ... ; ...desde 255 a 0, 255 veces. ;;****Retardo terminado, ahora apagamos el LED **** movlw 00h ; Apaga el LED poniendo primero el valor ... movwf PORTA ; ... en el registro w y después al puerto
end
;;****Añadimos otro retardo**** ;Bucle2 decfsz CONTADOR1,1 ; Este segundo bucle mantiene el LED... ;goto Bucle2 ; ...apagado el tiempo suficiente... ;decfsz CONTADOR2,1 ; ...para que lo veamos ;goto Bucle2 ; ;;****Ahora volvemos al inicio del programa ;goto Inicio ; Vuelve al principio y enciende el LED... ; ...de nuevo. ;****Termina el Programa**** ;end ; Algunos compiladores necesitan esta instrucción. ; y también por si acaso olvidamos poner... ; ... la instrucción 'goto'.
Título: Re: pregunta de novato
Publicado por: AngelGris en 14 de Septiembre de 2011, 09:41:10
Lo que puede estar ocurriendo en tu programa es que se reinicie el pic y vuelva a encender el led.
Antes de la instrucción end pon lo siguiente
Código: ASM
nop; no hace nada
goto $-1; salta a la linea anterior
de esa manera tu programa seguirá corriendo, haciendo nada, y por lo tanto el led permanecerá apagado.
Título: Re: pregunta de novato
Publicado por: pizz en 14 de Septiembre de 2011, 10:10:25
PERFECTO !!!
Muchas gracias, funciona perfectamente. Lo que no entiendo es por qué hay que poner estas dos lineas nuevas. En teoría no debería ser necesario, no?. Es que ayer yo pensé en hacer esto mismo. Bueno realmente esto mismo no, pensé en poner tres o cuatro "nop" seguidos y ver qué pasaba pero ya eran casi las dos de la mañana y estaba hasta las narices. Además pensé que si las instrucciones eran buenas no sería necesario. Normalmente hay que hacer este tipo de instrucciones para que una salida quede apagada?, es que hasta ahora pensaba que no.
Ahora probaré nuevamente a meter el código del programita PicDelay a ver si soy capaz de hacerlo al tiempo de retardo que yo quiero, aunque como dije antes, siempre se me quedaba encendido el led.
Muchas gracias otra vez por haber contestado tan rápido.
Título: Re: pregunta de novato
Publicado por: pizz en 14 de Septiembre de 2011, 12:10:01
Hola otra vez. Es que he estado intentando avanzar un poco más y he querido modificar los tiempos con el PicDelay como dije antes. Ya he conseguido que no se quede siempre encendido si no que ahora ya parpadea bien pero lo que me ocurre es que los destellos van más rápido de lo que deberían. He calculado para 5 segundos y realmente al funcionar el circuito los destellos son cada 700 milisegundos más o menos. Pero es que he hecho la prueba para 1 segundo y va a unos 300 milisegundos o menos. Por si sirve de algo, en el MPLAB tengo configurado el watchdog en off y el oscillator en XT, pero también he probado a cambiarlos pero sigue todo igual. Otra cosa. En el programa PDelay, cuando termina de generar el código, donde dice "Code Requirements" a parte de PDel0, PDel1 y PDel2, también me dice " 1 stack level" pero no sé qué es eso. Alguien me lo puede decir por si es que me falta algo?. Pongo el programa por si me pudieran volver a ayudar. Está calculado para 5000 ms. Gracias de nuevo.
;*****Establecimiento constantes **** STATUS equ 03h ; Dirección del registro STATUS TRISA equ 85h ; Dirección del registro triestado para el Puerto A. PORTA equ 05h ; Dirección del Puerto A. PDel0 equ 08h ; Primer contador para nuestros bucles de retardo. PDel1 equ 09h ; Segundo contador para nuestros bucles de retardo. PDel2 equ 0Ah ; Tercer contador para nuestros bucles de retardo. ; ;****Configuración del Puerto**** bsf STATUS,5 ; Cambiamos al banco 1Switch to Bank 1 movlw 00h ; Ponemos los pines del puerto A ... movwf TRISA ; ...como salidas. bcf STATUS,5 ; Volvemos al Banco 0. ; ;****Encendido del LED **** Inicio movlw 01h ; Encendemos el LED poniendo primero el valor... movwf PORTA ; ... en el registro w y después al puerto ; ;****Inicio del buble de retardo 1****
call PDelay
;****Retardo terminado, ahora apagamos el LED **** movlw 00h ; Apaga el LED poniendo primero el valor ... movwf PORTA ; ... en el registro w y después al puerto
; ;****Añadimos otro retardo****
call PDelay
goto Inicio ; Vuelve al principio y enciende el LED... ; ...de nuevo.
PDelay movlw .165 ; 1 set number of repetitions (C) movwf PDel0 ; 1 | PLoop0 movlw .41 ; 1 set number of repetitions (B) movwf PDel1 ; 1 | PLoop1 movlw .147 ; 1 set number of repetitions (A) movwf PDel2 ; 1 | PLoop2 clrwdt ; 1 clear watchdog clrwdt ; 1 cycle delay decfsz PDel2, 1 ; 1 + (1) is the time over? (A) goto PLoop2 ; 2 no, loop decfsz PDel1, 1 ; 1 + (1) is the time over? (B) goto PLoop1 ; 2 no, loop decfsz PDel0, 1 ; 1 + (1) is the time over? (C) goto PLoop0 ; 2 no, loop return ; 2+2 Done
;****Termina el Programa****
end ; Algunos compiladores necesitan esta instrucción. ; y también por si acaso olvidamos poner... ; ... la instrucción 'goto'.
Título: Re: pregunta de novato
Publicado por: AngelGris en 14 de Septiembre de 2011, 12:19:52
¿Lo estás simulando con el MPLAB, o probando en la vida real?
Según se ve en esos cálculos, sí daría aproximadamente 5 segundos con un cristal de 4Mhz. Si lo estás simulando fijate en las opciones de configurar el oscilador a 4MHz porque de tener otra frecuencia configurada, los tiempos no te van a coincidir.
Título: Re: pregunta de novato
Publicado por: pizz en 14 de Septiembre de 2011, 14:30:27
Lo estoy probando en la vida real. El MPLAB la verdad es que no lo controlo demasiado. Leí que se podía simular directamente en el MPLAB pero la verdad es que no he buscado mucho para ver cómo hacerlo. En el MPLAB he configurado el tema del watchdog y el cristal pero simplemente porque pensé que eso también se grababa en el pic y así si yo no aplicaba bien algún reset al watchdog en el código pues sería como hacerlo por hardware. No sé si tal vez haya alguna opción del MPLAB que haya que configurar antes de compilar aunque la verdad es que algunos ejemplos que bajé de internet y que estaban para parpadear a un tiempo determinado sí que funcionan bien, por eso pensé que algo estaría haciendo yo mal con el PicDelay.
Título: Re: pregunta de novato
Publicado por: BrunoF en 14 de Septiembre de 2011, 15:02:05
Hola
Revisá en el datasheet. Cuando uno empieza con los uC y ensamblador hay que leer hasta el hartazgo las tablas de distribución de todos los tipos de memorias(FLASH,RAM,EEPROM en tu caso).
Estás declarando variables PDel0 equ 08h ; Primer contador para nuestros bucles de retardo. PDel1 equ 09h ; Segundo contador para nuestros bucles de retardo. PDel2 equ 0Ah ; Tercer contador para nuestros bucles de retardo.
En posiciones ilegales para registros de propósito general(GPR) como esos.
La primera posición segura para registros como esos, es la 0x0C. Revisá la FIGURE 2-2 del datasheet del 16F84A, para ver más en detalle esto.
Lamentablemente hay que leer mucho, mucho y ser curioso. La curiosidad es la que lleva a nuevos horizontes.
Saludos.
Título: Re: pregunta de novato
Publicado por: pizz en 14 de Septiembre de 2011, 17:29:49
Ahora si !!!! Como bien decías, el problema venía por haber declarado las variables en esos registros. Los he cambiado a 0xC, 0xD y 0xE y ahora va perfecto. Y he vuelto a probar el primer ejemplo que pregunté para que al apagarse no se volviera a encender y ahora ya no hace falta añadirle las otras dos líneas. La verdad es que me has resuelto varias preguntas con una sola de tus respuestas porque te iba a haber preguntado precisamente por las posiciones de esos registros. El ejemplo que he puesto lo bajé de alguna página y ya venían declaradas ahí las variables y aunque sí que me llamó la atención que las pusieran ahí, como yo realmente no sé nada de esto pues pensé que por algo sería y que estaría bien, pero ya veo que no y que hay que tener más cuidado.
Por lo de leer, te puedo asegurar que llevo muchííísimo tiempo buscando documentación hasta que encontré precisamente en este foro cómo empezar de verdad desde cero con el assembler y los pic y te puedo asegurar que es muchísimo más fácil de entender que muchos tutoriales que me he bajado de muchos sitios e incluso que dos libros que compré y que son famosos precisamente porque dicen que son muy prácticos, pero te aseguro que con los tutoriales de este foro se comprende todo mucho mejor.
Solo me queda volver a agradecerte el tiempo que me has dedicado. Ahora me toca seguir probando con más tiempos y poner tiempos distintos a varias salidas. Probar con interrupciones por pulsador (con retardo para evitar el rebote), etc etc. Finalmente intentaré probar algún circuito para pwm que también me interesa muchísimo para un proyecto que tengo pendiente desde hace casi 3 años.
Saludos.
Título: Re: pregunta de novato
Publicado por: BrunoF en 14 de Septiembre de 2011, 18:04:14
Pues me alegra haber podido ayudar.
Felíz lectura y éxitos!
Título: Re: pregunta de novato
Publicado por: pizz en 22 de Septiembre de 2011, 19:05:47
Hola de nuevo. Hace una semana desde que decidí comenzar con este mundo y debo reconocer que he hecho muchos más progresos de los que pensé que haría. De hecho he pasado por hacer temporizadores que cuentan más o menos tiempo según el pulsador que se presione o incluso me he animado a hacer algún letrero de esos que se ven cuando haces girar la tira de led. Por supuesto que todo esto no habría sido posible sin su ayuda al principio del todo cuando surgen tantas dudas. Muchas gracias!!.
Ahora me he encontrado con un problema. Hasta ahora yo programaba y probaba en una placa de entrenamiento en la que viene todo ya montado pero ahora he intentado montar un circuito completo en una placa protoboard y tengo un problema con el cristal de 4 MHz. El cristal tiene dos patas (el de la placa de entrenamiento tiene 4) y lo pongo entre las patas 15 y 16. Luego pongo dos condensadores de 22pF (uno entre la pata 15 y masa y el otro entre la 16 y masa). Pero al dar tensión al circuito no funciona. He probado haciendo un oscilador R/C y aplicándolo a la pata 16 funciona bien. Incluso he sacado el cristal de 4 patas de la placa de entrenamiento y la he conectado en la protoboard y funciona perfecto. El cristal de 4 patas tiene una conexión a +V, otra a masa, otra es la salida a la pata 16 del PIC y la cuarta no va conectada a ningún sitio.
Alguien me podría dar una pista de lo que puede estar pasando? Muchas gracias. Saludos.
Título: Re: pregunta de novato
Publicado por: BrunoF en 22 de Septiembre de 2011, 19:58:40
De que frecuencia es el cristal de 4 patas que estas usando y que PIC es?
Título: Re: pregunta de novato
Publicado por: AngelGris en 22 de Septiembre de 2011, 20:37:40
¿Como tenés la configuración del oscilador del PIC?
Me da la sensación que puede estar configurado como EXT (externo) y cuando se utiliza cristal de hasta 4MHz debe quedar configurado como XT
Título: Re: pregunta de novato
Publicado por: pizz en 23 de Septiembre de 2011, 04:22:08
Hola. El cristal de 4 patas es de 4 MHz que es el que venía con la placa del entrenador. En el cristal pone: ACTCL j6 BAESJP 4.00 C1A
El cristal nuevo de dos patas lo pedí que fuera de 4MHz y aunque ahora mismo no lo tengo aquí pero cuando me lo dieron y lo miré, recuerdo que ponía algo así como que era de 4 Mhz. El pic es el 16F84A.
Yo creo que no tiene que ver con lo que comenta AngelGris de la configuración porque lo único que he hecho realmente ha sido cambiar un cristal por otro. Bueno y el PIC lo he puesto en una protoboard pero no he hecho cambios de frecuencias ni nada raro como para tener que configuar nada más.
Saludos.
Título: Re: pregunta de novato
Publicado por: pizz en 23 de Septiembre de 2011, 08:41:40
Hola de nuevo. Os doy un dato más por si sirve de algo. He ido hace un momento a la tienda de electrónica donde compré el cristal y le he enseñado el que tengo en la placa del entrenador y le he dicho que quería un cristal de 4 Mhz de 4 patas como el que tengo y me ha dicho que lo que yo tengo de 4 patas no es un cristal, si no un oscilador y por eso lleva una pata para conectar a +V. Así que no sé si es que tal vez haya que conectar alguna pata del PIC a algún sitio concreto o el cristal de dos patas tenga que estar conectado también a +V.
Título: Re: pregunta de novato
Publicado por: AngelGris en 23 de Septiembre de 2011, 09:34:25
Estoy mirando el datasheet -yo estoy viendo el documento DS35007B- en la página 22 que menciona las distintas configuraciones para el oscilador y aparentemente el oscilador externo funcionaría tanto si está configurado en XT, HS o LP.
Lo que me llama la atención es que te funcione con resistencia y capacitor, sin cambiar la configuración. Tal vez pueda ser que no funcioné el pin15 y por lo tanto nunca hará oscilar el cristal.
De todas maneras, ¿Probaste con la configuración en XT o HS?
Título: Re: pregunta de novato
Publicado por: pizz en 27 de Septiembre de 2011, 03:52:45
Hola, perdón por tardar tanto en contestar pero es que he estado fuera y no tenía acceso a internet. La configuración para el oscilador siempre lo he tenido en XT. Probaré con otro micro a ver si pudiera ser lo que comentas del pin15 por si acaso estuviera estropeado.
He podido montar una placa aparte con el oscilador nuevo que compré y funciona perfecto. No es lo mismo que con el cristal y los dos condensadores porque hay que llevarle alimentación y tal, pero bueno, al menos funciona para lo que quiero que es para hacer un letrero de estos que escriben en el aire (POV). Por cierto, que he intentado escribir en el aire la palabra "HOLA" y no soy capaz de leer nada. Solamente veo rayas y puntos. La idea la he sacado de esta página: http://www.neoteo.com/pov-escribe-con-luz-en-el-aire He puesto un delay de 2 ms como indica ahí pero no se llega a entender nada. Voy a seguir probando con distintos delays a ver qué sale.
Muchas gracias por contestar y ya os diré si funciona con otro micro lo del cristal. Saludos.
Título: Re: pregunta de novato
Publicado por: pizz en 02 de Octubre de 2011, 20:20:53
Hola de nuevo. Pues en cuanto a lo del cristal, la verdad es que no hay nada nuevo. He probado con otro pic y tampoco funciona, pero como os dije, al haber comprado un oscilador y funcionar bien con éste, de momento no le doy mucha importancia puesto que me corre más prisa poder terminar un pequeño proyecto que tengo entre manos. Precisamente para ese pequeño proyecto quería pedirles otra vez su ayuda. Les comenté que quería hacer un letrero tipo POV. Pues después de unos cuantos fallos he conseguido avanzar hasta un punto en el que no consigo salir. La idea es que cada vez que yo gire la tira de led aparezca el mismo mensaje unas tres veces, y al contar esas tres veces, aparezca otro mensaje. Pues bien, como es muy cansado hacer pruebas cada vez con el circuito haciéndolo girar porque he estado depurando muchas muchas veces, decicí hacer pruebas en el entrenador de pic's que les comenté que tenía. Lo que hago es que de la tira de 8 led, primero hago que corran los 4 de la derecha y cuando hayan corrido 3 veces, entonces que corran los de la izquierda otras 3 veces, y luego vuelta a empezar o a otro tipo de secuendia. En principio la cosa no es muy complicada porque no lo he hecho con rrf ni rlf ni nada de eso. De hecho, la secuencia de la derecha funciona perfecta. El problema es con la secuencia de la izquiera que nunca sale de ese bucle y he estado muchas horas intentando averiguar qué pasa pero no consigo salir de ahí. Quería ponerles el código por si me pudieran echar una mano. No sé por qué "CONTA2" nunca llega a cero y así volver al principio del todo a poner los dos registros a cero nuevamente. Gracias y saludos.
; prueva para pov 4 primeros led y despues los otros 4 para intentar hacer ciclo de conteo. ;*****Establecimiento constantes **** STATUS equ 03h TRISB equ 86h PORTB equ 06h PDel0 equ 0Ch PDel1 equ 0Fh PDel2 equ 0Dh CONTA1 equ 0Eh CONTA2 equ 0Fh ; ;****Configuración del Puerto**** bsf STATUS,5 ; Cambiamos al banco 1Switch to Bank 1 movlw 00h ; Ponemos los pines del puerto B ... movwf TRISB ; ...como salidas. bcf STATUS,5 ; Volvemos al Banco 0.