Autor Tema: pic 16F876. Problemas EEPROM y ADC  (Leído 2917 veces)

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

Desconectado Picavid

  • PIC12
  • **
  • Mensajes: 89
    • www.seguridomo.es
pic 16F876. Problemas EEPROM y ADC
« en: 05 de Junio de 2006, 04:11:11 »
Hola,
 Estoy empezando mi primer proyecto "serio", y tengo un 16f876, el cual desconozco. He empezado con lo mas básico y tengo problemas. No encuentro información que resuelva mis dudas. Actualmente estoy bloqueado con el tema de la EEPROM y del conversor ADC.
  Con la EEPROM, sigo, o creo, las instrucciones del fabricante, y no hace nada. Alguna vez, despues de probar, he leido la EEPROM con el T-20, y me ha grabado un "21" en vez de un 0 o un 1, donde le ha dado la gana. Esto con el 16F84a no me pasaba, iba bien.Las instrucciones que uso son:
EE_LEE
   bsf   STATUS,RP1
   bcf   STATUS,RP0      ;Banco 2
   movlw   EE_DIR
   movwf   EEADR      ;Dirección a leer
   bsf   STATUS,RP0      ;Banco 3
   bcf   EECON1,EEPGD   ;Accede a memoria de DATOS.
   bsf   EECON1,RD      ;Empieza lectura
EEPROM_sigueleyendo
   btfsc   EECON1,RD
   goto   EEPROM_sigueleyendo   ;Espera a que acabe de leer.
            ;El bit RD tiene que ponerse a 0
   bcf   STATUS,RP0      ;Situa en banco 2
   movf   EEDATA,W      ;Pone el valor en W
   movwf   EE_DATO      ;y en EE_DATO
   bcf   STATUS,RP1      ;Situa en banco 0
   return
   
;EE_DIR      indica la dirección de memoria
;EE_DATO      Registro donde grabará los datos

EE_ESCRIBE
   bsf   STATUS,RP1
   bsf   STATUS,RP0      ;Se situa en el banco 3
EE_Verifica
   btfsc   EECON1,WR      ;Se asegura que no esté escribiendo
   goto   EE_Verifica
   bcf   STATUS,RP0      ;Se situa en el banco 2
   movlw   EE_DIR
   movwf   EEADR      ;Direcciona la posición de memoria
   movf   EE_DATO,W
   movwf   EEDATA      ;Carga el dato a grabar
   bsf   STATUS,RP0      ;Situa en el banco 3
   bcf   EECON1,EEPGD   ;Accede a tipo memoria de datos
   bsf   EECON1,WREN      ;Activa permiso escritura
;   bcf   INTCON,GIE      ;Desabilita todas las interrupciones
Proceso_obligatorio
   movlw   0X55      
   movwf   EECON2
   movlw   0XAA      
   movwf   EECON2
   bsf   EECON1,WR
Fin_obligatorio
;   bsf   INTCON,GIE      ;Activa las interrupciones
   bcf   EECON1,WREN      ;Desactiva el permiso de escritura
   bcf   STATUS,RP1
   bcf   STATUS,RP0      ;Se situa en el banco0
   return
En el programa principal, tengo:
ORG 0x2100
DE  4,5,2 .... (por ejemplo). Como valores decimales.

NOTA: No uso niguna interrupción.
Tambien tengo dudas si es lo mismo mandar los datos en hexa, bin o dec. P.e. en las lineas obligatorias del fabricante, si pongo AAh en vez de 0xAA, me da error al compilar. En alguna ocasion en otros proyectos, y así de memoria, no iba igual si usaba la instruccion movlw o movf. Puede ser?

Por otro lado, tambien tengo problemas con el conversor AD. Tengo dos sensores, un LDR (AN4) y un LM335 (AN0). Centrandonos en el LDR (AN4), Normalmente me suele sacar un valor bastante igual (lo tape o no, 176 en decimal+-2). Si fisicamente pongo el LM334, los datos varias un monton. La lectura del LM335(AN0), tambien oscila en 183 decimal +-3, aún no estando fisicamente en la PCB.
Vref+ y - son Vdd y Vss.
Otra cosa muy curiosa (porque lo desconozco), es que me da el mismo valor en ADRESH que en ADRSL, tanto si lo justifico a izq. como a der.
Estas son las rutinas:
LEE_LDR
   bsf   STATUS,RP0
   movlw   b'00001001'
   movwf   ADCON1
   bcf   STATUS,RP0
   movlw   b'00100000'   ;Lee el AN4
   movwf   ADCON0
         ;ACQUISION TIME *************************************
   CALL   Retardo_20ms
   bsf   ADCON0,ADON
   bsf   ADCON0,GO
Espera_AN4   btfsc   ADCON0,NOT_DONE
   goto   Espera_AN4
   bcf   ADCON0,ADON
   bsf   STATUS,RP0
   movlw   b'00001110'
   movwf   ADCON1
   bcf   STATUS,RP0
   movf   ADRESH,W
   movwf   Valor_Ana
   return
 *Aqui ya solo trabajo con el ADRESH, ya que como he dicho los valores son iguales en ADRESH y ADRESL, por lo menos cuando los muestro por el LCD. El retardo de 20 ms solo es para hacer pruebas, no me varia nada.
  Otra duda que tengo, deben estar todas las entradas analogicas seguidas a partir de AN0?. Claro, yo tengo una en AN0 y otra en AN4, cuando tengo que convertir las pongo todas en ANA, y despues las vuelvo a poner a digitales. Puede ser esto?

  Alguien podria orientarme un poco?. He mirado en el buscador del foro, pero lo que he encontrado no me ha solucionado nada. He leido el datasheet una y otra vez, pero no se que falla. Claro, tambien hay que decir que solo llevo unos 7 meses en este mundo, y todavia ando super pez.

 Agradezco su ayuda y tiempo empleado.

Saludos, Picavid

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: pic 16F876. Problemas EEPROM y ADC
« Respuesta #1 en: 05 de Junio de 2006, 06:14:18 »
Hola, empiezo por el Leer EEPROM:
Primer MUY probable error en tu rutina: *
movlw EE_DIR

No creo que esto haga lo que intentas hacer:
recorda que la instruccion "MOVLW Literal" es una funcion que carga un valor DECLARADO en "Literal" en W, y el valor no es modificable, es decir que el valor es estatico.

Hacer movlw EE_DIR es lo mismo que decir movlw XX.

Donde XX es la posicion de memoria a la cual apunta la palabra EE_DIR.

Por lo tanto, supongamos que en mi programa tengo esto:

EE_DIR EQU 0x25   (0x25 = .37 = b'00100101')
...
...
Y pongo luego: MOVLW EE_DIR
El programa ensamblador (MPASM por ejemplo) automaticamente reemplazara EE_DIR por una CONSTANTE. ¿porque? porque asi es la arquitectura de esta instruccion! carga a W con un valor, y siempre va a ser el mismo valor.
Ahora queda otra pregunta...¿Que valor tendra esta CONSTANTE? Pues, tendra el valor del byte bajo de la direccion a la que hace referencia la variable que ingresaste, en este caso. Si pones:
MOVLW EE_DIR
el programa ensamblador, cambiara EE_DIR por el valor: 0x25
quedando:
movlw 0x25

Por lo tanto, pase lo que pase, tu programa SIEMPRE LEERA LA POSICION 0x25 de la EEPROM. Independiente del CONTENIDO de la variable EE_DIR.
Para cargar el CONTENIDO de una VARIABLE en W, podes utilizar la instruccion movf.

Reemplaza entonces(resumiendo luego de la explicacion) la linea: movlw EE_DIR por movf  EE_DIR,W

Segundo MUY probable error: *

   bcf   STATUS,RP0      ;Situa en banco 2
   movf   EEDATA,W      ;Pone el valor en W
   movwf   EE_DATO      ;y en EE_DATO
   bcf   STATUS,RP1      ;Situa en banco 0


Para simplificar un poco y no marearte:
El error esta en la posicion de estas dos lineas:

   movwf   EE_DATO      ;y en EE_DATO
   bcf   STATUS,RP1      ;Situa en banco 0

En realidad, deberia ser asi(es una posibilidad de las infinitas que hay):

   bcf   STATUS,RP1      ;Situa en banco 0
   movwf   EE_DATO      ;y en EE_DATO

¿ por que? Recorda que estabas en el BANCO 2 del PIC! No en el cero! por lo tanto, leiste la variable EEDATA que esta ubicada en el banco 2, y esto esta bien. Pero despues, volcaste el valor a la variable EE_DATO, siguiendo estando en el banco 2, lo que produce que el dato leido se grabe en la posicion: 1XXH de PIC, es decir, en una variable del banco 2 del PIC. Si tu intencion era grabarlo en el banco 2 perfecto, pero no creo que sea tu caso.
Por eso, antes de copiar el valor de W a tu variable, volve primero al banco 0 del PIC, para ubicar el valor de W en la posicion XXH y no en la 1XXH como lo estas haciendo.

Aclaracion:
Donde XX es:

EE_DATO EQU XXH

XX es la posicion de memoria que le asignaste a la variable.(La H expresa que el valor ingresado esta expresado en sistema Hexadecimal)

Resumiendo esto: esto deberia funcionar:

EE_LEE
   bsf   STATUS,RP1
   bcf   STATUS,RP0      ;Banco 2
   movf   EE_DIR,0
   movwf   EEADR      ;Dirección a leer
   bsf   STATUS,RP0      ;Banco 3
   bcf   EECON1,EEPGD   ;Accede a memoria de DATOS.
   bsf   EECON1,RD      ;Empieza lectura
EEPROM_sigueleyendo
   btfsc   EECON1,RD
   goto   EEPROM_sigueleyendo   ;Espera a que acabe de leer.
            ;El bit RD tiene que ponerse a 0
   bcf   STATUS,RP0      ;Situa en banco 2
   movf   EEDATA,W      ;Pone el valor en W
   bcf   STATUS,RP1      ;Situa en banco 0
   movwf   EE_DATO      ;y en EE_DATO
   return




Escritura de EEPROM:

Tenes errores parecidos, utilizas la instruccion movlw en lugar de la movf que es la que corresponde para lo que necesitas, y ademas, seguis sin estar en el banco correcto al momento de leer o guardar datos en ciertos registros.
Resumiendo, te lo corrijo y esto deberia funcionar:

;EE_DIR      indica la dirección de memoria
;EE_DATO      Registro donde grabará los datos

EE_ESCRIBE
   bsf   STATUS,RP1
   bsf   STATUS,RP0      ;Se situa en el banco 3
EE_Verifica
   btfsc   EECON1,WR      ;Se asegura que no esté escribiendo
   goto   EE_Verifica

   bcf   STATUS,RP1      ;Se situa en el banco 0
   bcf   STATUS,RP0      ;para poder leer el valor de la variable EEDIR
   movf   EE_DIR,0
   bsf   STATUS,RP1      ;Se situa, ahora SI, en el banco 2.
   movwf   EEADR        ;Direcciona la posición de memoria
   bcf   STATUS,RP1     ;Vuelvo al Banco cero, para leer el valor de EE_DATO...
   movf   EE_DATO,W
   bsf   STATUS,RP1     ;Y ahora, SI, vuelvo al banco 2.
   movwf   EEDATA      ;Carga el dato a grabar
   bsf   STATUS,RP0      ;Situa en el banco 3
   bcf   EECON1,EEPGD   ;Accede a tipo memoria de datos
   bsf   EECON1,WREN      ;Activa permiso escritura
;   bcf   INTCON,GIE      ;Desabilita todas las interrupciones
Proceso_obligatorio
   movlw   0X55     
   movwf   EECON2
   movlw   0XAA     
   movwf   EECON2
   bsf   EECON1,WR
Fin_obligatorio
;   bsf   INTCON,GIE      ;Activa las interrupciones
   bcf   EECON1,WREN      ;Desactiva el permiso de escritura
   bcf   STATUS,RP1
   bcf   STATUS,RP0      ;Se situa en el banco0
   return

*Con  MUY probable me refiero a que personas con conocimientos avanzados en ASM puede utilizar este tipo de "comportamientos" adrede y de manera calculada, de manera que funcionen como ellos lo deseen, pero supongo que que no fue tu intencion, por eso MUY probable, es decir, no 100% probable.





En el programa principal, tengo:
ORG 0x2100
DE  4,5,2 .... (por ejemplo). Como valores decimales.


¿Como valores decimales?? el PIC no guarda variables de tipo decimal(punto flotante). Ahora, si vos juntas, por ejemplo, mas de 1 byte, y los unis para formar cada numero decimal, perfecto, pero OJO! que ahi las comas, simplemente indican que se va a grabar:

4 en la posicion 0x2100 del PIC 0x2100 es la primer posicion de memoria EEPROM.
5 en la posicion 0x2101
2 en la posicion 0x2102

y NO 4,5 o 4,52 en la posicion 0x2100.



Citar
Tambien tengo dudas si es lo mismo mandar los datos en hexa, bin o dec.

Por supuesto que si! Es lo mismo. El valor es el mismo, independientemente del sistema numerico que utilices.


Citar
P.e. en las lineas obligatorias del fabricante, si pongo AAh en vez de 0xAA, me da error al compilar.

Si, y haciendo lo que haces esta perfecto.

Citar
En alguna ocasion en otros proyectos, y así de memoria, no iba igual si usaba la instruccion movlw o movf. Puede ser?

Por supuesto que puede ser! Es mas, es altamente probable que no haga lo mismo, sencillamente porque MOVLW y MOVF son dos instrucciones distintas!

MOVLW  literal
carga un valor en W y siempre se cargara ese valor declarado. No se puede cambiar ESE valor, excepto que se lo cambie desde el archivo a grabar, y se reprograme el PIC.

MOVF REGISTRO,destino
mueve el CONTENIDO de una posicion de memoria(REGISTRO), a: W si destino = 0 ó al mismo REGISTRO declarado si destino = 1.



Bueno, me canse, una cosita mas a primera vista de la parte de la converison ADC:

Citar
Aqui ya solo trabajo con el ADRESH, ya que como he dicho los valores son iguales en ADRESH y ADRESL

No creo que sean iguales, simplemente, recorda que el registro especial ADRESH esta en el banco 0, y el registro ADRESL esta en el banco 1!. Ambos se encuentran en la misma posicion de memoria(dentro de sus respectivas paginas), por eso te parece que son iguales.

Para leer el ADRESL hace asi:
bsf  STATUS,RP0  ;banco 1
movf ADRESL,0   ;W contiene el valor de ADRESL
bcf  STATUS,RP0  ;banco 0

Y para leer el ADRESH simplemente(suponiendo que estabas en el banco 0 antes de querer leerlo):

movf  ADRESH,0   ;W contiene el valor de ADRESH

Espero que te hechen una mano algunos usuarios con el resto de lo que queda x responder, sino, luego te lo respondo yo.
Saludos. Me duermo...ZzzZZZzzzzZ :D :D
"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 Picavid

  • PIC12
  • **
  • Mensajes: 89
    • www.seguridomo.es
Re: pic 16F876. Problemas EEPROM y ADC
« Respuesta #2 en: 06 de Junio de 2006, 04:00:47 »
Hola BrunoF, Te agradezco muchisimo tu informacion y mas aun el tiempo que has dedicado.

No he respondido antes, porque he decido rehacer todo el programa siguiendo tus pautas. El tema de movlw/movf no lo tenia nada claro. Por ahi tenía muchisimos fallos.
Bien, hay alguna cosita que aun no tengo del todo claro, pero a mendia que reconstruya el programa te informo.

Muchas Gracias, Picavid.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: pic 16F876. Problemas EEPROM y ADC
« Respuesta #3 en: 06 de Junio de 2006, 04:53:27 »
Ok, cualquier cosa no dudes en preguntar.
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.