TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: ECHEARANJUEZ en 13 de Abril de 2013, 19:40:04
-
El programa genera un pulso de 12us cada 60ms, lo que necesito es interrumpir ese pulso cuando halla un pulso en RB0 que se encienda un led en el puerto RB1, pero no logro que se ejecute la interrupción correctamente. agradecería cualquier ayuda.
; PIC16F887 Configuration Bit Settings
#include "p16F887.inc"
; CONFIG1
; __config 0xEFF1
__CONFIG _CONFIG1, _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _IESO_ON & _FCMEN_ON & _LVP_OFF
; CONFIG2
; __config 0xFFFF
__CONFIG _CONFIG2, _BOR4V_BOR40V & _WRT_OFF
; CONFIGURAR REGISTROS
temporal1 EQU 0X23
temporal2 EQU 0X24
PDel0 EQU 0X21
PDel1 EQU 0X22
ORG 0X00
GOTO INIT
ORG 0X04
GOTO INTERRUPCION
INIT
;*********************************
;*CONFIGURACION DE PUERTOS y de la interrupciones
;*********************************
ORG 0X05
banksel TRISB ;Pasamos al banco 1
MOVLW B'11111101' ; RB0 COMO ENTRADA
MOVWF TRISB
CLRF TRISA ;configura PORTA todo como salida
CLRF TRISE ; PUERTO A COMO SALIDA
CLRF TRISC ;PUERTO C COMO SALIDA
banksel ANSELH ;vamos al banco 3
CLRF ANSELH ;ENTRADAS DIGITALES
CLRF ANSEL
BANKSEL PORTA
;BORRAR PUERTOS
CLRF PORTA
CLRF PORTB
CLRF PORTC
CLRF PORTD
;CONFIGURACION INTERRUPCIONES
BANKSEL OPTION_REG
MOVLW B'01000000'
MOVWF OPTION_REG
MOVLW B'10010000'
MOVWF INTCON
BANKSEL PORTA
Inicio
call TRIGER
goto Inicio
;*********************************
;*CONFIGURACION DEl disparo para el ultrasonido, BUCLE INFINITO
;*********************************
TRIGER
BSF PORTA,0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BCF PORTA,0
CALL DELAY_60MS
GOTO TRIGER
;RUTINA RETARDOS
DELAY_60MS
movlw .66 ; 1 set numero de repeticion (B)
movwf PDel0 ; 1 |
PLoop1 movlw .181 ; 1 set numero de repeticion (A)
movwf PDel1 ; 1 |
PLoop2 clrwdt ; 1 clear watchdog
clrwdt ; 1 ciclo delay
decfsz PDel1, 1 ; 1 + (1) es el tiempo 0 ? (A)
goto PLoop2 ; 2 no, loop
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ? (B)
goto PLoop1 ; 2 no, loop
clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
;*********************************
;*Servicio de rutinas de interrupción
;*********************************
INTERRUPCION MOVWF temporal1
MOVF STATUS,W
MOVWF temporal2
BTFSC INTCON,INTF ;salta si la interrupción no es interna
GOTO INT_RBO
FIN_INTER
MOVF temporal2,w
movwf STATUS
MOVF temporal1,w
BCF INTCON,INTF
retfie
INT_RBO
BTFSS PORTB,1
GOTO ENCENDER
GOTO APAGAR
ENCENDER
BSF PORTB,1
GOTO FIN_INTER
APAGAR
BCF PORTB,1
GOTO FIN_INTER
END
-
Para poder ayudarte deberías poner más información la primera que máquina utilizas y segundo el hardware que estas utilizando.
-
El programa genera un pulso de 12us cada 60ms, lo que necesito es interrumpir ese pulso cuando halla un pulso en RB0 que se encienda un led en el puerto RB1, pero no logro que se ejecute la interrupción correctamente. agradecería cualquier ayuda.
; CONFIGURAR REGISTROS
temporal1 EQU 0X23
temporal2 EQU 0X24
PDel0 EQU 0X21
PDel1 EQU 0X22
ORG 0X00
GOTO INIT
ORG 0X04
GOTO INTERRUPCION
ORG 0X05
INIT
;*********************************
;*CONFIGURACION DE PUERTOS y de la interrupciones
;*********************************
banksel TRISB ;Pasamos al banco 1
MOVLW B'11111101' ; RB0 COMO ENTRADA
MOVWF TRISB
BCF OPTION_REG,6
CLRF TRISA ;configura PORTA todo como salida
CLRF TRISE ; PUERTO A COMO SALIDA
CLRF TRISC ;PUERTO C COMO SALIDA
CLRF ANSELH ;ENTRADAS DIGITALES
banksel PORTA ;volvemos al banco 0
;BORRAR PUERTOS
CLRF PORTA
CLRF PORTB
CLRF PORTC
CLRF PORTD
;CONFIGURACION INTERRUPCIONES
MOVLW B'10010010'
MOVWF INTCON
CLRF PORTB
Inicio
call TRIGER
goto Inicio
;*********************************
;*CONFIGURACION DEl disparo para el ultrasonido
;*********************************
TRIGER
BSF PORTA,0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BCF PORTA,0
CALL DELAY_60MS
GOTO TRIGER
;RUTINA RETARDOS
DELAY_60MS
movlw .66 ; 1 set numero de repeticion (B)
movwf PDel0 ; 1 |
PLoop1 movlw .181 ; 1 set numero de repeticion (A)
movwf PDel1 ; 1 |
PLoop2 clrwdt ; 1 clear watchdog
clrwdt ; 1 ciclo delay
decfsz PDel1, 1 ; 1 + (1) es el tiempo 0 ? (A)
goto PLoop2 ; 2 no, loop
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ? (B)
goto PLoop1 ; 2 no, loop
clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
;*********************************
;*Servicio de rutinas de interrupción
;*********************************
INTERRUPCION MOVWF temporal1
MOVF STATUS,W
MOVWF temporal2
BTFSC INTCON,INTF ;salta si la interrupción no es interna
GOTO INT_RBO
FIN_INTER
MOVF temporal2,w
movwf STATUS
MOVF temporal1,w
retfie
INT_RBO
BTFSS PORTB,0
GOTO ENCENDER
GOTO APAGAR
ENCENDER
BSF PORTB,1
GOTO FIN_INTER
APAGAR
BCF PORTB,1
GOTO FIN_INTER
END
Lo que tenes que haces segun yo es crear una rutina que genere el pulso y espere 60ms, esa la vas a repetir mientras no se pulse rb0.
Por otro lado lo unico que tenes que hacer en la interrupcion es modificar una variable que se llame por ejemplo "pulsado" y si esta variable es true interrumpir el blucle infinito del programa principal.
-
Para poder ayudarte deberías poner más información la primera que máquina utilizas y segundo el hardware que estas utilizando.
compañero estoy utilizando el pic16f887 y el mplab x v1.6 .
-
Porque no pones el hardware, creo que el error puede estar en la forma como estas interpretando el suceso de interrupción, ya que el terminal RB0 debe estar activo para de esta manera detectar el flanco descendente en RB0.
-
El programa genera un pulso de 12us cada 60ms, lo que necesito es interrumpir ese pulso cuando halla un pulso en RB0 que se encienda un led en el puerto RB1, pero no logro que se ejecute la interrupción correctamente. agradecería cualquier ayuda.
; CONFIGURAR REGISTROS
temporal1 EQU 0X23
temporal2 EQU 0X24
PDel0 EQU 0X21
PDel1 EQU 0X22
ORG 0X00
GOTO INIT
ORG 0X04
GOTO INTERRUPCION
ORG 0X05
INIT
;*********************************
;*CONFIGURACION DE PUERTOS y de la interrupciones
;*********************************
banksel TRISB ;Pasamos al banco 1
MOVLW B'11111101' ; RB0 COMO ENTRADA
MOVWF TRISB
BCF OPTION_REG,6
CLRF TRISA ;configura PORTA todo como salida
CLRF TRISE ; PUERTO A COMO SALIDA
CLRF TRISC ;PUERTO C COMO SALIDA
CLRF ANSELH ;ENTRADAS DIGITALES
banksel PORTA ;volvemos al banco 0
;BORRAR PUERTOS
CLRF PORTA
CLRF PORTB
CLRF PORTC
CLRF PORTD
;CONFIGURACION INTERRUPCIONES
MOVLW B'10010010'
MOVWF INTCON
CLRF PORTB
Inicio
call TRIGER
goto Inicio
;*********************************
;*CONFIGURACION DEl disparo para el ultrasonido
;*********************************
TRIGER
BSF PORTA,0
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BCF PORTA,0
CALL DELAY_60MS
GOTO TRIGER
;RUTINA RETARDOS
DELAY_60MS
movlw .66 ; 1 set numero de repeticion (B)
movwf PDel0 ; 1 |
PLoop1 movlw .181 ; 1 set numero de repeticion (A)
movwf PDel1 ; 1 |
PLoop2 clrwdt ; 1 clear watchdog
clrwdt ; 1 ciclo delay
decfsz PDel1, 1 ; 1 + (1) es el tiempo 0 ? (A)
goto PLoop2 ; 2 no, loop
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ? (B)
goto PLoop1 ; 2 no, loop
clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
;*********************************
;*Servicio de rutinas de interrupción
;*********************************
INTERRUPCION MOVWF temporal1
MOVF STATUS,W
MOVWF temporal2
BTFSC INTCON,INTF ;salta si la interrupción no es interna
GOTO INT_RBO
FIN_INTER
MOVF temporal2,w
movwf STATUS
MOVF temporal1,w
retfie
INT_RBO
BTFSS PORTB,0
GOTO ENCENDER
GOTO APAGAR
ENCENDER
BSF PORTB,1
GOTO FIN_INTER
APAGAR
BCF PORTB,1
GOTO FIN_INTER
END
Hola.
Me parece que en tu codigo esta mal que inicialices en 1 el bit INTF ( te lo he marcado en rojo en tu codigo)
;CONFIGURACION INTERRUPCIONES
MOVLW B'10010010'
Tendrias que inicializarlo en cero y cuando se produce la interrupcion chequeas que ha cambiado a 1 (esto ultimo ya lo estas haciendo en tu programa)
Lo sigo mirando a ver si encuentro algun error mas.
Saludos.
-
A parte de lo que comenta el compañero Darkman_A, existe un problema mucho mayor ya que no estas aplicando la regla de oro en la interrupciones y es que se deben limpiar los bits banderas que indican que una interrupción ha ocurrido en este caso particular en la rutina de interrupción (desde FIN_INTER) debes agregar la siguiente linea de código.
FIN_INTER
bcf intcon,1
Ya se han encontrado 2 errores, implementa las sugerencias haber si así anda.
-
Si compañeros tienen toda la razón, ya realice los cambios mencionados, ademas agregue el OPTION_REG para que el RB0 detecte el flanco de subida, pero aun no me anda bien.
Ya modifique el código y agregue una imagen de la simulación
-
Haber si estoy entendiendo, tienes configurado la interrupción para que detecte un flanco descendente en el terminal RB0, si un flanco descendente ocurre el programa principal se debe interrumpir para atender la solicitud de interrupción generada por el evento externo, pero según el hardware el terminal RB0 esta en 0 (o al menos eso es lo que observo en el esquemático) por lo tanto, para que funcione el terminal RB0 debe mantenerse inicialmente (antes de hacer la solicitud) en nivel alto, es decir, conectado a 5V. Así se realiza la simulación?.
-
Eso es exactamente lo que quiero hacer pero con la diferencia que quiero detectar el flanco de subida. Alguna sugerencia?
-
Hola.
Me parece que el problema esta aca.
Estas escribiendo
INT_RBO BTFSS PORTB,0
GOTO ENCENDER
GOTO APAGAR
Estas chequeando el puerto B0 ( por donde llega la interrupcion). Suponiendo que se produjo la interrupcion esa entrada esta a 1. Siempre se va a dar ese caso ( sin considerar el ruido de rebote del pulsador. Estamos con el Proteus).
Tenes una sentencia BTFSS que salta cuando es 1. Por lo tanto salta y va a GOTO APAGAR, y el led nunca se prende.
Si queres que cambie el estado del led cuando presionas tendrias que chequear B1 que es donde esta el led o en su defecto un registro auxiliar donde guardes el estado del led.
Miralo, cualquier cosa volve a consultar.
Saludos.
Otra cosa. esta limpiando el WDT (clrwdt). No necesitas limpiarlo si no lo estas usando (& _WDTE_OFF &)
Y una mas, no se que le parezca al moderados, pero me parece que si corregis el codigo original tendrias que poner algo un texto que indique que fue corregido, porque sino dentro de unos dias entra alguien y no entiende nada porque al final si seguis corrigiendo el programa va a estar bien y no va a encontrar los errores, salvo que se lea todo el post. Algun comentario que indique que corregiste tal linea.
Saludos nuevamente.
-
Tienes razón las correcciones que he realizado las he colocado en color rojo. he revisado el código una y otra vez y no le encuentro problema alguno, sinceramente ya no se que hacer
-
Me parece que hay un error en la configuración del registro ANSELH. Por lo que entiendo, lo estás intentando configurar estando en el banco 1 (al seleccionar dicho banco para modificar el trisB), pero el registro ANSELH se encuentra en el banco 3. Por lo tanto RB0 te queda configurada como entrada analógica.
-
Para que funciones debes agregar las siguientes lineas de código, fíjate que en tu código existe un error en estas lineas ya que estos registros se encuentran en el banco 3 y no en el banco 1 de la memoria como esta implementado en el programa guía.
bsf STATUS,6
bsf STATUS,5 ; banco 2
CLRF ANSELH ;ENTRADAS DIGITALES
CLRF ANSEL
De esta manera funciona si problema alguno.
-
Para que funciones debes agregar las siguientes lineas de código, fíjate que en tu código existe un error en estas lineas ya que estos registros se encuentran en el banco 3 y no en el banco 1 de la memoria como esta implementado en el programa guía.
bsf STATUS,6
bsf STATUS,5 ; banco 2
CLRF ANSELH ;ENTRADAS DIGITALES
CLRF ANSEL
De esta manera funciona si problema alguno.
Ecxelente un paso mas, ahora me enciende y me apaga el led con el flanco de subida, pero no se me interrumpe el triger lo que necesito es que mietras el led este encendido no halla pulso en el triger
-
Para que funciones debes agregar las siguientes lineas de código, fíjate que en tu código existe un error en estas lineas ya que estos registros se encuentran en el banco 3 y no en el banco 1 de la memoria como esta implementado en el programa guía.
bsf STATUS,6
bsf STATUS,5 ; banco 2
CLRF ANSELH ;ENTRADAS DIGITALES
CLRF ANSEL
De esta manera funciona si problema alguno.
Ecxelente un paso mas, ahora me enciende y me apaga el led con el flanco de subida, pero no se me interrumpe el triger lo que necesito es que mietras el led este encendido no halla pulso en el triger
En "inicio" chequea si el bit del led esta en 1 ( o en cero como prefieras; BTFss o BTFsc) y luego ejecutas la rutina call trigger. Si no pones una condicion lo hace siempre.
Fijate si necesitas o no deshabilitar la interrupcion mientras generas el pulso (durante la rutina del pulso), para que no te quede un pulso cortado.
Saludos.
-
Si bien soy partidario del uso de las interrupciones, en este caso particular me parece que estás complicando tal vez más de lo que está solucionando. Si el propósito de la interrupción no es académico no me parece un buen caso para utilizar la interrupción.
Desactivando la interrupción y colocando:
TRIGER
BTFSC PORTB,0
GOTO TRIGER
BSF PORTA,0
...
Alcanza y sobra para tu propósito.
Ojo que en ese caso se puede perder la separación entre pulsos de 60mS.
Por otro lado, estás guardando y restaurando de forma errónea los registros clave (W y STATUS en este caso). No podés usar movf libremente, porque movf es una instrucción que modifica el flag Z del registro STATUS, por lo que estás corrompiendo el correcto valor del registro a restaurar. Eso puede hacer que tu programa se descontrole en el momento menos pensado. Revisá la forma correcta de hacerlo, revisando el datasheet de tu uC, bajo la sección: Context Saving During Interrupts.
-
Si bien soy partidario del uso de las interrupciones, en este caso particular me parece que estás complicando tal vez más de lo que está solucionando. Si el propósito de la interrupción no es académico no me parece un buen caso para utilizar la interrupción.
Totalmente de acuerdo, no se porque motivo la gente, a veces, cree que las interrupciones son la solucion a todo y hay muchas veces que complican algo que seria muy simple.
Tambien pasa que hay profesores que se los mandan hacer asi, para que aprendan, pero les mandan hacer ejemplos tan "malos" que en vez de aprender "desaprenden" :P :P
-
Si bien soy partidario del uso de las interrupciones, en este caso particular me parece que estás complicando tal vez más de lo que está solucionando. Si el propósito de la interrupción no es académico no me parece un buen caso para utilizar la interrupción.
Totalmente de acuerdo, no se porque motivo la gente, a veces, cree que las interrupciones son la solucion a todo y hay muchas veces que complican algo que seria muy simple.
Tambien pasa que hay profesores que se los mandan hacer asi, para que aprendan, pero les mandan hacer ejemplos tan "malos" que en vez de aprender "desaprenden" :P :P
Lo que quiero implementar es un sensor de distancia ultrasonico, pero como apenas me inicio en esto de los pics y la programación, me pareció que lo primero que tenia que hacer era aprender las interrupciones, ya que necesito contar el ancho de pulso que le llega al puerto rb0 ya que este esta en funcion de la distancia, o si alguien me recomienda otra forma mas sencilla de hacerlo se lo agradecería mucho.
-
Lo que quiero implementar es un sensor de distancia ultrasonico, pero como apenas me inicio en esto de los pics y la programación, me pareció que lo primero que tenia que hacer era aprender las interrupciones, ya que necesito contar el ancho de pulso que le llega al puerto rb0 ya que este esta en funcion de la distancia, o si alguien me recomienda otra forma mas sencilla de hacerlo se lo agradecería mucho.
Si quieres medir el ancho de un pulso en el foro hay bastante info del tema, es más hay ejemplos de todas la clases y en todo los lenguajes, sólo utiliza el buscador del foro y te saldrá bastantes hilos, te recomiendo el hilo del compañero REDPIC donde enseña algunas técnicas (creo que son las únicas) para medir el ancho de un pulso utilizando diferentes modulo de hardware de la máquina.
-
Si, hay informacion por el foro, en esencia es darle al sensor orden de enviar eco, poner un TIMER a contar (TMR1 es el mas preciso) y cuando caiga el receptor del sensor leer ese TMR, supongo que hay mas maneras de hacerlo.
Recorde que hablamos de esto no hace mucho aqui:
http://www.todopic.com.ar/foros/index.php?topic=34630.0
Hay una documentacion bastante buena del SRF-05 en español.
A hacer interrupciones esta bien que aprendas, puede que en este caso te sean utiles, pero hay veces que no van bien...