Entender la configuración del 16F88

Buenas:

Quiero entender bien la configuración del PIC 16F88.

Código:
    LIST        P=16F88
    INCLUDE        <P16F88.INC>
     __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF  & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF  & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC
     __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

Hay uno que no se lo que es:
_CCP1_RB0 y el _CCP1_RB3.

¿Qué hace y para qué es?

Por defecto siempre lo dejo en _CCP1_RB0.

Los demás son:
; _CP_OFF: Protección de código DESACTIVADO.
; _DEBUG_OFF: Debug en circuito DESACTIVADO.
; _WRT_PROTECT_OFF: Protección a escritura en memoria de programa DESACTIVADO.
; _CPD_OFF: Protección de código de datos DESACTIVADO.
; _LVP_OFF: Programación en baja tensión DESACTIVADO.
; _BODEN_OFF: Reset por Brown-out DESACTIVADO.
; _MCLRE_ON: Reset por pin externo ACTIVADO.
; _PWRTE_ON: Retraso al reset ACTIVADO.
; _WDT_OFF: Watchdog DESACTIVADO.
; _XT_OSC: Oscilador externo del tipo XT.

; _IESO_OFF: Modo de intercambio de externo a interno DESACTIVADO.
; _FCMEN_OFF: Monitor de CLK DESACTIVADO

 
_CCP1_RB0 o el _CCP1_RB3... con eso le indicas al PIC cual de los dos pines (RB0 o RB3) lo vas a usar para el módulo CCP1.
En caso de ser _CCP1_RB0, entonces este pin estará conectado al módulo y el RB3 no.

Ojo, solo uno de ellos.
 
16f84a-7324.jpg


¿Y para qué es el CCP1 exactamente? Este cuadro parece que dice algo, prefiero tus palabras.
 
CCP o CCP1 como se le conoce dentro del datasheet de este PIC es el módulo "Captura/Comparación/PWM".

La verdad no entiendo porque en el cuadro han separado el PWM del CCP ya que el módulo completo lo conforman esos tres trabajos que puede cumplir el módulo CCP.
Revisa el datasheet que el módulo CCP va desde la página 81 a 85 (83 a 87 del visor pdf).

Igual, si en la configuración asignas el CCP a RB0 o RB3 puedes usarlo como I/O sin problemas a menos que configures el registro de dicho módulo, entonces automáticamente el pin escogido va a trabajar directamente con el CCP.

saludos
 
En un temporizador con el 16F88 no me funciona, si con el 16F84A tengo la configuración así.

Código:
Inicio
    call    LCD_Inicializa
    bcf        STATUS,RP1
    bsf        STATUS,RP0
    clrf    ANSEL
    movlw    b'10000111'                    ; Prescaler de 256 asignado al TMR0.
    movwf    OPTION_REG
    bsf        AjustePulsador                ; Configurados como entradas.
    bsf        IncrementarPulsador
    bcf        SalidaTemporizador            ; Configurados como salidas.
    bcf        Zumbador
    bcf    STATUS,RP1
    bcf    STATUS,RP0
    clrw                                ; Lee la posición 0x00 de memoria EEPROM de datos
    call    EEPROM_LeeDato                ; donde se guarda el tiempo deseado de la última vez
    movwf    TiempoDeseado_L                ; que se ajustó.
    movlw    .1
    call    EEPROM_LeeDato
    movwf    TiempoDeseado_H
    call    ModoTemporizador_OFF        ; Modo de funcionamiento inicial.
    movlw    b'10001000'                    ; Activa interrupciones RBI.
    movwf    INTCON
Principal
    goto    Principal

http://robots-argentina.com.ar/Cerebro_PIC628vs84.htm
 
Funciona a interrupción?... compara el registro INTCON de ambos PIC vas a ver una sorpresa :),
igual para activar interrupción también pon a '1' el bit 6 del registro INTCON (PEIE).
 
DataSheet (Hoja de datos)
PIC 16F84A y PIC 16F88.

¿Por qué lo dices o cómo es que llegas a esa conclusión?
Ni se me ocurría mirar esa parte.

Este es el código ya en el PIC 16F88.
Código:
;********************************** INT_Temporizador.asm 
;
;
; Programa de control para un temporizador digital de precisión. La programación del tiempo
; de temporización se realiza mediante dos pulsadores: "AJUSTE" y "ON/INCREM". Funcionamiento:
;     -    En estado de reposo la salida del temporizador está apagada y el pantalla aparece el
;        tiempo deseado para la próxima temporización.
;     - Si se pulsa "ON/INCREM" comienza la temporización.
;     - Cuando acaba la temporización pasa otra vez a reposo.
;     -    Si pulsa "AJUSTE" antes que haya acabado el tiempo de temporización actúa como pulsador
;        de paro: interrumpe la temporización, apaga la carga y pasa al estado de reposo.
;
; Para ajustar la temporización al tiempo deseado. 
;     -    Pulsa "AJUSTE" y ajusta el tiempo deseado mediante el pulsador "ON/INCREM".
;     -    Se vuelve a pulsar "AJUSTE" y pasa a modo de reposo.
;
; Al apagar el sistema debe conservar el tiempo de temporización deseado para la próxima vez
; que se encienda.
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F88
    INCLUDE        <P16F88.INC>
     __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC
     __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

    CBLOCK  0x20
    TiempoDeseado_H                ; El tiempo deseado de temporización.
    TiempoDeseado_L
    Tiempo_H                        ; Tiempo que resta de temporización.
    Tiempo_L
    FlagsModos                    ; Guarda los flags con los diferentes
    ENDC                        ; modos de funcionamiento.

    ORG    0x2100                    ; Corresponde a la dirección 0 de la zona
                                ; EEPROM de datos. Aquí se va a guardar el
    DE    0x00                    ; tiempo de temporización deseado.

#DEFINE  F_Temporizador_ON        FlagsModos,2
#DEFINE  F_Temporizador_Ajuste    FlagsModos,1
#DEFINE  F_Temporizador_OFF        FlagsModos,0

#DEFINE  SalidaTemporizador     PORTB,1        ; Salida donde se conecta la carga.
#DEFINE  Zumbador                 PORTB,2        ; Salida donde se conecta el zumbador.
#DEFINE  AjustePulsador            PORTB,7        ; Los pulsadores están conectados a estas
#DEFINE  IncrementarPulsador    PORTB,6        ; líneas del Puerto B.

; ZONA DE CÓDIGOS ********************************************************************

    ORG     0
    goto    Inicio
    ORG    4
    goto    ServicioInterrupcion

Mensajes
    addwf    PCL,F
Mensaje_ON
    DT "   Contando...", 0x00
Mensaje_Ajuste
    DT "Tiempo deseado:", 0x00
Mensaje_OFF
    DT "     PARADO", 0x00
Mensaje_Arriba_ON

Mensaje_Arriba_OFF

Mensaje_Abajo_ON

Mensaje_Abajo_OFF

; Instrucciones de inicialización. ------------------------------------------------------
;
Inicio
    call    LCD_Inicializa
    bcf        STATUS,RP1
    bsf        STATUS,RP0
    clrf    ANSEL
    movlw    b'10000111'                    ; Prescaler de 256 asignado al TMR0.
    movwf    OPTION_REG
    bsf        AjustePulsador                ; Configurados como entradas.
    bsf        IncrementarPulsador
    bcf        SalidaTemporizador            ; Configurados como salidas.
    bcf        Zumbador
    bcf        STATUS,RP1
    bcf        STATUS,RP0
    clrw                                ; Lee la posición 0x00 de memoria EEPROM de datos
    call    EEPROM_LeeDato                ; donde se guarda el tiempo deseado de la última vez
    movwf    TiempoDeseado_L                ; que se ajustó.
    movlw    .1
    call    EEPROM_LeeDato
    movwf    TiempoDeseado_H
    call    ModoTemporizador_OFF        ; Modo de funcionamiento inicial.
    movlw    b'10001000'                    ; Activa interrupciones RBI.
    movwf    INTCON
Principal
    goto    Principal

; Subrutina "ServicioInterrupcion" ------------------------------------------------------
;
; Detecta qué ha producido la interrupción y ejecuta la subrutina de atención correspondiente.

ServicioInterrupcion
    btfsc    INTCON,TMR0IF
    call    Temporizador
    btfss    INTCON,RBIF                    ; Si es una interrupción RBI lee los pulsadores.
    goto    FinInterrupcion
    btfss    AjustePulsador                ; ¿Está presionado el pulsador de "AJUSTE"?.
    call    CambiarModo                    ; Sí, pues salta a la subrutina correspondiente.
    btfsc    IncrementarPulsador            ; ¿Pulsado "ON/INCREM"?.
    goto    FinInterrupcion                ; No, pues salta al final y sale.
;
    call    Retardo_20ms                ; Espera que se estabilice el nivel de tensión.
    btfsc    IncrementarPulsador            ; Si es un rebote del pulsador "ON/INCREM" sale fuera.
    goto    FinInterrupcion
    btfsc    F_Temporizador_OFF            ; ¿Estaba en reposo cuando pulsó "ON/INCREM"?
    call    ModoTemporizador_ON            ; Sí, pues comienza la temporización.
    btfsc    F_Temporizador_Ajuste        ; ¿Estaba ajustando tiempo?
    call    IncrementarTiempoDeseado    ; Sí, pues pasa a incrementar el tiempo deseado.
FinInterrupcion
    bcf        INTCON,RBIF                    ; Limpia los flags de reconocimiento.
    bcf        INTCON,TMR0IF
    retfie

; Subrutinas "CambiarModo" y todas las de MODO de funcionamiento ------------------------
;
; Subrutina de atención a la interrupción producida al presionar el pulsador "AJUSTE" que 
; cambia el modo de funcionamiento.

; Hay identificados tres modos de funcionamiento que se diferencian mediante los tres flags:
;    A)    Modo "Temporizador_OFF" o estado inicial. A él se pasa en el estado inicial cada vez
;        que termina una temporización o cuando se aborta la temporización sin esperar a que
;        finalice. Reconocido por el flag F_Temporizador_OFF, bit 0 del registro FlagsModos.
;         una temporización  o cada vez que se aborta la temporización sin esperar a que finalice.
;    B)    Modo "Temporizador_Ajuste", donde se ajusta la temporización deseada cuando funcione
;        como temporizador. Reconocido por el flag F_Temporizador_Ajuste, bit 1 del FlagsModos.
;    C)    Modo "Temporizador_ON", la salida está activada mientras dure la temporización.
;        Reconocido por el flag F_Temporización_ON, que es el bit 2 del registro FlagsModos.
;
; El programa consigue que esté activado uno sólo de los flags anteriores.

; El contenido del registro (FlagsModos) diferencia los siguientes modos de funcionamiento:
; - (FlagsModos)=b'00000001'. Está en el modo "Temporizador_OFF", en reposo.
; - (FlagsModos)=b'00000010'. Está en el modo "Temporizador_Ajuste", ajustando tiempo deseado.
; - (FlagsModos)=b'00000100'. Está en el modo "Temporizador_ON", activa la carga y temporizador.
;
; Al pulsar "AJUSTE" pueden darse tres casos:
; - Si estaba en modo "Temporizador_OFF", pasa a modo "Temporizador_Ajuste".
; - Si estaba en modo "Temporizador_Ajuste", pasa a modo "Temporizador_OFF", pero antes salva
;   el tiempo de temporización deseado en la EEPROM de datos.       
; - Si estaba en modo "Temporizador_ON", pasa a modo "Temporizador_OFF". (Interrumpe la
;   temporización).

CambiarModo
    call    PitidoCorto                    ; Cada vez que pulsa origina un pitido. 
    btfsc    AjustePulsador                ; Si es un rebote sale fuera.
    goto    EsperaDejePulsar
    btfsc    F_Temporizador_OFF            ; ¿Está en reposo?
    goto    ModoTemporizador_Ajuste        ; Sí, pues pasa a ajustar la temporización.
    btfss    F_Temporizador_Ajuste        ; ¿Está ajustando?
    goto    ModoTemporizador_OFF        ; No, pues pasa a reposo.
                                        ; Sí, pues antes de pasar a reposo salva en la
    clrw                                ; posición 00h de memoria EEPROM de datos el tiempo 
    movwf    EEADR                        ; de temporización deseado. Se conserva aunque se
    movf    TiempoDeseado_L,W                ; apague la alimentación.
    call    EEPROM_EscribeDato
    incf    EEADR,F
    movf    TiempoDeseado_H,W
    call    EEPROM_EscribeDato
ModoTemporizador_OFF
    bcf        SalidaTemporizador            ; Apaga la carga y resetea tiempo deseado.
    call    Pitido
    movlw    b'00000001'                ; Actualiza el registro FlagsModos pasando al
    movwf    FlagsModos                ; modo inicial "Temporizador_OFF".
    bcf        INTCON,TMR0IF                ; Prohíbe las interrupciones del TMR0.
    movf    TiempoDeseado_L,W            ; Repone otra vez el tiempo que se desea para la 
    movwf    Tiempo_L                    ; próxima temporización.
    movf    TiempoDeseado_H,W
    movwf    Tiempo_H
    call    LCD_Borra                ; Borra la pantalla.
    movlw    Mensaje_OFF                ; En pantalla el mensaje correspondiente.
    goto    FinCambiarModo

ModoTemporizador_Ajuste
    bcf        SalidaTemporizador        ; Apaga la carga
    movlw    b'00000010'                ; Actualiza el registro FlagsModos pasando al
    movwf    FlagsModos                ; modo "Temporizador_Ajuste".
    clrf    Tiempo_L                    ; Resetea el tiempo.
    clrf    Tiempo_H
    clrf    TiempoDeseado_L
    clrf    TiempoDeseado_H
    bcf        INTCON,TMR0IF                ; Prohíbe las interrupciones del TMR0.
    call    LCD_Borra
    movlw    Mensaje_Ajuste            ; En pantalla el mensaje correspondiente.
    goto    FinCambiarModo

ModoTemporizador_ON
    movf    TiempoDeseado_H,F            ; Si el tiempo deseado es cero pasa a modo
    btfss    STATUS,Z                ; de trabajo "Temporizador_OFF".
    goto    ModoTemporizador_ON_Sigue
    movf    TiempoDeseado_L,F
    btfsc    STATUS,Z
    goto    ModoTemporizador_OFF
ModoTemporizador_ON_Sigue
    movf    TiempoDeseado_L,W
    movwf    Tiempo_L
    movf    TiempoDeseado_H,W
    movwf    Tiempo_H
    call    PitidoCorto
    movlw    b'00000100'                ; Actualiza el registro FlagsModos pasando al
    movwf    FlagsModos                ; modo "Temporizador_ON".
    movlw    TMR0_Carga50ms            ; Carga el TMR0.
    movwf    TMR0
    movlw    CARGA_1s                ; Y el registro cuyo decremento contará los
    movwf    Registro50ms            ; segundos.
    bsf        INTCON,TMR0IF                ; Autoriza las interrupciones de TMR0.
    call    LCD_Borra
    bsf        SalidaTemporizador        ; Enciende la carga.
    movlw    Mensaje_ON                ; En pantalla el mensaje correspondiente.
FinCambiarModo
    call    LCD_Mensaje
    call    VisualizaTiempo
EsperaDejePulsar
    btfss    AjustePulsador            ; Espera deje de pulsar.
    goto    EsperaDejePulsar
    return

; Subrutina "Temporizador" ----------------------------------------------------------------
;
; Esta subrutina va decrementando el tiempo de temporización y visualizándolo en la pantalla.
; Se ejecuta debido a la petición de interrupción del Timer 0 cada 50 ms exactos, comprobado
; experimentalmente con la ventana "Stopwatch" del simulador del MPLAB.

    CBLOCK
    Registro50ms                    ; Guarda los incrementos cada 50 ms.
    ENDC

TMR0_Carga50ms    EQU    d'256'-d'195'            ; Para conseguir la interrupción cada 50 ms.
CARGA_1s        EQU    d'20'            ; Leerá cada segundo (20 x 50ms = 1000 ms).    

Temporizador
    call    Retardo_50micros        ; Ajuste fino de 71 microsegundos para
    call    Retardo_20micros        ; ajustar a 50 milisegundos exactos.
    nop
      movlw    TMR0_Carga50ms            ; Carga el Timer0.
    movwf    TMR0
    decfsz    Registro50ms,F            ; Decrementa el contador.
    goto    FinTemporizador            ; No ha pasado 1 segundo y por tanto sale.
    movlw    CARGA_1s                ; Repone el contador nuevamente.
    movwf    Registro50ms
    btfss    F_Temporizador_ON        ; Si no está en modo "Temporizador_ON" sale
    goto    FinTemporizador            ; fuera.
    decf    Tiempo_L,F
    movlw    0xFF
    xorwf    Tiempo_L,W
    btfsc    STATUS,Z
    decf    Tiempo_H,F

    movf    Tiempo_L,F
    btfss    STATUS,Z
    goto    VisualizaContador        ; Visualiza el tiempo restante.
    movf    Tiempo_H,W
    btfss    STATUS,Z
    goto    VisualizaContador        ; Visualiza el tiempo restante.
    bcf        SalidaTemporizador        ; Apaga la salida
    call    VisualizaTiempo            ; Visualiza cero segundos en la pantalla.
    call    Pitido                    ; Tres pitidos indican final de la temporización.
    call    Retardo_500ms
    call    Pitido
    call    Retardo_500ms
    call    PitidoLargo
    call    Retardo_500ms
    call    ModoTemporizador_OFF    ; Acabó la temporización.
    goto    FinTemporizador
VisualizaContador
    call    VisualizaTiempo
FinTemporizador
    return

; Subrutina "VisualizaTiempo" -----------------------------------------------------------------
;
; Visualiza el registro Tiempo en formato "Minutos:Segundos". Así por ejemplo, si
; (Tiempo)=124 segundos en la segunda línea de la pantalla visualiza " 2:04", ya que 124
; segundos es igual a 2 minutos más 4 segundos.
;
VisualizaTiempo
    movlw    .5                        ; Para centrar visualización en la
    call    LCD_PosicionLinea2        ; segunda línea.
    movf    Tiempo_L,W                ; Convierte el tiempo deseado (y expresado sólo en
    movwf    MinutosSegundos_TiempoL    ; segundos) a minutos y segundos.
    movf    Tiempo_H,W
    movwf    MinutosSegundos_TiempoH
    call    MinutosSegundos            
    movf    TemporizadorMinutos,W    ; Visualiza los minutos.
    call    BIN_a_BCD                ; Lo pasa a BCD.
    call    LCD_Byte
    movlw    ':'                        ; Visualiza dos puntos.
    call    LCD_Caracter
    movf    TemporizadorSegundos,W    ; Visualiza los segundos.
    call    BIN_a_BCD                ; Lo pasa a BCD.
    goto    LCD_ByteCompleto
    return

;*************************
; Aquí está la subrutina MinutosSegundos modificada para manejar
; números de 2 bytes. Ésta sí úsala en lugar de la otra.
MinutosSegundos
    CBLOCK
        TemporizadorSegundos, TemporizadorMinutos
        MinutosSegundos_TiempoH
        MinutosSegundos_TiempoL
    ENDC
    
    clrf    TemporizadorMinutos        ; Borra los minutos.
; Le resta 60 al tiempo que está almacenado en las variables
; MinutosSegundos_TiempoH y MinutosSegundos_TiempoL.
MinutosSegundos_Resta60
    movlw    .60
    subwf    MinutosSegundos_TiempoL,F    ; Resta 60 del byte bajo.
    btfss    STATUS,C        ; ¿Es negativo?
    decf    MinutosSegundos_TiempoH,F    ; Sí, entonces decrementa en
                                        ; 1 el byte alto.
    btfsc    MinutosSegundos_TiempoH,7    ; ¿El resultado es negativo?
    goto    Fin_MinutosSegundos        ; Sí, pues ya terminamos de convertir.

    incf    TemporizadorMinutos,F        ; Incrementa en 1 la cantidad de minutos.
    goto    MinutosSegundos_Resta60    ; Sigue revisando si hay más minutos.

Fin_MinutosSegundos
    movlw    .60        ; Le suma 60 a la cantidad de tiempo ya que 
                    ; previamente se le restó 60 y el resultado
                    ; fué negativo.
    addwf    MinutosSegundos_TiempoL,W
    movwf    TemporizadorSegundos
    return

; Subrutina "IncrementarTiempoDeseado" --------------------------------------------------
;
; Subrutina de atención a la interrupción por cambio de la línea RB6 a la cual se ha
; conectado el pulsador "INCREMENTAR".
; Estando en el modo "Temporizador_Ajustar" incrementa el valor del tiempo deseado
; expresado en segundos en intervalos de 5 segundos y hasta un máximo de 255 segundos.
;
SALTO_INCR    EQU    .5

IncrementarTiempoDeseado
    call    PitidoCorto                ; Cada vez que pulsa se oye un pitido.
    movlw    SALTO_INCR                ; Incrementa el tiempo deseado de temporización
    addwf    Tiempo_L,F                ; saltos de SALTO_INCR segundos.
    btfsc    STATUS,C
    incf    Tiempo_H,F
    call    VisualizaTiempo            ; Visualiza mientras espera que deje de pulsar.
    call    Retardo_200ms
    btfss    IncrementarPulsador        ; Mientras permanezca pulsado,
    goto    IncrementarTiempoDeseado ; incrementa el dígito.
    movf    Tiempo_L,W                ; Actualiza el tiempo deseado.
    movwf    TiempoDeseado_L            ; Este es el tiempo deseado.
    movf    Tiempo_H,W
    movwf    TiempoDeseado_H
    return
    
; Subrutinas "PitidoLargo", "Pitido" y "PitidoCorto" -------------------------------------
;
PitidoLargo
    bsf        Zumbador
    call    Retardo_500ms
Pitido
    bsf        Zumbador
    call    Retardo_200ms
PitidoCorto
    bsf        Zumbador
    call    Retardo_20ms
    bcf        Zumbador
    return
;
    INCLUDE  <RETARDOS.INC>
    INCLUDE  <BIN_BCD.INC>
    INCLUDE  <LCD_4BIT.INC>
    INCLUDE  <LCD_MENS.INC>
    INCLUDE  <EEPROM.INC>
    END
Recuerdo que el INTCON del 16F84A al pasarlo al 16F88 tuve que adaptar el bit 2 T0IF por TMR0IF. ¿Si es lo mismo para qué lo cambian y confunden a la gente? ;)

intcom.jpg

En esta parte del código la sorpresa que me llevo ahora es esta.

Código:
;***************************** Librería "EEPROM.INC" **********************************
;
;    ====================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS".
;      E. Palacios, F. Remiro y L. López.        www.pic16f84a.com
;       Editorial Ra-Ma.  www.ra-ma.es
;    ====================================================================
;
; Estas subrutinas permiten realizar las tareas básicas de escritura y lectura de la
; memoria EEPROM de datos del PIC.
;
; Subrutina "EEPROM_LeeDato" ------------------------------------------------------------
;
; El microcontrolador lee el dato que hay escrito en la posición de la EEPROM del PIC apuntada
; por el contenido del registro de trabajo W. El resultado se proporciona en el mismo W.
;
; Entrada: En (W) la dirección de la memoria EEPROM a leer.
; Salida :  En (W) el byte leído.

EEPROM_LeeDato
    bsf        STATUS,RP1
    bcf        STATUS,RP0                ; Asegura que trabaja con el Banco 2.
    movwf    EEADR                ; Dirección a leer.
    bsf        STATUS,RP1
    bsf        STATUS,RP0                ; Banco 3.
    bsf        EECON1,RD            ; Orden de lectura.
EEPROM_SigueLeyendo
    btfsc    EECON1,RD            ; El PIC indica que ha terminado la lectura
    goto    EEPROM_SigueLeyendo    ; poniendo en bajo este bit.
    bsf        STATUS,RP1
    bcf        STATUS,RP0                ; Banco 2.
    movf    EEDATA,W            ; El byte leído al registro W.
    return

; Subrutina "EEPROM_EscribeDato" --------------------------------------------------------
;
; Escribe el dato introducido en el registro de trabajo W en la posición de memoria EEPROM del
; PIC apuntada por el registro EEADR.
;
; Como altera el valor del registro INTCON al posicionar el flag GIE, éste se debe guardar al
; principio de la subrutina y restaurarlo al final.
;
; Entradas:    En el registro EEADR la dirección de la memoria EEPROM a escribir.
;        En el registro W el byte a escribir.
;
    CBLOCK
    EEPROM_GuardaINTCON
    ENDC

EEPROM_EscribeDato
    bsf        STATUS,RP1
    bcf        STATUS,RP0                ; Asegura que trabaja con el Banco 2.
    movwf    EEDATA                ; El byte a escribir.
    movf    INTCON,W            ; Reserva el valor anterior de INTCON
    movwf    EEPROM_GuardaINTCON
    bsf        STATUS,RP1
    bsf        STATUS,RP0                ; Acceso al Banco 3.
    bcf        INTCON,GIE            ; Deshabilita todas las interrupciones.
    bsf        EECON1,WREN            ; Habilita escritura.
;
; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROM:
;
    movlw    0x55
    movwf    EECON2
    movlw    0xAA
    movwf    EECON2
    bsf        EECON1,WR            ; Inicia la escritura.
EEPROM_TerminaEscribir
    btfsc    EECON1,WR            ; Comprueba que termina de escribir en la EEPROM.
    goto    EEPROM_TerminaEscribir
    bcf        EECON1,WREN            ; Desautoriza la escritura en EEPROM.
    bcf        EECON1,EEIF            ; Limpia este flag.
    bcf        STATUS,RP1
    bcf        STATUS,RP0                ; Acceso al Banco 0.
    movf    EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
    movwf    INTCON
    return
Donde pone:
bcf EECON1,EEIF del bit 4 para el 16F84A en el 16F88 no está, parece ser que es del F88 está en el bit 7 y se llama EEPGD con lo cual debe quedar así:

bcf EECON1,EEPGD.

Lo que no entiendo es que me lo ejecuta sin problemas como hice desde el principio, pero no me funciona en el Proteus.

Voy hacer pruebas, no creo que tenga nada que ver con la EERPOM, por algo se empieza.







Edito:

Puse a '1' el bit 6 del registro INTCON (PEIE) que dijiste y no pasa nada.

Código:
Inicio
    call    LCD_Inicializa
    bcf        STATUS,RP1
    bsf        STATUS,RP0
    clrf    ANSEL
    movlw    b'10000111'                    ; Prescaler de 256 asignado al TMR0.
    movwf    OPTION_REG
    bsf        AjustePulsador                ; Configurados como entradas.
    bsf        IncrementarPulsador
    bcf        SalidaTemporizador            ; Configurados como salidas.
    bcf        Zumbador
    bcf        STATUS,RP1
    bcf        STATUS,RP0
    clrw                                ; Lee la posición 0x00 de memoria EEPROM de datos
    call    EEPROM_LeeDato                ; donde se guarda el tiempo deseado de la última vez
    movwf    TiempoDeseado_L                ; que se ajustó.
    movlw    .1
    call    EEPROM_LeeDato
    movwf    TiempoDeseado_H
    call    ModoTemporizador_OFF        ; Modo de funcionamiento inicial.
    movlw    b'11001000'                    ; Activa interrupciones RBI.
    movwf    INTCON
Principal
    goto    Principal

Dejo como descarga ejemplo completo con simulación proteus incluido para que lo veas.
 

Adjuntos

  • Temporizador_Insoladora_16F88_v0.4.zip
    67.5 KB · Visitas: 12
Última edición:
bcf EECON1,EEPGD.
No, este bit es para decirle al PIC que memoria se va a leer/escribir, recuerda que en el 16F88 también se puede leer/escribir la memoria de programa y se hace por ese método; revisa la hoja de datos del F88 (pag 29) que hay un ejemplo de escritura en la EEPROM. El flag de la eeprom en el F88 se usa solo para interrupción y esta en el registro PIR2 (el bit de enable esta en el registro PIE2).

----
 
Hola:

No sabía que los PIC también se graba en memoria flash así mismo, que yo sepa es en la RAM y EERPOM, no memoria de programa.

El flag de la eeprom en el F88 se usa solo para interrupción y esta en el registro PIR2 (el bit de enable esta en el registro PIE2).

Es verdad, han cambiado todo. Así estoy. Menos mal que con el C no ocurren nada de estas cosas, claro que estoy centrado en el .asm.

Voy a investigar y te cuento...

salu2.
 
Hola:
No sabía que los PIC también se graba en memoria flash así mismo, que yo sepa es en la RAM y EERPOM, no memoria de programa.
Si de echo varios modelos pueden hacer eso, si en la hoja de datos dice algo como "Processor read/write access to program memory" ya se supone que se puede leer/escribir a si mismo y también aumentan los registros asociados con la EEPROM.
Solo he visto que lo usen para bootloaders y no dentro de un programa funcional... eso cuando lo entendí me vino a la cabeza "neuronas!!! :LOL:" ¿puedo hacer que el PIC aprenda? :LOL:, claro que implementar eso es complicado y pues no hay muchos motivos para hacer eso... lograr que el pic se actualice por si mismo re-escribiendo partes de código que ya no necesite :D...

Respecto al tema, no logro que compile (no encuentra los .inc)... me acuerdo del asm pero no mucho del mplab...

saludos
 
Hice algo como esto abajo según dice en la página 16 del DataSheet. Puse en el banco 0 PIR2.

Código:
EEPROM_TerminaEscribir
    btfsc    EECON1,WR            ; Comprueba que termina de escribir en la EEPROM.
    goto    EEPROM_TerminaEscribir
    bcf        EECON1,WREN            ; Desautoriza la escritura en EEPROM.
    bcf        STATUS,RP1
    bcf        STATUS,RP0                ; Acceso al Banco 0.
    bcf        PIR2,EEIF            ; Limpia este flag. (EEIF)
    movf    EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
    movwf    INTCON
    return

Para entenderte mejor sobre el PIE2. ¿Qué le pasa a ese?
 
Última edición:
En los registros PIE están los bit de habilitación cuando se quiere usar interrupción con los periféricos que contiene (Peripheral interrupt enable); en los registro PIR están los flag de interrupción de los periféricos.

El flag EEIF se pone a '1' cuando la operación de escritura eeprom a finalizado y debe ser borrado manualmente, ahora lo que no se es si el EEIF también funciona sin interrupción de parte del módulo eeprom; en caso que fuera así entonces también se puede consultar al bit EEIF en reemplazo del EECON1,WR... intenta revisar eso en el MPLAB simulando en la ventana del Watch Window.

Pero en el ejemplo creo que no es necesario borrar el EEIF ya que ni lo usas, pero eso si! asegúrate de volver al banco respectivo antes de return.
 
Última edición:
La EEPROM del 16F84A sin modificar es esta:

Código:
;***************************** Librería "EEPROM.INC" **********************************
;
;    ====================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS".
;      E. Palacios, F. Remiro y L. López.        www.pic16f84a.com
;       Editorial Ra-Ma.  www.ra-ma.es
;    ====================================================================
;
; Estas subrutinas permiten realizar las tareas básicas de escritura y lectura de la
; memoria EEPROM de datos del PIC.
;
; Subrutina "EEPROM_LeeDato" ------------------------------------------------------------
;
; El microcontrolador lee el dato que hay escrito en la posición de la EEPROM del PIC apuntada
; por el contenido del registro de trabajo W. El resultado se proporciona en el mismo W.
;
; Entrada: En (W) la dirección de la memoria EEPROM a leer.
; Salida :  En (W) el byte leído.

EEPROM_LeeDato
    bcf        STATUS,RP0            ; Asegura que trabaja con el Banco 0.
    movwf    EEADR                ; Dirección a leer.
    bsf        STATUS,RP0            ; Banco 1.
    bsf        EECON1,RD            ; Orden de lectura.
EEPROM_SigueLeyendo
    btfsc    EECON1,RD            ; El PIC indica que ha terminado la lectura
    goto    EEPROM_SigueLeyendo    ; poniendo en bajo este bit.
    bcf        STATUS,RP0            ; Banco 0.
    movf    EEDATA,W            ; El byte leído al registro W.
    return

; Subrutina "EEPROM_EscribeDato" --------------------------------------------------------
;
; Escribe el dato introducido en el registro de trabajo W en la posición de memoria EEPROM del
; PIC apuntada por el registro EEADR.
;
; Como altera el valor del registro INTCON al posicionar el flag GIE, éste se debe guardar al
; principio de la subrutina y restaurarlo al final.
;
; Entradas:    En el registro EEADR la dirección de la memoria EEPROM a escribir.
;        En el registro W el byte a escribir.
;
    CBLOCK
    EEPROM_GuardaINTCON
    ENDC

EEPROM_EscribeDato
    bcf        STATUS,RP0            ; Asegura que trabaja con el Banco 0.
    movwf    EEDATA                ; El byte a escribir.
    movf    INTCON,W            ; Reserva el valor anterior de INTCON
    movwf    EEPROM_GuardaINTCON
    bsf        STATUS,RP0            ; Acceso al Banco 1.
    bcf        INTCON,GIE            ; Deshabilita todas las interrupciones.
    bsf        EECON1,WREN            ; Habilita escritura.
;
; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROM:
;
    movlw    0x55
    movwf    EECON2
    movlw    0xAA
    movwf    EECON2
    bsf        EECON1,WR            ; Inicia la escritura.
EEPROM_TerminaEscribir
    btfsc    EECON1,WR            ; Comprueba que termina de escribir en la EEPROM.
    goto    EEPROM_TerminaEscribir
    bcf        EECON1,WREN            ; Desautoriza la escritura en EEPROM.
    bcf        EECON1,EEIF            ; Limpia este flag.
    bcf        STATUS,RP0            ; Acceso al Banco 0.
    movf    EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
    movwf    INTCON
    return

;
La que he modificado es esta otra para el 16F88.

Código:
;***************************** Librería "EEPROM.INC" **********************************
;
;
; Estas subrutinas permiten realizar las tareas básicas de escritura y lectura de la
; memoria EEPROM de datos del PIC.
;
; Subrutina "EEPROM_LeeDato" ------------------------------------------------------------
;
; El microcontrolador lee el dato que hay escrito en la posición de la EEPROM del PIC apuntada
; por el contenido del registro de trabajo W. El resultado se proporciona en el mismo W.
;
; Entrada: En (W) la dirección de la memoria EEPROM a leer.
; Salida :  En (W) el byte leído.

EEPROM_LeeDato
    bsf        STATUS,RP1
    bcf        STATUS,RP0                ; Asegura que trabaja con el Banco 2.
    movwf    EEADR                ; Dirección a leer.
    bsf        STATUS,RP1
    bsf        STATUS,RP0                ; Banco 3.
    bsf        EECON1,RD            ; Orden de lectura.
EEPROM_SigueLeyendo
    btfsc    EECON1,RD            ; El PIC indica que ha terminado la lectura
    goto    EEPROM_SigueLeyendo    ; poniendo en bajo este bit.
    bsf        STATUS,RP1
    bcf        STATUS,RP0                ; Banco 2.
    movf    EEDATA,W            ; El byte leído al registro W.
    return

; Subrutina "EEPROM_EscribeDato" --------------------------------------------------------
;
; Escribe el dato introducido en el registro de trabajo W en la posición de memoria EEPROM del
; PIC apuntada por el registro EEADR.
;
; Como altera el valor del registro INTCON al posicionar el flag GIE, éste se debe guardar al
; principio de la subrutina y restaurarlo al final.
;
; Entradas:    En el registro EEADR la dirección de la memoria EEPROM a escribir.
;        En el registro W el byte a escribir.
;
    CBLOCK
    EEPROM_GuardaINTCON
    ENDC

EEPROM_EscribeDato
    bsf        STATUS,RP1
    bcf        STATUS,RP0                ; Asegura que trabaja con el Banco 2.
    movwf    EEDATA                ; El byte a escribir.
    movf    INTCON,W            ; Reserva el valor anterior de INTCON
    movwf    EEPROM_GuardaINTCON
    bsf        STATUS,RP1
    bsf        STATUS,RP0                ; Acceso al Banco 3.
    bcf        INTCON,GIE            ; Deshabilita todas las interrupciones.
    bsf        EECON1,WREN            ; Habilita escritura.
;
; El fabricante especifica que hay que seguir esta secuencia para escritura en EEPROM:
;
    movlw    0x55
    movwf    EECON2
    movlw    0xAA
    movwf    EECON2
    bsf        EECON1,WR            ; Inicia la escritura.
EEPROM_TerminaEscribir
    btfsc    EECON1,WR            ; Comprueba que termina de escribir en la EEPROM.
    goto    EEPROM_TerminaEscribir
    bcf        EECON1,WREN            ; Desautoriza la escritura en EEPROM.
    bcf        STATUS,RP1
    bcf        STATUS,RP0                ; Acceso al Banco 0.
    bcf        PIR2,EEIF            ; Limpia este flag. (EEIF)
    movf    EEPROM_GuardaINTCON,W ; Restaura el valor anterior de INTCON.
    movwf    INTCON
    return

;
Sin-título-1.png

No se lo que hago que a veces no salgo de esta parte. Se queda como bloqueado y no puedo seguir para ver bien la EEPROM.
p.png
 
No se lo que hago que a veces no salgo de esta parte. Se queda como bloqueado y no puedo seguir para ver bien la EEPROM.
Usa la ventana del "Stimulus" que está en "Debugger > Stímulus > New WorkBook", ahí configuras los pines digitales que estás usando como entradas junto a la acción o estado del pin, por decir "Set High".
 
Me funciona loque dices, no consigo llegar donde pone guardar la EEPROM. No logro llegar a esta perte del código principal.

Código:
CambiarModo
    call    PitidoCorto                    ; Cada vez que pulsa origina un pitido. 
    btfsc    AjustePulsador                ; Si es un rebote sale fuera.
    goto    EsperaDejePulsar
    btfsc    F_Temporizador_OFF            ; ¿Está en reposo?
    goto    ModoTemporizador_Ajuste        ; Sí, pues pasa a ajustar la temporización.
    btfss    F_Temporizador_Ajuste        ; ¿Está ajustando?
    goto    ModoTemporizador_OFF        ; No, pues pasa a reposo.
                                        ; Sí, pues antes de pasar a reposo salva en la
    clrw                                ; posición 00h de memoria EEPROM de datos el tiempo 
    movwf    EEADR                        ; de temporización deseado. Se conserva aunque se
    movf    TiempoDeseado_L,W                ; apague la alimentación.
    call    EEPROM_EscribeDato
    incf    EEADR,F
    movf    TiempoDeseado_H,W
    call    EEPROM_EscribeDato
 
Última edición:
Funciona a interrupción?... compara el registro INTCON de ambos PIC vas a ver una sorpresa :),
igual para activar interrupción también pon a '1' el bit 6 del registro INTCON (PEIE).

Lo he activado y no pasa nada.

No, este bit es para decirle al PIC que memoria se va a leer/escribir, recuerda que en el 16F88 también se puede leer/escribir la memoria de programa y se hace por ese método; revisa la hoja de datos del F88 (pag 29) que hay un ejemplo de escritura en la EEPROM. El flag de la eeprom en el F88 se usa solo para interrupción y esta en el registro PIR2 (el bit de enable esta en el registro PIE2).

----


dddddddddddddddddd-9807.png


¿Dónde quieres que active exactamente el famoso PIE2?

DataSheet:
PIC16F88

Lo he hecho funcionar mejor el programa, por ejemplo, puedo ponerlo a modo "Tiempo deseado:", luego a incrementar el tiempo y ponerlo a modo normal.

Lo que no puedo hacer es activar el tiempo que ya tengo deseado, es decir, que no me hace la cuenta atrás. Puedes descargar el código fuente y el de proteus para que lo pruebes.

Saludo.
 

Adjuntos

  • Temporizador Insoladora 16F88_v5.zip
    67.4 KB · Visitas: 13
Hola, ya con más tiempo...
La V5 de tu código es el actual?. En la simulación, al parecer no se controla bien el INTCON al momento de programar el tiempo:
- Encontré que el bit EEIE del registro INTCON se pone a '0' luego de apretar un par de veces el pulsador en RB7, es importante y sin el bit a '1' la interrupción no va a funcionar.
No debería pero agrega esto.
Código:
bsf		INTCON,PEIE
retfie

- También el bit RBIE queda a '0' luego de programar, nunca más sucede una interrupción y en la simulación en el proteus los flag no se borran luego de programar.

Hay algo donde se pierde el control con el registro INTCON pero no se donde!! :confused:
 
Hola, ya con más tiempo...
La V5 de tu código es el actual?.

Sí.

En la simulación, al parecer no se controla bien el INTCON al momento de programar el tiempo:
- Encontré que el bit EEIE del registro INTCON se pone a '0' luego de apretar un par de veces el pulsador en RB7, es importante y sin el bit a '1' la interrupción no va a funcionar.
No debería pero agrega esto.
Código:
bsf        INTCON,PEIE
retfie
¿Por qué no debería?

¿Qué es lo que te preocupa?

¿Quieres decir que al pulsar el botón RB7 debe ponerse a 1?

Voy a poner ese código si te refieres que va hacia el programa principal.

Código:
Inicio
    call    LCD_Inicializa
    BANKSEL    ANSEL
    clrf    ANSEL
    BANKSEL OPTION_REG
    movlw    b'10000111'                    ; Prescaler de 256 asignado al TMR0.
    movwf    OPTION_REG
    bsf        AjustePulsador                ; Configurados como entradas.
    bsf        IncrementarPulsador
    bcf        SalidaTemporizador            ; Configurados como salidas.
    bcf        Zumbador
    BANKSEL    PORTA
    clrw                                ; Lee la posición 0x00 de memoria EEPROM de datos
    call    EEPROM_LeeDato                ; donde se guarda el tiempo deseado de la última vez
    movwf    TiempoDeseado_L                ; que se ajustó.
    movlw    .1
    call    EEPROM_LeeDato
    movwf    TiempoDeseado_H
    call    ModoTemporizador_OFF        ; Modo de funcionamiento inicial.
    movlw    b'10001000'                    ; Activa interrupciones RBI.
    movwf    INTCON
    BANKSEL    INTCON
    bsf        INTCON, PEIE                
    BANKSEL    PORTA ; NADA.
Principal
    goto    Principal
- También el bit RBIE queda a '0' luego de programar, nunca más sucede una interrupción y en la simulación en el proteus los flag no se borran luego de programar.

Es decir. ¿Hay que volver a poner los flag a cero todos a la vez o algunos? De una manera o otra hay que poner los flag otra vez a cero. Pues los voy a poner.

Hay algo donde se pierde el control con el registro INTCON pero no se donde!! :confused:

Poco a poco lo encontraremos, primero lo que me has comentado arriba para llegar hasta aquí.

He probado sólo lo del
Código:
bsf        INTCON,PEIE
retfie
y por ahora no hay cambios.

Sigo investigando lo de volver a poner en su sitio los flag a 0 de los INTCON y muchísimas gracias.
 
Atrás
Arriba