Visita mi canal de youtube

sábado, 8 de octubre de 2016

Eeprom Pic C CCS

EEPROM PIC en la memoria interna EEPROM del microcontrolador PIC se pueden guardar datos que no se quiere que se borren en caso se corte la alimentación del PIC, en esta sección se comentará para el caso de la memoria EEPROM PIC para el PIC16F877A, lo que aquí se comente es muy similar en caso de utilizar otro microcontrolador PIC, siempre tener a mano la hoja de datos del PIC utilizado, en la memoria EEPROM PIC del PIC16F877A se pueden almacenar hasta 256 bytes, esto es 256 datos de 8 bits, la capacidad de la memoria EEPROM PIC puede variar de un PIC a otro.

Para la escritura y la lectura de datos en la EEPROM PIC se tienen que seguir una serie de pasos, en el orden que viene indicado en la hoja de datos del PIC.
EEPROM PIC REGISTROS


Los registros utilizados para el manejo de la EEPROM PIC del PIC16F877A son el registro EECON1, el registro EECON2, el registro EEDATA, el registro EEDATH, el registro EEADR y el registro EEADRH, en el caso de utilizar las interrupciones por finalización de escritura de la EEPROM PIC también se utilizarán los registros PIE2 y PIR2.

El registro EECON1 este es el registro de control de la memoria EEPROM PIC



El bit7 EEPGD para programar dentro de la memoria EEPROM PIC este bit tiene que ser puesto a 0, cuando este bit se pone a 1 será para programar en la memoria FLASH.

Los bits 6, 5, y 4 no son utilizados.

El bit3 WRERR este bit se pondrá automáticamente a 1 si ocurre algún reset mientras se esta escribiendo en la EEPROM PIC, al ocurrir el reset el dato no se escribirá correctamente, por lo que este bit indicará un error de escritura.

El bit2 WREN al poner a 1 este bit se habilita la escritura en la EEPROM PIC, al ponerlo a 0 la escritura en la EEPROM estará inhabilitada.

El bit1 WR al poner este bit a 1 se inicia la escritura en la EEPROM PIC, una vez que la escritura a terminado este bit se pondrá automáticamente a 0, se puede utilizar este bit para detectar cuando la escritura en la EEPROM a terminado, al finalizar la escritura también puede producirse una interrupción si esta se encuentra habilitada, si no también puede utilizarse la bandera de interrupción, el bit4 EEIF del registro PIR2 para detectar cuando se ha finalizado la escritura en la EEPROM PIC

El bit0 RD al poner este bit a 1 se inicia la lectura en la EEPROM PIC, una vez que la lectura a terminado este bit se pondrá automáticamente a 0.

El registro EECON2 este registro no es accesible, es un registro auxiliar para la escritura en la EEPROM PIC.

Los registros EEDATA y EEDATH juntos hacen un solo registro donde se cargará el dato que se quiere escribir en la EEPROM PIC, será el registro desde el programa colocará el dato que se quiera leer desde la EEPROM PIC.

Los registros EEADR y EEADRH juntos hacen un solo registro donde se cargará la dirección de la EEPROM PIC desde donde se quiere leer el dato, o donde se quiere escribir el dato.
EEPROM PIC Pasos a seguir en su programación en el XC8

Se comenta lo que se hará para escribir o leer en la EEPROM PIC, los pasos a seguir son los indicados en la hoja de datos del PIC16F877A.

Escritura en la EEPROM PIC para la secuencia a seguir sl escribir un byte en la EEPROM PIC con el XC8 se seguirá lo que indica la hoja de datos:
Comprobar si hay alguna escritura en curso, esto se puede hacer leyendo el bit WR del registro EECON1, si está a 1 es porque hay una escritura en curso. Si hay alguna escritura en curso se tendrá que esperar que esta termine.
En el registro EEADR cargar la dirección de la EEPROM PIC donde se quiera escribir, para el PIC16F877A estas direcciones están entre 0 y 256.
En el registro EEDATA se carga el dato que se quiere escribir en la EEPROM PIC.
El bit7 EEPGD del registro EECON1 se pone a 0 para que programar en la EEPROM PIC.
El bit2 WREN del registro EECON1 se pone a 1 para habilitar la escritura en la EEPROM PIC.
Deshabilitar las interrupciones poniendo el bit7 GIE del registro INTCON a 0.
Cargar el registro EECON2 con 0x55.
Cargar el registro EECON2 con 0xaa.
El bit7 WR del registro EECON1 se pone a 1 para que inicie la escritura en la EEPROM PIC.
Habilitar las interrupciones poniendo el bit7 GIE del registro INTCON a 1.
El bit2 WREN del registro EECON1 se pone a 0 para deshabilitar el uso de la EEPROM PIC.
Comprobar si la escritura a terminado, esto se puede hacer leyendo el bit WR del registro EECON1, si está a 0 es porque la escritura a terminado, también se puede leer la bandera de interrupción (bit4 EEIF del registro PIR2), si está a 1 es porque la escritura a terminado, al finalizar la escritura está bandera tiene que ser puesta a 0, al utilizar la bandera de interrupción no será necesario verificar el paso 1.

Lectura de la EEPROM PIC la secuencia a seguir para leer un byte desde la EEPROM PIC según indica la hoja de datos es la siguiente:
En el registro EEADR cargar la dirección de la EEPROM PIC donde se quiera escribir, para el PIC16F877A estas direcciones están entre 0 y 256.
El bit7 EEPGD del registro EECON1 se pone a 0 para que programar en la EEPROM PIC.
El bit7 RD del registro EECON1 se pone a 1 para que inicie la lectura en la EEPROM PIC.
Leer el dato de la dirección indicada, este dato se puede leer desde el registro EEDATA.


CCS implementa muchas funciones para trabajar con las memorias EEPROM, algunas de ellas son:




· value = read_eeprom (address): función básica para leer el valor de la EEPROM interna del PIC. Devuelve un valor entero (int8) de un byte. "address" puede ser un entero de 8 ó 16 bit. Dependiendo del PIC que utilicemos dispondremos de mas ó menos memoria EEPROM, por ejemplo el PIC 16f84A dispone de 64 bytes y los pic16F87X tienen 256 bytes que se direccionan del 0 a 255.

· write_eeprom (address, value): esta función escribe un dato (entero de 8 bit) en la dirección especificada en address en la memoria interna del PIC. Al igual que read_eeprom address puede ser un entero de 8 ó 16 bit.



Algunos dispositivos permiten leer y escribir datos en la memoria de programa en tiempo de ejecución, para los dispositivos que soportan esta funcionalidad CCS, nos proporciona las siguientes funciones:



· value = read_program_eeprom (address): esta función lee un dato de la memoria de programa del PIC y devuelve el valor leído como un entero de 16 bits. Adrress es un entero de 16 ó 32 bits que depende del dispositivo empleado.

· write_program_eeprom (address, data): función homologa a la anterior pero que nos permite escribir datos en la memoria de programa. data tiene que ser un entero de 16 bits.


CCS también incorpora funciones para leer y escribir en memorias EEPROM externas:

read_external_memory(address, dataptr, count )
write_program_memory( address, dataptr, count)

Como veis CCS nos aporta una serie de funciones para trabajar fácilmente con este tipo de memorias,

estas que he puesto aquí son algunas de ellas, pero todavía hay más. Mejor ir viéndolas poco a poco con ejemplos.

Algunas consideraciones a tener en cuenta sobre las memorias EEPROM es que son rápidas en el proceso de lectura, pero pueden tardar varios ms en realizar un proceso de escritura. Otro factor a tener en cuenta es que se pueden hacer operaciones de lectura sobre el valor de sus registros el numero de veces que se quiera, pero soportan un número limitado de ciclos de escritura / borrado. Ese número según Microchip es de aproximadamente un millón, el que quiera que lo compruebe.

La memoria EEPROM de datos no está mapeada en la zona de la memoria de datos donde se ubican los registros SFR y GPR, si programáramos en Ensamblador deberíamos realizar una serie de pasos para su lectura y escritura que aunque no difíciles resultan al menos laboriosos, CCS nos permite abstraernos por completo del proceso de lectura y escritura, lo único que tenemos que saber es las funciones que tenemos que aplicar y los parámetros y valores que devuelven dichas funciones.

Como 1º ejemplo del uso de este tipo de memorias vamos a utilizar las funciones básicas para leer y escribir datos en la memoria interna del PIC: read_eeprom (address) y write_eeprom (address, value).

El ejemplo es un contador del tipo "su turno" que solemos encontrar en algunos establecimientos como carnicerías y pescaderías. Como funcionalidades mínimas he puesto que sea capaz de contar del 0 al 99.
Y por supuesto que si se va la corriente guarde en memoria el último valor.


El código del programa será el siguiente:

01./*-----------------------------------------------------------*\
02.| Uso de la memoria EEPROM del PIC |
06.
07.#include <16F877.h>
08.//Configuración de los fusibles.
09.#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
10.#use delay(clock=4000000) //Frecuencia de reloj 4MHz
11.#byte puerto_D = 0x08 // Identificador para el puerto C.
12.
13.#int_EXT
14.
15.void EXT_isr( void )
16.{
17.
18.if ((read_eeprom(0)==0x99)||(read_eeprom(0)==0xFF))
19.{
20.write_eeprom(0,0);
21.puerto_D=read_eeprom(0);
22.}
23.else if ((read_eeprom(0) & 0x0F)<0x09)
24.{
25.write_eeprom(0,(read_eeprom(0))+1);
26.puerto_D=read_eeprom(0);
27.}
28.else if ((read_eeprom(0) & 0x0F)>=0x09)
29.{
30.write_eeprom(0,(read_eeprom(0))+7);
31.puerto_D=read_eeprom(0);
32.}
33.
34.}
35.
36.void main()
37.{
38.set_tris_b(0xFF); //Puerto B como entrada
39.set_tris_d(0x00);//Puerto D como salida
40.enable_interrupts(GLOBAL); // Se habilita la interrupción global
41.enable_interrupts(INT_EXT); // Se habilita la interrupción externa
42.puerto_D =0xFF; //inicializo puerto D
43.//write_eeprom(0,0xFF);Resetear EEPROM
44.while(true)
45.{
46.//Resto del programa
47.
48.}
49.}



Comentario del programa:

El ejemplo básicamente es un contador ascendente de 0 a 99 que incrementa su valor cada vez que pulsamos el pulsador "su turno" para evitar que el contador se reinicie y empiece a contar desde cero cada vez que se vaya la corriente, el valor actual del contador se almacenará en la memoria EEPROM del PIC en vez de en la memoria RAM. Como solo queremos guardar un valor que estará comprendido entre 0 y 99, solo utilizaremos el primer byte de la memoria EEPROM. Para detectar cuando se pulsa el pulsador, se utiliza la interrupción externa en la patilla RB0/INT.

Dentro de la función de interrupción nos encontramos con tres sentencias condicionales:

if ((read_eeprom(0)==0x99)||(read_eeprom(0)==0xFF))
{
write_eeprom(0,0);//escribo el valor 0 en la dirección 0 de la memoria EEPROM
puerto_D=read_eeprom(0);//asigno al puerto D el valor devuelto por la función de lectura de la EEPROM
}

La primera vez que se ejecute el programa el valor de la EEPROM es 0xFF (viene así de fabrica) por lo que tendremos que sobreescribir su valor a 0 para iniciar el contaje, después de esto esta condición solo se cumplirá cuando el contador llegue a 99.

else if ((read_eeprom(0) & 0x0F)<0x09)
{
write_eeprom(0,(read_eeprom(0))+1);
puerto_D=read_eeprom(0);
}


Cada "nibble" del puerto D está conectado a un decodificador por lo que tenemos RD0-RD3 al decodificador U2 y su salida conectado al display de las unidades a través del bus de datos (hay que hacer un zoom sobre el esquema en Proteus para ver las conexiones) y RD4-RD7 al decodificador U3, que está conectado al display de las decenas.


Pues bien, si tenemos 4 bits por "nibble" tendremos 16 combinaciones posibles, incrementamos con 1 el valor de la EEPROM mientras el valor del "nibble" de menor peso sea < 9. Fijaros como la función de escritura en la EEPROM nos permite poner como parámetro la función de lectura por lo que no es necesario declarar una variable local para hacer de intercambio.


Una vez incrementado el valor de la EEPROM, hacemos una nueva lectura y asignamos su valor al puerto D.

else if ((read_eeprom(0) & 0x0F)>=0x09)
{
write_eeprom(0,(read_eeprom(0))+7);
puerto_D=read_eeprom(0);
}

Los valores del "nibble" de menor peso correspondientes al rango 10-15 los saltamos sumando 7 en vez de uno. El nibble de mas peso de la lectura de la EEPROM no me interesa ya que el primer if ya se encarga de ponerlo a cero cuando el valor llegue a 0x99. Para discriminar el "nibble" de mas peso de la EEPROM lo enmascaramos antes de hacer la comparación

Podemos ver los registros de la EEPROM interna del PIC, si en Proteus seleccionamos Debug-->PIC CPU EPROM Memory.





0 comentarios:

Publicar un comentario