TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: kurdo22 en 28 de Octubre de 2004, 06:48:00
-
Muy buenas, aqui estoy de nuevo a ver si me pueden echar una mano con un problemilla que me ha surgido en una interrupcion. El problema consiste en que en la interrupcion (interrupcion por llegada de dato de la USART2) tengo varios casos en funcion de la informacion obtenida, entoces hace la distincion del caso y ejecuta el caso (call) . Para que se salga le pongo el RETFIE, pero lo ejecuta como un RETURN, es decir, no se sale de la interrupcion al programa principal, sino que vuelve a la siguiente intruccion despues del call.
Os dejo el codigo lo mas simplificado posible para ver si podeis ehcarle un vistazo y darme alguna solucion.
Un saludo.
;**************************** EAP Unit Tester ***************************
;
; INTETRFACE PC - HARWARE
;
; Descripcion: espero a recibir un telecomando del PC, lo interpreto,
; y respondo.
;
; Tipo Reloj: HS
; Velocidad Reloj: 20MHz
; Reloj Instruccion: 5MHz = 0,2us
; Perro Guardian: deshabilitado
; Proteccion de codigo: OFF
;
;*************************************************************************
;DATOS
LIST P=18F8720 ;Tipo de procesador
INCLUDE <P18F8720.INC> ;Definicion de registros internos
TXDATO equ 0x10 ;Variables VARIAS
RXDATO equ 0x11
TEMPORAL equ 0x12
CONTADOR equ 0x13
CABECERA_PAQUETE_H equ 0x1B ;Variables TELECOMANDO
CABECERA_PAQUETE_L equ 0x1C
TELEMETRIA_COMIENZO_H equ 0x2D ;Variables TELEMETRIA
TELEMETRIA_COMIENZO_L equ 0x2E
MUSCLE_VOLT_H equ 0x2F
MUSCLE_VOLT_L equ 0x30
MUSCLE_CURR_H equ 0x31
MUSCLE_CURR_L equ 0x32
;CODIGO
ORG 0x00 ;inicio en el vector de reset
goto INICIO ;va a la primera instrucción de programa
ORG 0x08 ;vector de interrupción de alta prioridad
goto CABECERA_TELECOMANDO ;subrrutina de atención a alta prioridad
;------------- SURUTINAS INTERRUPCION
;*************************************************************************
; RUTINA Recibir un dato
;*************************************************************************
RECIBO
btfss PIR3,RC2IF ;testeamos si el buffer de RX lleno(flag RC2IF=1)
goto RECIBO ;vacio = no hay dato (esperamos)
movf RCREG2,W
movwf RXDATO
bcf RCSTA2,CREN ;limpiamos posibles errores
bsf RCSTA2,CREN ;deshabilitando y habilitando CREN
return
;*************************************************************************
; RUTINA Transmitir un dato
;*************************************************************************
ENVIO
movf TXDATO,W ;en el momento en que se pone el dato en TXREG2
movwf TXREG2 ;este es enviado
BUCLE
btfss TXSTA2,TRMT ;esperamos registro TSR vacio (flag TRMT=1)
goto BUCLE ;no vacio, esperamos
return
;*************************************************************************
; RUTINA Escribir Tabla Adquisicion Telecomando
;*************************************************************************
ESCRIBIR_TABLA
call RECIBO ;dato recibido por puerto serie
movf RXDATO,W
movwf INDF0 ;guardamos dato recibido en tabla
incf FSR0L,1 ;incrementamos puntero de tabla
return
;*************************************************************************
; RUTINA Leer Tabla Telemetria
;*************************************************************************
LEER_TABLA
movf INDF0,W ;leemos dato de tabla
movwf TXDATO
call ENVIO ;enviamos dato por puerto serie
incf FSR0L,1 ;incrementamos puntero de tabla
return
;*************************************************************************
; RUTINA Enviar Telemetría
;*************************************************************************
TELEMETRIA
;Recorrer una tabla en RAM para enviarla
movlw D"6" ;son 24
movwf CONTADOR ;inicializamos contador de variables de telemetría
movlw H"00" ;inicializamos cabecera y final de paquete
movwf TELEMETRIA_COMIENZO_L
movlw H"FF"
movwf TELEMETRIA_COMIENZO_H
movlw TELEMETRIA_COMIENZO_H ;inicializamos puntero de tabla
movwf FSR0L
BUCLE_ADQUISICION
call LEER_TABLA
decfsz CONTADOR,1
goto BUCLE_ADQUISICION
return
;------------- RUTINA DE ATENCION A INTERRUPCION
CABECERA_TELECOMANDO
bcf PIE3,RC2IE ;deshabilitamos interrupción de recepción USART_2
movf RCREG2,W
movwf CABECERA_PAQUETE_H
bcf RCSTA2,CREN ;limpiamos posibles errores
bsf RCSTA2,CREN ;deshabilitando y habilitando CREN
BUCLE_RECIBO
call RECIBO
movf RXDATO,W
movwf CABECERA_PAQUETE_L
;------------------ INTERPRETACION
INTERPRETAR_TELECOMANDO ;interpretamos la cabecera de telecomando obtenida
TELECOMANDO_1 ;1º Comienzo de Conexión
movlw H"00"
cpfseq CABECERA_PAQUETE_L ;comparamos y si no es igual saltamos siguiente telecomando
goto TELECOMANDO_2
goto COMIENZO_CONEXION
TELECOMANDO_2 ;2º Final de Conexión
movlw H"FF"
cpfseq CABECERA_PAQUETE_L ;comparamos y si no es igual saltamos siguiente telecomando
goto TELECOMANDO_3
goto FINAL_CONEXION
TELECOMANDO_3 ;3º Señal de Excitación
movlw H"11"
cpfseq CABECERA_PAQUETE_L ;comparamos y si no es igual saltamos siguiente telecomando
goto TELECOMANDO_4
goto SENAL_EXCITACION
TELECOMANDO_4 ;4º Selección de Ganacia
movlw H"22"
cpfseq CABECERA_PAQUETE_L ;comparamos y si no es igual saltamos siguiente telecomando
goto TELECOMANDO_5
goto SELECCION_GANANCIA
TELECOMANDO_5 ;5º Cambio de Estado
movlw H"33"
cpfseq CABECERA_PAQUETE_L ;comparamos y si no es igual saltamos siguiente telecomando
goto TELECOMANDO_6
goto CAMBIO_ESTADO
TELECOMANDO_6 ;6º Solicitud de Telemetría
movlw H"44"
cpfseq CABECERA_PAQUETE_L ;comparamos y si no es igual, error
goto SOLICITUD_TELEMETRIA
goto SOLICITUD_TELEMETRIA ;en caso de ERROR se envia telemetría
;------------------ EJECUCION TELECOMANDO
COMIENZO_CONEXION ; 1º
call FIN_INTERRUPCION_BAJA_PRIORIDAD
;------------------
FINAL_CONEXION ; 2º
call FIN_INTERRUPCION_BAJA_PRIORIDAD
;------------------
SENAL_EXCITACION ; 3º
call FIN_INTERRUPCION_BAJA_PRIORIDAD
;------------------
SELECCION_GANANCIA ; 4º
call FIN_INTERRUPCION_BAJA_PRIORIDAD
;------------------
CAMBIO_ESTADO ; 5º
call FIN_INTERRUPCION_BAJA_PRIORIDAD
;------------------
SOLICITUD_TELEMETRIA ; 6º
call FIN_INTERRUPCION_BAJA_PRIORIDAD
FIN_INTERRUPCION_BAJA_PRIORIDAD
bsf PIE3,RC2IE ;habilitamos interrupción de recepción USART_2
retfie
;-------------- SUBRRUTINAS PROGRAMA PRINCIPAL
;*************************************************************************
; RUTINA Inicialización Registros
;*************************************************************************
INICIALIZAR_REGISTROS
movlw D"2" ;son 24
movwf CONTADOR ;inicializamos contador de variables de telemetría
movlw TELEMETRIA_COMIENZO_H
movwf FSR0L ;inicializamos puntero de tabla
BUCLE_INICIACION
movlw H"68"
movwf INDF0
;clrf INDF0 ;limpiamos la variable
incf FSR0L,1 ;incrementamos puntero de tabla
decfsz CONTADOR,1
goto BUCLE_INICIACION
return
;------------------ oooOOO PROGRAMA PRINCIPAL OOOooo ---------------------
INICIO
;------------------ INICIALIZAMOS INTERRUPCIONES
bsf INTCON,GIE ;habilitamos interrupciónes
bsf INTCON,PEIE ;habilitamos interrupciónes perifericas
bsf PIE3,RC2IE ;habilitamos interrupción de recepción USART_2
;------------------ INICIALIZAMOS REGISTROS TELEMETRIA
call INICIALIZAR_REGISTROS ;limpiamos los registros de telemetría
;------------------ INICIALIZAMOS LA USART_2
bsf TRISG,2 ;habilitamos RX2 como entrada
bcf TRISG,1 ;habilitamos TX2 como salida
movlw D"129" ;9600 baudios
movwf SPBRG2
movlw B"00000100" ;8 bits datos, com. asincrona, alta velocidad=(menor error)
movwf TXSTA2
bsf RCSTA2,SPEN ;habilitamos puerto serie (USART2)
bsf TXSTA2,TXEN ;habilitamos transmision
bsf RCSTA2,CREN ;habilitamos recepcion
;----------------- BUCLE
;----------------- FIN DE PROGRAMA PRINCIPAL
FIN
nop
nop
nop
nop
goto FIN
END
-
Perdonarme pero ya vi el fallo, utilizo call en vez de goto, por eso vuelve despues del retfie. Ahora lo simulo y me lo hace todo prefectamente PERO NO FUNCIONA, PUEDEN SUGERIRME ALGO ALGO????
Un saludo
-
hola kurdo22
mira, no vi el programa pero queria decirte que tengas en cuenta el tema de la PILA del micro. cuando se hace una llamada CALL o de interrupciones, el micro guarda la ultima direccion que se iba a ejecutar en la pila, para luego de terminar con la subrutina, se carga el contador de programa CP con esa direccion y asi puede seguir ejecutando desde donde habia quedado.
esto de recuperar la direccion previa al pedido de interrupcion o a la peticion de de salto CALL se hace luego de la sentencia RETURN o RETFIE.
en conclusion : tenes que tener cuidado a la hora de hacer llamadas a subrutinas cuando estas dentro de otra subrutina, porque a la hora de volver con un RETURN o RETFIE, lo hace a la primera direccion que encuentra en la pila que trabaja en modo LIFO (last input first output, el ultimo que entra es el primero qeu sale), y tal vez esta direccion no corresponda o no sea la qeu vos estabas esperando.
por eso puede ser que cuando reemplazaste CALL por GOTO se te soluciono. la instruccion GOTO es un salto incondicional que no usa la pila para nada.
-
Supongo que habras cambiado todos los call por goto no ?
Por cierto no veo en ninguna parte que limpies el bit de interrupción esa sería una causa segura de no salir de la interrupcion. Bonito PIC yo estoy con el 18F6720 y es una maravilla ya me contarás como va lo de la memória externa y tal?
-
Muchas gracias a todos, dandole vueltas llegue a la misma conclusion del pc, por eso sustitui el call por goto. El programa ya esta funcionando perfectamente, asi que no hace falta que os estrugeis mas los sesos.
En cuanto al 18f8720 es muy potente, y es increible la multitud de tareas para las que esta preparado. He encontrado una pequeña pega, cuando quiero utilizar la instruccion sleep para ahorrar energia (pasa de 2mA a 2uA) las formas de hacerle salir del sleep son muy limitadas, es mas, solo se puede con eventos externos y muy limitados. Creo que seria mejor que pudiera salir del sleep con cualquier interrupcion. Yo por ejemplo utilizo una comunicacion serie asincrona y me interesa dejarlo en sleep cuando esta en reposo para evitar el consumo e energia y que se despierte cuando lleguen datos, pero no es posible porque solo lo permite con comunicacin serie sincrona, o por lo menos eso dicela data sheet. Otra pega es que ningun timer funciona cuando entra en sleep a excepcion del perro gurardian. Corregirme si me equivoco
Un saludo y gracias de nuevo