Autor Tema: Problemas para leer y escribir EEPROM de un PIC16F877A  (Leído 203 veces)

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

Desconectado jonaspan88

  • PIC10
  • *
  • Mensajes: 3
Problemas para leer y escribir EEPROM de un PIC16F877A
« en: 05 de Julio de 2018, 01:27:19 »
Buen dia amigos , les cuento que estoy iniciando en esto de la programación del pic con ensamblador y lo que deseo es poder escribir un dato cualquiera luego leerlo y mostrarlo en un led o algo asi, solo es para probar como funciona, pero a la final no lo eh conseguido y no se porque, dejo adjunto el código para saber si alguien me podría ayudar a saber que estoy haciendo mal, estoy usando el pic16f877A
----codigo--
PROCESSOR 16F877 ;LIST P=16F877
RADIX HEX
INCLUDE "P16F877A.INC"
;Setup of PIC configuration flags
;XT oscillator
;Disable watch dog timer
;Enable power up timer
;Disable code protect
__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
status equ 0x03        ; Direccion registro STATUS
porta equ 0x05         ; direccion Pueros A
trisa equ 0x85          ; Direccion TRISA
portb equ 0x06         ; Direccion puertos B
trisb equ 0x86          ; Direccion TRISB
 ;_____Memoria EEPROM______________

EEDATA equ h'10C'
EEADR equ h'10D'
EECON1 equ h'18C'
EECON2 equ h'18D'
ADDRES_W equ h'10D'   ; Direccion en la que quiero escribir el dato
Dat equ h'20'             ; Dato a guardar
 Reg equ h'21'   
 ;--CODIGO
 RESET ORG 0X00
 GOTO INICIO
 ORG 0X05
 INICIO
movlw b'11111111'
 movwf Dat
bsf status,5         ; Pasar al banco 1
movlw b'00000000'        ;COPIA LITERAL A w
movwf trisa          ; Puerto A como salida
clrw                 ; Limpiar registro W
movlw b'11111111'
movwf trisb          ; Puerto B como entrada
bcf status,5         ; Volver al banco 0
 ;---ESCRITURA
 ;comprobacion
 BSF STATUS,RP1
 BSF STATUS,RP0
 AVISO
 BTFSC EECON1,WR
 GOTO AVISO
 ;banco 2 estan EEDATA Y EEADR
 BSF STATUS,RP1
 BCF STATUS,RP0; BANCO 2
movlw ADDRES_W   ; Paso la direccion a W
movwf EEADR        ; y la paso al registro de la EEPROM  EEADR
movlw Dat            ; Pongo en W el dato que quiero grabar
movwf EEDATA      ; y lo paso al registro de dato de la EEPROM
 ;BANCO 3 ESTA ECON1
  BSF STATUS,RP1;me aseguro de ir
   BSF STATUS,RP0;banco 3
   BCF EECON1,EEPGD; SELECCIONO MEMORIA EEPROM
   BSF EECON1,WREN
   BCF INTCON,GIE     ; Pido permiso de escritura (BIT 2: WREN)
;____Secuencia requerida_______
movlw      0x55         
movwf      EECON2
movlw      0xAA      
movwf      EECON2
bsf EECON1,WR       ; Ejecuto escritura!!
BSF INTCON,GIE
BCF EECON1,WREN
;---lectura------
   ;debo ir al banco 2
   BSF STATUS,RP1
   BCF STATUS,RP0 ; BANCO2
   movlw ADDRES_W   ; Direccion a leer
movwf EEADR         ; Se la paso al registro de direcciones de la EEPROM
;BANCO 3
   BSF STATUS,RP1
   bsf STATUS,RP0           ; Paso al banco 3
BCF EECON1,EEPGD         ; Activo READ DATA, (bit0)
BSF EECON1,RD
 BSF STATUS,RP1
   BCF STATUS,RP0 ; BANCO2
movf EEDATA,W      ;guardo el valor leido en W
;movwf Reg    ;Lo paso al registro1   
 BCF STATUS,RP0
 BCF STATUS,RP1
 ;MOVLW Reg
 MOVWF PORTA
 END
 
 
muchas gracias de antemano
« Última modificación: 05 de Julio de 2018, 03:02:04 por jonaspan88 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6850
Re:Problemas para leer y escribir EEPROM de un PIC16F877A
« Respuesta #1 en: 06 de Julio de 2018, 12:57:23 »
Código: ASM
  1. status equ 0x03        ; Direccion registro STATUS
  2. porta equ 0x05         ; direccion Pueros A
  3. trisa equ 0x85          ; Direccion TRISA
  4. portb equ 0x06         ; Direccion puertos B
  5. trisb equ 0x86          ; Direccion TRISB
  6.  ;_____Memoria EEPROM______________
  7.  
  8. EEDATA equ h'10C'
  9. EEADR equ h'10D'
  10. EECON1 equ h'18C'
  11. EECON2 equ h'18D'

Ese pedazo de codigo no tiene sentido... todo eso lo tenes definido dentro del .inc que agregas al comienzo, asi que no lo vuelvas a repetir


Se que vas a usar solo los 8 bits, pero por que definir la direccion:

Código: ASM
  1.    ADDRES_W equ h'10D'   ; Direccion en la que quiero escribir el dato

como 0x10D cuando la EEPROM es de 256, es decir de 0x00 a 0xFF, aunque cuando hagas el MOVLW de ese valor solo va a quedar 0x0D



Código: ASM
  1. BSF INTCON,GIE

No actives las interrupciones si no las usas.. Asi que esa linea deberias borrarla



Te falto un loop infinito, siempre debe existir uno, asi que al final del programa deberias tener algo asi:

Código: ASM
  1.  BCF STATUS,RP0
  2.  BCF STATUS,RP1
  3.  ;MOVLW Reg
  4.  MOVWF PORTA
  5.  
  6. LOOP:
  7.     GOTO   LOOP
  8.  
  9.   END

Desconectado jonaspan88

  • PIC10
  • *
  • Mensajes: 3
Re:Problemas para leer y escribir EEPROM de un PIC16F877A
« Respuesta #2 en: 07 de Julio de 2018, 21:36:48 »
Muchas gracias enserio, me sirvio mucho pude hacerlo ahora sin problemas pero no se si me puedas ayudar con una duda mas, despues de ver tus indicaciones decidi cambiar mi codigo e intentar algo mas queria q cada q pulse un boton en el RB0 la direccion se incremente y escriba en la siguiente direccion pero lo he probado y no entiendo xq no pasa eso, te agredeceria si me ayudaras, me di cuenta haciendo el debug que al moemento de mover mi variable q se llama DIR a EEADR se mueve la direccion mas no el valor y la verdad como soy nuevo en esto no entiendo el porque.

;----Codigo
PROCESSOR 16F877
INCLUDE "P16F877A.INC"
__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
     ;---macros--banco---
      BANCO0   MACRO   
BCF   STATUS,RP0
BCF   STATUS,RP1
ENDM
BANCO1   MACRO
BSF   STATUS,RP0
BCF   STATUS,RP1
ENDM
BANCO2   MACRO   
BCF   STATUS,RP0
BSF   STATUS,RP1
ENDM
BANCO3   MACRO
BSF   STATUS,RP0
BSF   STATUS,RP1
ENDM
     ;---
      ;---Definicion de variables
 CBLOCK 20H
 COUNT
    L
    M
   DIR
 ENDC
 ;-------
 ;.----
 org 00h
    ;configuracion de puertos
    CLRF STATUS
    clrf PORTC           ; Limpia PORTC
    CLRF PORTD
    CLRF PORTB
    BSF STATUS,RP0; BANCO1
    MOVLW b'00000000';
    MOVWF TRISD
    MOVLW b'11111111';
    MOVWF TRISB
    clrf TRISC            ; PortC0 Salidas
    BANCO0
    INICIO:
    ;;----
    TEST1
    BANCO0
    CALL  ESCRITURAYLECTURA
    BTFSC PORTB,0;TESTEA SI ES 0 SI LO ES SALTA
    GOTO TEST1
    CALL ESCRITURAYLECTURA
    TEST2
    BANCO0
    BTFSS PORTB,0
    GOTO TEST2
    BANCO2
    INCF DIR ;aqui incremento la direccion
    GOTO TEST1
    ;----
     ;---EScritura y lectura;
    ESCRITURAYLECTURA:
    BANCO3
    ;debo ir al banco 2 para escribir en EEADR
    BANCO2
    MOVLW DIR
    MOVWF EEADR   ;DIRECCION EEPROM=0
    MOVLW COUNT
    MOVWF EEDATA ; escribo el dato    
    ; debo limpiar el bit EEPGD en el banco 3
    BANCO3 ; banco 3
    BCF EECON1,EEPGD ; limpio el bit EEPGD
    BSF EECON1,WREN ; habilito la escritura
    ; como no uso interrupciones la deshabilito
    BCF INTCON,GIE; deshabilito interrupciones
    ;secuencia requerida
    MOVLW h'55'
    MOVWF EECON2
    MOVLW h'AA' ;AAh=170 en decimal o 10101010
    MOVWF EECON2
    BSF EECON1,WR
    vacio
    BTFSC EECON1,WR
    GOTO vacio ; ENTRA AQUI SI aun no ha terminado de escribirse
    ;aqui termina la secuencia requerida
    ;BSF INTCON,GIE ; habilito interrupciones si voy a utilizar
    BCF EECON1,WREN; debo limpiar el bit    WREN
    BSF INTCON,GIE
    ;---aqui termina la escritura---
 ;----
 ;--- LECTURA
 LEER
    BANCO2 ;banco 2
    MOVLW DIR
    MOVWF EEADR   ;DIRECCION EEPROM=0
    BANCO3      
    BCF EECON1,EEPGD
    BSF   EECON1,RD;HABILITA EL BIT 0 (RD) DEL REGISTRO EECON1      
    BANCO2
    MOVF   EEDATA,W      ;TRANSFIERE EL DATO EN EEDATA A W,
    BANCO0
    MOVWF PORTC
    ;call   delay3
   
   ; aquí inician las subrutinas de retraso
   
    GOTO INICIO

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6850
Re:Problemas para leer y escribir EEPROM de un PIC16F877A
« Respuesta #3 en: 08 de Julio de 2018, 12:31:19 »
Antes de ver cual es el problema del programa, vamos a cambiar un par de cosas del mismo. Voy a tirar todas las ideas medias sueltas, vos tenes que organizarlas lueg.
De paso introducimos algunas otras cosas


Esto no posee sentido:
Código: ASM
  1.      ;---macros--banco---
  2.       BANCO0   MACRO  
  3. BCF   STATUS,RP0
  4. BCF   STATUS,RP1
  5. ENDM
  6. BANCO1   MACRO
  7. BSF   STATUS,RP0
  8. BCF   STATUS,RP1
  9. ENDM
  10. BANCO2   MACRO  
  11. BCF   STATUS,RP0
  12. BSF   STATUS,RP1
  13. ENDM
  14. BANCO3   MACRO
  15. BSF   STATUS,RP0
  16. BSF   STATUS,RP1
  17. ENDM

El mismo compilador posee una pseudo-instruccion que luego la reemplaza por eso, haciendo lo mismo que la macro. Como se usa ?

Primero usas BANKSEL y luego le decis el nombre de algun registro que este en el banco que deseeas. ejemplo, si quiero ir al banco 2 por que ahi esta EEADR y EEDAT, hago:

Código: ASM
  1. BANKSEL EEADR

Luego el compilador va a reemplazar ese BANKSEL por sus respectivos BSF/BCF, y vos te simplficas la vida.



Otro de los cambios que propongo es hacer una subrutina de escritura y una de lectura. Veo que lo hiciste con la escritura, pero veo un problema.
Cuando usas un CALL, si o si deberia haber un RETURN para que vuelva de ese CALL. Algo asi:

Código: ASM
  1. ; Subrutina de escritura de EEPROM
  2. ;
  3. ; Entrada:
  4. ;  - Direccion en el registro EEADR (Banco 2)
  5. ;  - Dato en el registro EEDAT (Banco 2)
  6. ;
  7. ; Retorna:
  8. ;  - Nada
  9.  
  10. EEPROM_ESCRITURA:
  11.     BANKSEL EECON1         ; banco 3
  12.     BCF     EECON1,EEPGD   ; limpio el bit EEPGD
  13.     BSF     EECON1,WREN    ; habilito la escritura
  14.     BCF     INTCON,GIE     ; deshabilito interrupciones
  15.     ;secuencia requerida
  16.     MOVLW   h'55'
  17.     MOVWF   EECON2
  18.     MOVLW   h'AA'          ;AAh=170 en decimal o 10101010
  19.     MOVWF   EECON2
  20.     BSF     EECON1,WR
  21. vacio
  22.     BTFSC   EECON1,WR
  23.     GOTO    vacio          ; ENTRA AQUI SI aun no ha terminado de escribirse
  24.  
  25.     ;BSF    INTCON,GIE     ; habilito interrupciones si voy a utilizar
  26.     BCF     EECON1,WREN    ; debo limpiar el bit    WREN
  27.     RETURN
  28.  
  29. ; Subrutina de lectura de EEPROM
  30. ;
  31. ; Entrada:
  32. ;  - Direccion en el registro EEADR (Banco 2)
  33. ;
  34. ; Retorna:
  35. ;  - Valor de la EEPROM en W
  36.  
  37.  
  38. EEPROM_LEER
  39.    BANKSEL  EECON1         ;Banco 3
  40.    BCF      EECON1,EEPGD
  41.    BSF      EECON1,RD      ;HABILITA EL BIT 0 (RD) DEL REGISTRO EECON1      
  42.    BANKSEL  EEDATA
  43.    MOVF     EEDATA,W       ;TRANSFIERE EL DATO EN EEDATA A W
  44.    RETURN

Observaras que quite TODO lo que es guardar el dato y la direccion dentro de estas rutinas, ya que esos datos van a variar ahora.

Entonces tu codigo si quisieras escribir y luego leer seria asi:

Código: ASM
  1.    ; Se que EEADR comienza en 0, asi que no lo cargo
  2.    BANKSEL  EEDAT       ; Banco 1
  3.    MOVLW    COUNT       ; Dato a escribir
  4.    MOVWF    EEDATA      ; escribo el dato
  5.    CALL     EEPROM_ESCRITURA
  6.  
  7.    ;Ahora procedo a leer, ya escribi, y no hace falta escribir de nuevo EEADR, ya que antes ya lo elegi
  8.    CALL     EEPROM_LEER ; Leo y el resultado va a W
  9.    MOVWF    PORTD       ; De W lo paso a PORTD


Ahora si vamos al programa en si,

Citar
cada q pulse un boton en el RB0 la direccion se incremente y escriba en la siguiente direccion pero lo he probado y no entiendo xq no pasa eso

Esto puede ser un problema... El decir cada ves que persione implica que esa presion puede ser de 1ms, 10ms o tal ves 5s. Esto puede traer problemas ya que al ser tan rapido el micro, en 10ms tal ves pase 100 veces por el codigo. Entonces es una ruleta lo que estas jugando.
Entonces existen 2 formas de poder proceder de una manera "sencilla" para hacer esto.

- La primera es preguntar por el pin, y bloquear el programa hasta que se suelte. Esto implica que el programa se queda encerrado en un loop. Asi:
Código: ASM
  1. INICIO:
  2.   BTFSS  PORTB, 0  ; Si esta en 1 hace el codigo, sino sigue preguntando
  3.   GOTO INICIO
  4.   ; Aca el codigo
  5. ENCIERRO:
  6.   BTFSC PORTB, 0  ; Mientras se mantenga en 1 se queda encerrado aca, asi
  7.   GOTO ENCIERRO
  8.   GOTO INICIO

- La segunda, sin activar interrupciones, es configurar al RB0 para flanco ascendente, antes del loop principal pones a 0 el flag de RB0/INT, y preguntas por si esta en 1, cuando este en 1 ejecutas el codigo y lo pones a 0 al flag, solo se va a poner a 1 cuando vos presiones de nuevo. Esto es por FLANCO, el anterior es por NIVEL.



La inicializacion quedaria asi:

Código: ASM
  1.    ORG      0x00           ; Vector de reset
  2.    GOTO     CONFIGURACION
  3.    ORG      0x04           ; Vector de interrupcion
  4.    GOTO     RETURN
  5.  
  6. CONFIGURACION:  
  7.    ;configuracion de puertos
  8.    CLRF     PORTC          ; Limpia PORTC
  9.    CLRF     PORTD
  10.    CLRF     PORTB
  11.    BANKSEL  TRISA          ; Banco 1
  12.    MOVLW    b'00000000'
  13.    MOVWF    TRISD
  14.    MOVLW    b'11111111'
  15.    MOVWF    TRISB
  16.    CLRF     TRISC          ; PortC0 Salidas
  17.  
  18.    BANKSEL  EEADR          ;Banco 2
  19.    CLRF        EEADR          ;Inicializo el registro a 0
  20.  
  21.    BANKSEL  PORTA          ;Banco 0
  22.  
  23. INICIO:
  24.  
  25.    ;Aca vas a poner tu codigo
  26.    
  27.    GOTO     INICIO



Que es lo que debo agregar para que incremente la direccion?

Solo debo agregar esto, cuando se presione el boton:

Código: ASM
  1.    BANKSEL  EEADR
  2.    INCF     EEADR, F



Te respondo otra cosa:
Citar
me di cuenta haciendo el debug que al moemento de mover mi variable q se llama DIR a EEADR se mueve la direccion mas no el valor

Cuando definis algo con CBLOCK o EQU, le asignas un valor, una constante. Y luego depende de que instrucciones usas ejemplo,

Código: ASM
  1. MOVLW DIR

Ahi lo que haces es lo mismo que

Código: ASM
  1. MOVLW 0x22

Ya que DIR es una constante igual a 0x22.

El problema esta en la instruccion, si usas MOVLW, el 0x22 es un literal y eso se copia a W, es decir W = 0x22
Si usas MOVF 0x22, le estas diciendo al micro que busque en la direccion 0x22 de la RAM (el contenido de DIR )

Ahi esta tu error. Ojo que 0x22 esta en el banco 0, mientras que las demas estan en el banco 2.

Desconectado jonaspan88

  • PIC10
  • *
  • Mensajes: 3
Re:Problemas para leer y escribir EEPROM de un PIC16F877A
« Respuesta #4 en: 10 de Julio de 2018, 17:33:46 »
Muchas gracias enserio, gracias a tu explicacion entendi varias cosas y errores que estaba cometiendo, te agraedsco mucho por tu ayuda y tu tiempo.


 

anything