Autor Tema: PROBLEMAS CON PCL, EN PIC16F877  (Leído 8097 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
PROBLEMAS CON PCL, EN PIC16F877
« en: 12 de Agosto de 2009, 21:21:45 »
Hola a todos, estoy metido en el desarrollo del control de una máquina que ejecuta diferentes funciones, por diferentes motivos, elegí el PIC16F877. Iba todo en orden hasta que decidí, por motivos de necesidad del sistema, aumentar algunas líneas en el programa, esto provocó que este no se ejecute correctamente, llega hasta un punto, se “resetea” y vuelve al principio.
Gracias al simulador del MPLAB, descubrí que lo que está ocurriendo es que el contador de programa ó de página, no tengo muy en claro el tema, se rebalsa y esto provoca la falla mencionada. Por motivos de espacio no puedo publicar todo el programa, pero les dejo resumido, a modo de ejemplo la falla en cuestión, básicamente se van ejecutando instrucciones y al momento de llamar una subrutina, en este caso de retardo, durante la ejecución de este se produce el reseteo.
Espero que alguien me pueda orientar, estaría muy agradecido, chau Darío.         



;**************************** CONFIGURACIÓN DE PUERTOS Y REGISTROS ****************************           
 
           ORG    0x00           ; El programa comienza en la dirección 0 y
           goto   INICIO         ; salta a la dirección 5 para sobrepasar el
           ORG    0x05           ; vector de interrupción


INICIO movlw  0x81           ;SE SELECCIONA RA0 COMO ENTRADA ANALÓGICA, RELOG
           movwf  ADCON0     ;DERIVADO DE LA FRECUENCIA DEL OSCILADOR/32     
             

           bsf    STATUS,5      ;SE SELECCIONA DEL BANCO 1
                   
           movlw  0xFF           ;SE CONFIGURA EL PUERTO A COMO ENTRADA
           movwf  PORTA       

           movlw  0x00          ;SE CONFIGURA EL PUERTO B COMO SALIDA     
           movwf  PORTB

           movlw  0xBF          ;SE CONFIGURAN RC0, RC1, RC2, RC3, RC4, RC5 Y RC7 COMO
           movwf  PORTC       ;ENTRADA, RC6 COMO SALIDA
 
           movlw  0x00          ;SE CONFIGURA EL PUERTO D COMO SALIDA
           movwf  PORTD       
   
           movlw  0x07          ;SE CONFIGURA EL PUERTO E COMO ENTRADA, PUERTO D COMO 
           movwf  PORTE       ;PUERTO DE PROPOSITO GENERAL 

           movlw  0x04          ;SE CONFIGURAN RA0, RA1 Y RA3 COMO ENTRADAS   
           movwf  ADCON1    ;ANALÓGICAS  RA2, RA5, RE1, RE2 Y RE3 COMO ENTRADAS DIGITALES
                 
           movlw  0x24          ;SE CONFIGURAN 8 BITS DE TRANSMISIÓN, TRANSMISIÓN HABILITADA 
           movwf  TXSTA       ;MODO DE COMUNICACIÓN ASÍNCRONO, ALTA VELOCIDAD PARA EL MODO
                                       ;ASÍNCRONO
 
           movlw  0x0A         ;SE AJUSTA LA VELOCIDAD DE COMUNICACIÓN A 56.818 BIT/SEG       
           movwf  SPBRG 

           movlw  0x05         ;SE MUEVE EL VALOR 0x05 A SSPADD, DE ESTA FORMA SE CONFIGURA   
           movwf  SSPADD    ;LA FRECUENCIA DE TRABAJO DEL PUERTO I2C A 400KHz, PARA UNA
                                       ;FRECUENCIA DE RELOJ DE 10MHz
 
           movlw  0x00          ;SE PONE A 0 AL REGISTRO SSPSTAT
           movwf  SSPSTAT

           movlw  0x80          ;SE LE ASIGNA LA DIVISION AL TMR0
           movwf  TMR0_OPT
           
           bcf    STATUS,5      ;SELECCION DEL BANCO 0

;**********************************************************************************************

 
;****************************** 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           


          Acá se produce la falla, no se “vuelve” de la subrutina de retardo

           call  RET_1_SEG   ;COMO PRECAUCIÓN SE GENERA UN RETARDO DE 1 SEGUNDO  [/size]






Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #1 en: 13 de Agosto de 2009, 01:57:13 »
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?
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #2 en: 13 de Agosto de 2009, 12:15:30 »
Citar
[   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

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #3 en: 13 de Agosto de 2009, 14:21:13 »
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.


Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #4 en: 14 de Agosto de 2009, 00:14:41 »
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?


Hola Bruno, gracias por contestar an rápido y disculpa por mi ignorancia, ¿pero a que le llaman tabla ustedes?, saludos!!

Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #5 en: 14 de Agosto de 2009, 00:32:45 »
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!!! 

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #6 en: 14 de Agosto de 2009, 04:44:41 »
Adjunta el codigo entero y puede que logremos ayudarte..
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #7 en: 14 de Agosto de 2009, 09:52:26 »
Adjunta el codigo entero y puede que logremos ayudarte..

Hola de nuevo, el programa completo ocupa casi 4750 líneas, lo cual me causa un poco de verguenza jajaj, ya que seguramente se podría hacer mejor, pero bueno, me salió así ¿o publico por acá nomas?

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #8 en: 14 de Agosto de 2009, 14:10:44 »
Comprimilo y publicalo como archivo adjunto a tu mensaje
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #9 en: 14 de Agosto de 2009, 17:20:46 »
Comprimilo y publicalo como archivo adjunto a tu mensaje

Bueno, entendí, entonces adjunto a este mnsaje envío el archivo "asm"

Desconectado todopic

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3495
    • http://www.todopicelectronica.com.ar
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #10 en: 16 de Agosto de 2009, 13:27:47 »
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
Firmat - Santa Fe - Argentina

www.TodoPic.net

Solo se tiran piedras, al arbol que tiene frutos...

Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #11 en: 16 de Agosto de 2009, 18:38:02 »
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 Norberto, esa subrutina la coloqué allí a modo de "borrador", pensé que no influiría en el programa. De todos modos las eliminé, pero el problema continúa, olvide aclarar que al compilar el programa en el mplab, este me da una advertencia: "Message[306] D:\T.I\MPLAB\T.I-02\MODELO BASE\T.I-02A\TI-02A.ASM 4655 : Crossing page boundary -- ensure page bits are set", saludos y gracias, por ayudarme.
 

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #12 en: 16 de Agosto de 2009, 23:20:17 »
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.


"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado GRUTTIS

  • PIC10
  • *
  • Mensajes: 26
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #13 en: 17 de Agosto de 2009, 17:52:51 »
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!!!





Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: PROBLEMAS CON PCL, EN PIC16F877
« Respuesta #14 en: 17 de Agosto de 2009, 18:52:39 »
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
  1. org 0x000
  2.  
  3.         clrf PCLATH
  4.  
  5.         pagesel pag1
  6.         call pag1
  7.      
  8.         call pag0
  9.  
  10.         goto $
  11.  
  12. pag0    nop
  13.         nop
  14.         retlw 0x00
  15.  
  16.         org 0x800                 ;vector de pagina 1
  17.         pag1 nop
  18.  
  19.         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 PCLATH0x000
pagesel pag10x001
0x002
call pag10x003
call pag00x004
goto $0x005
pag0 nop0x006
retlw 0x000x007
org 0x800-
pag1 nop0x800
retlw 0xAA0x801

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 FLASHCódigo pseudo-ensamblado:
org 0x000--
clrf PCLATH0x000clrf 0x0A
pagesel pag10x001
0x002
pagesel 0x800
call pag10x003call 0x00
call pag00x004call 0x06
goto $0x005goto 0x05
pag0 nop0x006nop
retlw 0x000x007retlw 0x00
org 0x800--
pag1 nop0x800nop
retlw 0xAA0x801retlw 0xAA

Ahora otra pasada mas, un poco más profunda:

LINEA:DIRECCION FLASHCódigo pseudo-ensamblado:
org 0x000--
clrf PCLATH0x000clrf 0x0A
pagesel pag10x001
0x002
bsf PCLATH,3
bcf PCLATH,4
call pag10x003call 0x00
call pag00x004call 0x06
goto $0x005goto 0x05
pag0 nop0x006nop
retlw 0x000x007retlw 0x00
org 0x800--
pag1 nop0x800nop
retlw 0xAA0x801retlw 0xAA


Un poco más...

LINEA:DIRECCION FLASHCódigo pseudo-ensamblado:
org 0x000--
clrf PCLATH0x000clrf 0x0A
pagesel pag10x001
0x002
bsf 0x0A,3
bcf 0x0A,4
call pag10x003call 0x00
call pag00x004call 0x06
goto $0x005goto 0x05
pag0 nop0x006nop
retlw 0x000x007retlw 0x00
org 0x800--
pag1 nop0x800nop
retlw 0xAA0x801retlw 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 11 bits. Esto significa que puede llamar sólo dentro del rango(decimal): [0;2047].

En los uC que tienen más de 2KWords esto(11 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 13 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 13 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        000 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        000 00000110

Todos juntos: 0100000000110
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.
« Última modificación: 20 de Agosto de 2009, 16:59:15 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.


 

anything