Muy buenas a todos, en esta entrada vamos a realizar una
práctica sobre cómo leer y escribir en una memoria EEPROM.
El proceso será, conectar, a través del BUS SPI y el
PIC18f4550, la memoria EEPROM.
Puesto que ya he mencionado SPI y el PIC 18F4550 en otras
entradas, solo os diré que echéis un vistazo en mi BIBLIOTECA.
Por otro lado lo que sí haré será poneros este enlace sobre
lo más importante de la EEPROM :
Información sobre qué es una memoria EEPROM.
Y aquí su datasheet: 25LC020A
Aunque esto ya suene algo repetitivo, haremos como siempre,
utilizar una librería ya creada para controlar las comunicaciones entre
dispositivos.
Concrétamente la 25C040 que viene incluida en el en el “C
compiler”.
ESTA ES LA LIBRERÍA.
///////////////////////////////////////////////////////////////////////////
//// Library for a
MicroChip
25C040
////
////
////
////
init_ext_eeprom(); Call before the other functions are
used ////
////
////
////
write_ext_eeprom(a, d); Write the byte d to the address
a ////
////
////
////
d = read_ext_eeprom(a); Read the byte d from the address
a ////
////
////
////
b = ext_eeprom_ready(); Returns TRUE if the eeprom is
ready ////
////
to receive
opcodes
////
////
////
////
The main program may define EEPROM_SELECT, EEPROM_DI, EEPROM_DO ////
////
and EEPROM_CLK to override the defaults
below.
////
////
////
////
////
////
Pin
Layout
////
////
-----------------------------------------------
////
////
|
__
|
////
////
| 1: CS EEPROM_SELECT | 8: VCC
+5V
|
////
////
|
|
____
|
////
////
| 2: SO EEPROM_DO | 7: HOLD
+5V
|
////
////
|
__
|
|
////
////
| 3: WP
+5V | 6:
SCK EEPROM_CLK
|
////
////
|
|
|
////
////
| 4: VSS GND
| 5: SI EEPROM_DI
|
////
////
-----------------------------------------------
////
////
////
///////////////////////////////////////////////////////////////////////////
////
(C) Copyright 1996, 2003 Custom Computer
Services ////
//// This
source code may only be used by licensed users of the CCS C ////
////
compiler. This source code may only be distributed to
other ////
////
licensed users of the CCS C compiler. No other use, reproduction ////
//// or
distribution is permitted without written
permission. ////
////
Derivative programs created using this software in object
code ////
//// form
are not restricted in any
way.
////
///////////////////////////////////////////////////////////////////////////
#ifndef
EEPROM_SELECT
#define
EEPROM_SELECT PIN_A0
#define
EEPROM_CLK PIN_B1
#define
EEPROM_DI PIN_C7//
#define
EEPROM_DO PIN_B0//
#endif
#define
EEPROM_ADDRESS long int
#define
EEPROM_SIZE 512
void
init_ext_eeprom() {
output_high(EEPROM_SELECT);
output_low(EEPROM_DI);
output_low(EEPROM_CLK);
}
BOOLEAN
ext_eeprom_ready() {
BYTE cmd[1], i, data;
cmd[0] =
0x05;
//rdsr opcode
output_low(EEPROM_SELECT);
for(i=1; i<=8; ++i) {
output_bit(EEPROM_DI, shift_left(cmd,1,0));
output_high(EEPROM_CLK); //data latches
output_low(EEPROM_CLK); //back to idle
}
for(i=1; i<=8; ++i) {
output_high(EEPROM_CLK); //data latches
shift_left(&data,1,input(EEPROM_DO));
output_low(EEPROM_CLK); //back to idle
}
output_high(EEPROM_SELECT);
return !bit_test(data, 0);
}
void
write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
BYTE cmd[3];
BYTE i;
BYTE wren;
wren=0x06;
cmd[0]=data;
cmd[1]=address;
cmd[2]=0x02|((address>>5)&0x08);
// Wait until the eeprom is done with a previous write
while(!ext_eeprom_ready());
output_low(EEPROM_SELECT);
for(i=0; i<8; ++i)
{
output_bit(EEPROM_DI, shift_left(&wren,1,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_high(EEPROM_SELECT);
output_low(EEPROM_SELECT);
for(i=0; i<24; ++i)
{
output_bit(EEPROM_DI, shift_left(cmd,3,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_high(EEPROM_SELECT);
delay_ms(5);
}
BYTE
read_ext_eeprom(EEPROM_ADDRESS address) {
BYTE cmd[2];
BYTE i,data;
cmd[0]=address;
cmd[1]=0x03|((address>>5)&0x08);
// Wait until the eeprom is done with a previous write
while(!ext_eeprom_ready());
output_low(EEPROM_SELECT);
for(i=0; i<16; ++i)
{
output_bit(EEPROM_DI, shift_left(cmd,2,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
for(i=0; i<8; ++i)
{
shift_left(&data,1,input(EEPROM_DO));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_high(EEPROM_SELECT);
return(data);
}
Puesto que para mostrar los datos vamos a tener que usar un
LCD, también usaré una librería para el
LCD, la que he usado en anteriores entradas.
//
flex_lcd.c
// These
pins are for the Microchip PicDem2-Plus board,
// which is
what I used to test the driver. Change these
// pins to
fit your own board.
#define
LCD_DB4 PIN_D4
#define
LCD_DB5 PIN_D5
#define
LCD_DB6 PIN_D6
#define
LCD_DB7 PIN_D7
//
#define
LCD_RS PIN_D0
#define
LCD_RW PIN_D1
#define
LCD_E PIN_D2
// If you
only want a 6-pin interface to your LCD, then
// connect
the R/W pin on the LCD to ground, and comment
// out the
following line.
#define
USE_LCD_RW 1
//========================================
#define
lcd_type 2 // 0=5x7, 1=5x10, 2=2
lines
#define
lcd_line_two 0x40 // LCD RAM address for the 2nd line
int8 const
LCD_INIT_STRING[4] =
{
0x20 |
(lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc,
// Display on
1,
// Clear display
6
// Increment cursor
};
//-------------------------------------
void
lcd_send_nibble(int8 nibble)
{
//
Note: !! converts an integer expression
// to a
boolean (1 or 0).
output_bit(LCD_DB4,
!!(nibble & 1));
output_bit(LCD_DB5,
!!(nibble & 2));
output_bit(LCD_DB6,
!!(nibble & 4));
output_bit(LCD_DB7,
!!(nibble & 8));
delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}
//-----------------------------------
// This
sub-routine is only called by lcd_read_byte().
// It's not
a stand-alone routine. For example, the
// R/W
signal is set high by lcd_read_byte() before
// this
routine is called.
#ifdef
USE_LCD_RW
int8
lcd_read_nibble(void)
{
int8 retval;
// Create
bit variables so that we can easily set
//
individual bits in the retval variable.
#bit
retval_0 = retval.0
#bit
retval_1 = retval.1
#bit
retval_2 = retval.2
#bit
retval_3 = retval.3
retval = 0;
output_high(LCD_E);
delay_cycles(1);
retval_0 =
input(LCD_DB4);
retval_1 =
input(LCD_DB5);
retval_2 =
input(LCD_DB6);
retval_3 =
input(LCD_DB7);
output_low(LCD_E);
return(retval);
}
#endif
//---------------------------------------
// Read a
byte from the LCD and return it.
#ifdef
USE_LCD_RW
int8
lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high =
lcd_read_nibble();
low =
lcd_read_nibble();
return(
(high<<4) | low);
}
#endif
//----------------------------------------
// Send a
byte to the LCD.
void
lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);
#ifdef
USE_LCD_RW
while(bit_test(lcd_read_byte(),7))
;
#else
delay_us(60);
#endif
if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);
delay_cycles(1);
#ifdef
USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif
output_low(LCD_E);
lcd_send_nibble(n
>> 4);
lcd_send_nibble(n
& 0xf);
}
//----------------------------
void
lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef
USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for(i=0 ;i
< 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i
< sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
//----------------------------
void
lcd_gotoxy(int8 x, int8 y)
{
int8
address;
if(y != 1)
address = lcd_line_two;
else
address=0;
address +=
x-1;
lcd_send_byte(0,
0x80 | address);
}
//-----------------------------
void
lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
//------------------------------
#ifdef
USE_LCD_RW
char
lcd_getc(int8 x, int8 y)
{
char value;
lcd_gotoxy(x,y);
// Wait
until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value =
lcd_read_byte();
output_low(lcd_RS);
return(value);
}
#endif
void
lcd_setcursor_vb(short visible, short blink) {
lcd_send_byte(0, 0xC|(visible<<1)|blink);
}
Aquí el programa principal.
///////////////////////////////////////////////////////////////////////////////////
// AUTOR: Gabi Allende Enero/2012
////////////////////////////////////////////////////////////////////////////////////
// PROGRAMA: Leer y escribir en una EEprom VERSIÓN: 1.0
// DISPOSITIVO: PIC 18F4550 COMPILADOR: CCSc
// Entorno IDE: MPLAB SIMULADOR: Proteus
// TARJETA DE APLICACIÓN: ___ DEBUGGER: ICD3
/////////////////////////////////////////////////////////////////////////////////
//
//
// En este proyecto vamos a hacer primero una escritura sobre la EEprom, en ella
// pondremos nuestro nombre, seguídamente, con la función de lectura, la leeremos.
// no puedes enviar más de 16 bytes.
//
//////////////////////////////////////////////////////////////////////////////////
#include
#fuses INTHS //Seleccion de oscilador (interno)
#use delay(internal=8Mhz) // Selecciona la velocidad del oscilador interno
#include // usamos la librería de la Eeprom
#include // este lcd es el que funciona bien.
////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
int i;
int hex=0x00;
char array[]="GABI";
char variable;
////////////////////////////////////////////////////////////////////////////////////
// PRINCIPAL ///////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
void main()
{
init_ext_eeprom(); // INICIO EEPROM
lcd_init(); // INICIO LCD
for(i=0;i<12;i++) //BUCLE QUE MUEVE EL CURSOR PARA ESCRIBIR
{
write_ext_eeprom(hex,array[i]);//
hex++; // incremento la variable para ver en el lcd la dirección de la memoria.
delay_ms(650);
lcd_putc("\f");//borra lcd
}
hex=0x00;//pongo a 0 la variable exadecimal para leer desde el principio
printf(lcd_putc,"LECTURA"); //sale cuando inicia el programa, antes de leer
delay_ms(300);
lcd_putc("\f");//se borra lcd
for(i=0;i<12;i++)//Volvemos al inicio y posicionamos el cursor.
{
variable = read_ext_eeprom(hex);//se introducen en una variable char los datos que se van leyendo en la EEPROM
printf(lcd_putc,"%c",variable);
delay_ms(300);
hex++; // incrementas la posición de la memoria EEprom
}
for(;;); //para no pderder el flujo
}
///////////////////////////////////////////////////////////////////////////////////
// AUTOR: Gabi Allende Enero/2012
////////////////////////////////////////////////////////////////////////////////////
// PROGRAMA: Leer y escribir en una EEprom VERSIÓN: 1.0
// DISPOSITIVO: PIC 18F4550 COMPILADOR: CCSc
// Entorno IDE: MPLAB SIMULADOR: Proteus
// TARJETA DE APLICACIÓN: ___ DEBUGGER: ICD3
/////////////////////////////////////////////////////////////////////////////////
//
//
// En este proyecto vamos a hacer primero una escritura sobre la EEprom, en ella
// pondremos nuestro nombre, seguídamente, con la función de lectura, la leeremos.
// no puedes enviar más de 16 bytes.
//
//////////////////////////////////////////////////////////////////////////////////
#include
#fuses INTHS //Seleccion de oscilador (interno)
#use delay(internal=8Mhz) // Selecciona la velocidad del oscilador interno
#include
#include
////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
int i;
int hex=0x00;
char array[]="GABI";
char variable;
////////////////////////////////////////////////////////////////////////////////////
// PRINCIPAL ///////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
void main()
{
init_ext_eeprom(); // INICIO EEPROM
lcd_init(); // INICIO LCD
for(i=0;i<12;i++) //BUCLE QUE MUEVE EL CURSOR PARA ESCRIBIR
{
write_ext_eeprom(hex,array[i]);//
hex++; // incremento la variable para ver en el lcd la dirección de la memoria.
delay_ms(650);
lcd_putc("\f");//borra lcd
}
hex=0x00;//pongo a 0 la variable exadecimal para leer desde el principio
printf(lcd_putc,"LECTURA"); //sale cuando inicia el programa, antes de leer
delay_ms(300);
lcd_putc("\f");//se borra lcd
for(i=0;i<12;i++)//Volvemos al inicio y posicionamos el cursor.
{
variable = read_ext_eeprom(hex);//se introducen en una variable char los datos que se van leyendo en la EEPROM
printf(lcd_putc,"%c",variable);
delay_ms(300);
hex++; // incrementas la posición de la memoria EEprom
}
for(;;); //para no pderder el flujo
}
No hay comentarios:
Publicar un comentario