TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: tavisho en 03 de Marzo de 2009, 01:23:45
-
Saludos piclisteros. Tengo un problema con el stack. Estoy escribiendo un simple programa para probar la interrupción rb4-b7, y para comprobar que he entrado a ella enciendo un led en la rutina de servicio de interrupción. El problema es que cuando pongo el temporizado entre el encendido y apagado del led ( de 1 seg )
no sirve bien la instrucción de retfie. Supongo que el problema es con el stack. Miren las porciones del programa:
Tratamiento_Interrupción
btfss INTCON,RBIF ; Fue la interrupción de cambio??
goto Final ; no, interrupción en falso, regrsa.
bsf PORTB,1
call Retardo_1s
nop
call Retardo_1s
bcf PORTB,1
Final
movf PORTB,0
bcf INTCON,RBIF ; Repara el fag de la interrupción.
retfie ; Retorno de la interrupción
si me decido a quitar retardo_1s ( incluido en un .inc ) el programa corre tranquilamente, sin embargo cuando lo pongo la pila se vuelve loca. Miren:
Stack level Return Address Location
0 Empty
1 18(akí es a donde debería regresar)
2 0A (este nivel se agrega al usar retardo_1s)
Y cuando quito retardo_1s se ve así y funciona bien:
Stack Level Return Address
0 Empty
1 18
Como puedo elegir el nivel de la pila para regresar de la interrupción usando Retardo_1s....¿ o me recomiendan hacer ese retardo de 1 segundo con contadores anidados?
-
Cuando vuelves de la rutina de Retardo_1s, ¿Vuelves por medio de la instrución RETURN?
-
tienres razón leon pic, supongo que el problema se genera porque no usa la instrucción return para volver del retardos.inc. Es algo extraño ya que esta rutina (.inc) nunca me había generado problemas, se regresa como "por arte de magia" porque salta entre los retardos y la rsi de manera misteriosa. ¿ Algún consejo ? Tal vez pudiera adjuntar los archvos ( mi programa y la rutina de retardos ) para que los puedan analizar, pero no sé como adjuntar un archivo al foro, ¿ cómo se hace ?
-
Cuando estás redactando el mensaje, ve a opciones adicionales (inferior izquierda) ahí tienes la opción de adjuntar archivos. Fijate que están puestos las extenciones de los archivos permitidos, otros fuera de esos, no te deja y tienen un límite de 250Kb
-
acá lo pongo para ue lo puedas analizar leonpic. cuando yo lo forzo a entrar a la interrupcíón con un stimulus pasa por la rutina retardo_1s y paas de retfie no regresa al lugar adecuado, sino a unos renglones más arriba.
-
Hola,
Tengo el mismo libro que tu, me parece muy bueno para iniciarse.
En cuanto a la subrutina de tiempos, si sale con un return. Fijate que cuando llamas a la subrutina de 1s, lo que hace es cargar un valor en el registro W, en este caso 10, y salta (no llama) a Retardo_1Decima, algo mas abajo. Ahi precarga el contador R_ContC con ese valor y entra en una serie de bucles que decrementan varios contadores hasta llegar al return que tienes abajo del todo, justo antes del comentario final de la subrutina.
La verdad es que no veo que falla en el programa. Bajo mi punto de vista (de novato total), lo veo correcto.
Saludos,
-
El problema es que en la parte donde defines los datos:
CBLOCK
R_ContA ; Contadores para los retardos.
R_ContB
R_ContC
ENDCno estás definiendo el lugar de memoria donde guardar esas variables, por lo tanto el ensamblador la coloca desde la dirección 0x00 en adelante, es decir 0x00,0x01 y 0x02, Justo en la dirección 0x02 se encuentra el contador de programa (PCL), y le estás cargando el valor 10 en decimal o sea 0A en hexa cuando entras al retardo de 1s. Por eso cuando debería seguir con el programa al cargar ese valor en R_ContC, salta a la dirección 0A que es justo la línea
bcf PORTB,1
fijate en el list:
0000 280E GOTO 0xe 10: goto Inicio
11: org 0x04
12: Tratamiento_Interrupción
0004 138B BCF 0xb, 0x7 13: bcf INTCON,GIE
0005 1C0B BTFSS 0xb, 0 14: btfss INTCON,RBIF ; Fue la interrupción de cambio??
0006 280B GOTO 0xb 15: goto Final ; no, interrupción en falso, regrsa.
0007 1486 BSF 0x6, 0x1 16: bsf PORTB,1
0008 2052 CALL 0x52 17: call Retardo_1s
0009 0000 NOP 18: nop
000A 1086 BCF 0x6, 0x1 19: bcf PORTB,1 ----->acá es donde salta
20: Final
000B 0806 MOVF 0x6, W 21: movf PORTB,0
000C 100B BCF 0xb, 0 22: bcf INTCON,RBIF ; Repara el fag de la interrupción.
000D 0009 RETFIE 23: retfie ; Retorno de la interrupción
24:
25:
26: Inicio
000E 1683 BSF 0x3, 0x5 27: bsf STATUS,RP0 ;
000F 1303 BCF 0x3, 0x6 28: bcf STATUS,RP1 ; Pasa al ban
Por lo tanto te recomiendo que le asignes alguna dirección de inicio del block de datos, que esté libre , por ejemplo 0x21
-
Enhora buena pablomanieri,
creo que puede estar ahi el error.
En el programa principal no se define ningún registro con CBLOCK, es decir, el primero que se encuentra el compilador es el de la subrutina, que normalmente no debería ser el primero. Te cito casi textualmente:
Si el primer CBLOCK en el archivo fuente, en este caso no existe, no define ningún comienzo, las posiciones de memoria de los registros a crear comienzan por el 0, que se corresponde a la zona del SFR, sobreescribiendo los datos del mismo.
Yo creo que si añades a tu programa fuente:
Cblock 0x0C
Endc
Ya no tendrás problemas, puesto que, aunque no hayas creado ningún registro, si le has dado un valor inicial al Cblock.
Si sigues teniendo problemas, crea un registro, aunque no lo uses.
Saludos,