[ movlw 0x80 ;SE LE ASIGNA LA DIVISION AL TMR0
movwf TMR0_OPT
/quote]
No estara aqui el fallo?
INTEDG: Interrupt Edge Select bit
1 = Interrupt on rising edge of RB0/INT pin
0 = Interrupt on falling edge of RB0/INT pin
no eatas activando esto?
tapi8
El 99% de los casos en que un programa se resetea al agregarle unas líneas, está relacionado con las tablas, computed goto's o funciones que cruzan las páginas del uC.
Tenés alguna tabla más adelante en el código?
Lo de citar no es lo mio y el hex parece que tampoco, es esto lo que deshabilita
.-
RBPU: PORTB Pull-up Enable bit
1 = PORTB pull-ups are disabled
0 = PORTB pull-ups are enabled by individual port latch values
Pero no veo que lo habilites en INTCON, o esta mal el comentario y solo deshabitas las PULL-UPS.
Hola Tapi8, gracias por interesarte en mi problema, te comento que las Pull-up del puerto B no están siendo habilitadas, faltó aclararlo en el texto, con el valor que asigné a TMR0_OPT (0x80) las deshabilito y le doy el valor de división que necesito para las subrutinas de retardo que estoy usando.
En cuanto al registro INTCON solo exploro el bit 2, que según entiendo, es el que me indica cuando el TMR0 se rebalsó ¿puede ser que el problema este relacionado con esto?, saludos!!!
Adjunta el codigo entero y puede que logremos ayudarte..
Comprimilo y publicalo como archivo adjunto a tu mensaje
Hola Grutis, a simple vista, veo que al final, hay unas subrutinas, que estan "despues" del END... el end es lo ultimo que tienes que colocar ok?
Suerte!
Norberto
Hola.
Si, esa advertencia es la que indica el problema.
Como estas usando más de 2KWords de la memoria FLASH del uC, tenes que tener ciertos recuados antes de llamar a una subrutina que no se encuentra en la misma pagina del uC.
para hacerlo debes hacer, por ejemplo:
pagesel Rutina_Pag1
call Rutina_Pag1
pagesel $
el pagesel es una MACRO que viene incorporada en un conjunto que trae el MPASM y es la que va a generar las 2 instrucciones necesarias para realizar el cambio de pagina.
el pagesel $ es necesario para volver a la pagina actual cada vez que se retorna de una subrutina que estaba en otro banco...
Quise hacer una MACRO que generara(o no) automaticamente el codigo, pero la verdad que el MPLAB deja bastante que desear en eso, y solo obtengo errores asi que te va a tocar agregarlas una por una.
Saludos.
Hola de nuevo BrunoF, nuevamente gracias por contestar, me has aclarado un poco más el tema, veo que no estoy al tanto de todos los secretos de este mundo de los µC y sus programaciones y nuevamente pido disculpas por mi ignorancia.
Puedo entender que lo que está ocurriendo, es similar a cuando se usan registros que no están en el Bank 0 y están en los otros bancos, por ejemplo, si quisiera usar el conversor A/D del PIC16F877 tengo el registro “ADRESH”, que esta en el Bank 0 y el “ADRESL” que esta en el Bank 1 para pasar de bancos es necesario utilizar los bits 5 y 6 del registro “STATUS” ¿es acertada la comparación?, de todos modos sigo sin entender bien lo que pusiste después (lo de generar una MACRO y lo de arreglarlas una por una) nuevamente perdón por la ignorancia, realmente me da mucha vergüenza. De todos modos el ejemplito me sirvió para hacer esto:
pagesel RET_1_SEG
call RET_1_SEG ;COMO PRECAUCIÓN SE GENERA UN RETARDO DE 1 SEGUNDO
pagesel $ ¿acá debería indicar a donde debe apuntar pcl?
bsf PORTD,7 ;SE CONMUTA LA LLAVE ELECTRÓNICA PARA PODER COMUNICAR LA
;CENTRAL CON EL MÓDULO DE CONTROL DEL DISPLAY
Espero no molestarlos con tantas preguntas básicas, quizás para ustedes que dominan el tema tan bien, saludos!!!
| LINEA: | DIRECCION FLASH |
| org 0x000 | - |
| clrf PCLATH | 0x000 |
| pagesel pag1 | 0x001 0x002 |
| call pag1 | 0x003 |
| call pag0 | 0x004 |
| goto $ | 0x005 |
| pag0 nop | 0x006 |
| retlw 0x00 | 0x007 |
| org 0x800 | - |
| pag1 nop | 0x800 |
| retlw 0xAA | 0x801 |
| LINEA: | DIRECCION FLASH | Código pseudo-ensamblado: |
| org 0x000 | - | - |
| clrf PCLATH | 0x000 | clrf 0x0A |
| pagesel pag1 | 0x001 0x002 | pagesel 0x800 |
| call pag1 | 0x003 | call 0x00 |
| call pag0 | 0x004 | call 0x06 |
| goto $ | 0x005 | goto 0x05 |
| pag0 nop | 0x006 | nop |
| retlw 0x00 | 0x007 | retlw 0x00 |
| org 0x800 | - | - |
| pag1 nop | 0x800 | nop |
| retlw 0xAA | 0x801 | retlw 0xAA |
| LINEA: | DIRECCION FLASH | Código pseudo-ensamblado: |
| org 0x000 | - | - |
| clrf PCLATH | 0x000 | clrf 0x0A |
| pagesel pag1 | 0x001 0x002 | bsf PCLATH,3 bcf PCLATH,4 |
| call pag1 | 0x003 | call 0x00 |
| call pag0 | 0x004 | call 0x06 |
| goto $ | 0x005 | goto 0x05 |
| pag0 nop | 0x006 | nop |
| retlw 0x00 | 0x007 | retlw 0x00 |
| org 0x800 | - | - |
| pag1 nop | 0x800 | nop |
| retlw 0xAA | 0x801 | retlw 0xAA |
| LINEA: | DIRECCION FLASH | Código pseudo-ensamblado: |
| org 0x000 | - | - |
| clrf PCLATH | 0x000 | clrf 0x0A |
| pagesel pag1 | 0x001 0x002 | bsf 0x0A,3 bcf 0x0A,4 |
| call pag1 | 0x003 | call 0x00 |
| call pag0 | 0x004 | call 0x06 |
| goto $ | 0x005 | goto 0x05 |
| pag0 nop | 0x006 | nop |
| retlw 0x00 | 0x007 | retlw 0x00 |
| org 0x800 | - | - |
| pag1 nop | 0x800 | nop |
| retlw 0xAA | 0x801 | retlw 0xAA |
Si. Es una comparacion bastante bien aproximada...
Y a lo segundo también. Cada vez que llames a una subrutina que no esté en la misma página que desde donde la estás llamando, necesitás configurar la página antes de llamarla, y volver a configurar la página actual después de haberlo hecho.
No necesitás hacer ninguna macro. Era solo para que no tengas que hacer la tediosa tarea de agregar las macros antes y después de cada llamada a subrutinas de otras páginas.
Te comento el motivo del por qué es necesario el pagesel $ después de cada llamada a subrutinas de otras páginas.(He hablado sobre este tema en el foro extensamente, aunque no recuerdo bien en qué tema...tal vez si haces una busqueda en el foro logres encontrar algo).
La MACRO pagesel setea los bits necesarios del registro PCLATH. Estos bits se utilizan a la hora de ejecutar una instrucción call. Cuando por ejemplo haces:
pagesel subrutina_pag1
call subrutina_pag1
la primer linea(pagesel) setea los bits para la pagina donde se encuentre la subrutina "subrutina_pag1"(que supuestamente esta en la pagina 1). Luego se realiza el call correctamente. Al volver de la subrutina, los bits del PCLATH siguen cargados con la página 1, entonces acá surgen los problemas si intentás llamara normalmente a otra subrutina,ya que deberías volver a la página actual antes de hacerlo.
Por ello, es necesario la instrucción pagesel $, que hará que los bits del PCLATH vuelvan a configurarse para la página actual.
Vamos con un ejemplo más real:Código: ASM
org 0x000 clrf PCLATH pagesel pag1 call pag1 call pag0 goto $ pag0 nop nop retlw 0x00 org 0x800 ;vector de pagina 1 pag1 nop retlw 0xAA
Este codigo no se va a comportar bien...Veamos en profundidad el por qué.
Primero vamos a anotar dónde se guarda cada línea en la memoria FLASH:
LINEA: DIRECCION FLASH org 0x000 - clrf PCLATH 0x000 pagesel pag1 0x001
0x002call pag1 0x003 call pag0 0x004 goto $ 0x005 pag0 nop 0x006 retlw 0x00 0x007 org 0x800 - pag1 nop 0x800 retlw 0xAA 0x801
Ahora vamos a empezar a ensamblar de a poquito las líneas tal cual lo haría el MPASM( te recuerdo que todo esto lo estoy haciendo solo teoricamente, por lo que no está probado y puede que me equivoque en algunos detalles)
LINEA: DIRECCION FLASH Código pseudo-ensamblado: org 0x000 - - clrf PCLATH 0x000 clrf 0x0A pagesel pag1 0x001
0x002pagesel 0x800 call pag1 0x003 call 0x00 call pag0 0x004 call 0x06 goto $ 0x005 goto 0x05 pag0 nop 0x006 nop retlw 0x00 0x007 retlw 0x00 org 0x800 - - pag1 nop 0x800 nop retlw 0xAA 0x801 retlw 0xAA
Ahora otra pasada mas, un poco más profunda:
LINEA: DIRECCION FLASH Código pseudo-ensamblado: org 0x000 - - clrf PCLATH 0x000 clrf 0x0A pagesel pag1 0x001
0x002bsf PCLATH,3
bcf PCLATH,4call pag1 0x003 call 0x00 call pag0 0x004 call 0x06 goto $ 0x005 goto 0x05 pag0 nop 0x006 nop retlw 0x00 0x007 retlw 0x00 org 0x800 - - pag1 nop 0x800 nop retlw 0xAA 0x801 retlw 0xAA
Un poco más...
LINEA: DIRECCION FLASH Código pseudo-ensamblado: org 0x000 - - clrf PCLATH 0x000 clrf 0x0A pagesel pag1 0x001
0x002bsf 0x0A,3
bcf 0x0A,4call pag1 0x003 call 0x00 call pag0 0x004 call 0x06 goto $ 0x005 goto 0x05 pag0 nop 0x006 nop retlw 0x00 0x007 retlw 0x00 org 0x800 - - pag1 nop 0x800 nop retlw 0xAA 0x801 retlw 0xAA
Ahora creo que vamos a poder hablar con un poco más de prioridad.
La instrucción call(en los uC de 14bits de largo de palabra) sólo puede direccion 12 bits. Esto significa que puede llamar sólo dentro del rango(decimal): [0;2047].
En los uC que tienen más de 2KWords esto(12 bits) no alcanzaría. Y aquí cobran importancia los bits 3 y 4 el registro PCLATH. Ellos son los 2 bits adicionales que necesitamos para poder direccionar los 14 bits completos que necesitamos(es decir, direccionar un rango de 8KWords).
Como se puede apreciar más arriba, la instrucción call pag1 se transforma en un call 0x00...Esto parecería que la llamada está mal ya que nosotros queremos llamar a la subrutina pag1(ubicada en la posición 0x800). Pero como expliqué previamente, al ejecutarse una instrucción call, el uC también utiliza los bits 3 y 4 del PCLATH para completar los 14 bits que necesita. Como hemos sido inteligentes, los hemos precargado con el valor binario: 01
Ahora, armando lo que tenemos entre los bits PCLATH,4 PCLATH,3 y la dirección a la que llama la instrucción call tendríamos:
PCLATH,4 PCLATH,3 call 0x00
En binario: 0 1 0000 00000000
Todos juntos: 01000000000000
lo que en hexadecimal resulta: 0x800
¡Qué barbaro,¿no?! Resulta que hemos llamado realmente a la posición 0x800.
Ahora una vez realizada la llamada,el nop y el retlw, surge el problema...cuando queremos llamar a la subrutina "pag0". ¿Por que? Porque el PCLATH[4,3] continúa cargado con el valor binario 01.
Entonces, en lugar de llamar a la posición 0x006(que es donde se encuentra la subrutina pag0) estaríamos haciendo:
PCLATH,4 PCLATH,3 call 0x06
En binario: 0 1 0000 00000110
Todos juntos: 01000000000110
lo que en hexadecimal resulta: 0x806
Por lo que estaríamos yendonos a una posición completamente alejada de la que queríamos. Es por ello, que debemos utilizar la instrucción pagesel $, que acomodará nuevamente los bits 4 y 3 del PCLATH para asegurar que en futuras llamadas no nos suceda esto.
Espero que haya quedado claro.
Un saludo.
Hola de nuevo, algo más entendí, evidentemente soy un brut... hice algunas modificaciones en el programa, con lo cual ahorré algunas líneas y pude avanzar, pero estoy al límite de pasarme de nuevo y faltan desarrollar muchísimas funciones más, lo que hice fue esto:
;****************************** INICIO DEL PROGRAMA PRINCIPAL *********************************
clrf PORTA ;SE LIMPIAN LOS POSIBLES VALORES ERRÓNEOS DE LOS PUERTOS
clrf PORTB
clrf PORTC
clrf PORTD
clrf PORTE
clrf PIR1 ;SE PONE A 0 A PIR1 Y RCREG A 0
clrf RCREG
pagesel RET_1_SEG ;PCLATH adquiere el valor 0x08, tal como lo explicaste
call RET_1_SEG ;COMO PRECAUCIÓN SE GENERA UN RETARDO DE 1 SEGUNDO
pagesel $ ;PCLATH adquiere el valor 0x00, tal como lo explicaste
bsf PORTD,7 ;SE CONMUTA LA LLAVE ELECTRÓNICA PARA PODER COMUNICAR LA
;CENTRAL CON EL MÓDULO DE CONTROL DEL DISPLAY
.....
.....
.....
Seguramente, si sigo agregando líneas de programación, ocurrirá lo mismo, voy a ver si puedo profundizar y entender bien las excelentes explicaciones. Gracias nuevamente por la paciencia, saludos
[/quLa instrucción call(en los uC de 14bits de largo de palabra) sólo puede direccion 12 bits. Esto significa que puede llamar sólo dentro del rango(decimal): [0;2047].
ote]
Bruno creo que aqui tuviste un pequeño lapsus, creo que son 11 bits los que direcciona la instruccion, los 8 del PCL y los 3 menos significativos del PCLATCH.
Lo digo para que no haya confusiones, no por querer quitarle defectos a esta excelente explicacion.
tapi8
OK. Ya lo corregí
Por favor, en estos casos es necesario que muestres todo el código. Primero comprimilo en formato zip o rar y luego adjuntalo a un post para poder ayudarte...
Saludos.