# Escribir/Leer Eeprom externa



## zgouki (Ago 21, 2008)

Que tal gente. Por mas que he leido y releido distintos posts y despues de cansarme de buscar en el buscador (valga la redundancia ), me vi obligado a iniciar este nuevo tema.
Como siempre en mis post, aqui esta detallada mi situación:
Acabo de construir una matriz de leds y mediante un PIC 16F628A, en ella escribo un mensaje pasante...Mi problema reside en que me gustaría escribir un texto bastante extenso e inevitablemente empezamos a hablar de memorias externas.
Pero la verdad que nose nada sobre ellas... 
Como soft utilizo el PIC Simulator Ide, el cual tiene como lenguaje el PIC BASIC. Hasta ahora me ha resultado el lenguaje mas facil para programar y no me ha dado problemas. 
Me gustaría si alguien me podria ayudar a hacer una rutina para leer un byte de la Eeprom externa (la que uds. me digan). En realidad, tambien necesito saber como grabarla previamente los datos que quiero volcar en la matriz (combinaciones de 0 y 1). Y tambien las conexiónes con el pic y demas componentes necesarios para la comunicacion entre la Eeprom y el pic (osea esquematicos e instrucciones). 
En resumen, hoy estoy mas que pedigueño . 
Saludos y espero que puedan ayudarme.


----------



## gzaloprgm (Ago 21, 2008)

Basicamente podés usar una memoria 24lcxxx que soporta i2c. El pic no soporta i2c por 'hardware', pero es posible implementarlo por software. En cuanto a escribir combinaciones de 1 y 0 (array de bits) es posible agruparlos de a 8 (byte) y grabarlo. Yo logré hacerlo de forma muy facil usando picc (hay una librería ya hecha para 24lc256 (32kiB). Este IC de 4 pines sale más o menos $7 argentinos.

El datasheet de la memoria lo encontrás acá: ww1.microchip.com/downloads/en/devicedoc/21203N.pdf
En cuanto a cómo conectarlo te puedo decir que necesitás dos lineas bidireccionales: SDC (Clock) y SDA (Data). Es necesario usar resistencias de pull up de 10K en ambas líneas o bien usar las del puerto B del pic.

Cómo interfacear via i2c lo podés encontrár acá: http://www.esacademy.com/faq/i2c/general/i2cproto.htm

Es bastante facil aunque la implementacion puede ser un poco larga.

Espero que te sirva,
Gonzalo


----------



## zgouki (Ago 22, 2008)

Muchas gracias por tu respuesta. Sucede que de ingles se poco y nada pero bueno, algo se entiende. De todos modos me gustaría saber alguna rutina en basic para hacerlo, no me veo bien usando el C++...
Husmenado por la web, encontre este codigo que paso a poner:


```
' I2CREAD and I2WRITE Commands
'
' Write to the first 16 locations of an external serial EEPROM
' Read first 16 locations back and send to serial out repeatedly
' Note: for EEPROMS with byte-sized address

        Include "modedefs.bas"          ' Include serial modes

SO      con     0                       ' Define serial output pin
DPIN    var     PORTA.0                 ' I2C data pin
CPIN    var     PORTA.1                 ' I2C clock pin
B0      var     byte
B1      var     byte
B2      var     byte

        For B0 = 0 To 15                ' Loop 16 times
                I2CWRITE DPIN,CPIN,$A0,B0,[B0]  ' Write each location's address to itself
                Pause 10                ' Delay 10ms after each write
        Next B0

loop:   For B0 = 0 To 15 step 2         ' Loop 8 times
                I2CREAD DPIN,CPIN,$A0,B0,[B1,B2]        ' Read 2 locations in a row
                Serout SO,N2400,[#B1," ",#B2," "]       ' Print 2 locations
        Next B0

        Serout SO,N2400,[10]            ' Print linefeed

        Goto loop
```

Quizas alguien puede decirme para que sirve este código y coo implementarlo.
Ademas, todavia nose lo ás importante...como programo una memoria! 
Saludos


----------



## zgouki (Ago 22, 2008)

Aca encontre otro código, algo de :

"i2cslave.bas
 i2cmast.bas 	

 PICBASIC PRO program to demonstrate the I2C slave function.  Use i2cmast.bas to   
 read and write data to the slave device."


```
' PicBasic Pro I2C slave program - PIC16F877/PIC-X1

DEFINE	ONINT_USED	1			' For use with melabs Loader

' Alias pins
scl     VAR     PORTC.3         ' I2C clock input
sda     VAR     PORTC.4         ' I2C data input


' Define used register flags
SSPIF   VAR     PIR1.3          ' SSP (I2C) interrupt flag
BF      VAR     SSPSTAT.0       ' SSP (I2C) Buffer Full
R_W     VAR     SSPSTAT.2       ' SSP (I2C) Read/Write
D_A     VAR     SSPSTAT.5       ' SSP (I2C) Data/Address
CKP     VAR     SSPCON.4        ' SSP (I2C) SCK Release Control
SSPEN   VAR     SSPCON.5        ' SSP (I2C) Enable
SSPOV   VAR     SSPCON.6        ' SSP (I2C) Receive Overflow Indicator
WCOL    VAR     SSPCON.7        ' SSP (I2C) Write Collision Detect


' Define constants
I2Caddress CON	2				' Make our address 2


' Allocate RAM
result	VAR		BYTE			' ADC result
datain 	VAR     BYTE			' Data in 
dataout	VAR     BYTE[8]			' Data out array
readcnt	VAR     BYTE            ' I2C read count



' Initialize ports and directions
        ADCON1 = $0e			' PORTA.0 analog, rest PORTA and PORTE pins to digital

' Initialize I2C slave mode
        SSPADD = I2Caddress		' Set our address
        SSPCON2 = 0 			' General call address disabled
        SSPCON = $36 			' Set to I2C slave with 7-bit address

        readcnt = 0				' Zero counter

        dataout[0] = "A"		' Preset output data to "ADC=    "
        dataout[1] = "D"
        dataout[2] = "C"
        dataout[3] = "="
        dataout[4] = " "
        dataout[5] = " "
        dataout[6] = " "
        dataout[7] = " "


        GoTo mainloop 			' Skip over subroutines



i2cslave:						' I2C slave subroutine

		SSPIF = 0				' Clear interrupt flag
		
        IF R_W = 1 Then i2crd   ' Read data from us

        IF BF = 0 Then i2cexit  ' Nothing in buffer so exit

        IF D_A = 1 Then i2cwr   ' Data for us (not address)

        IF SSPBUF != I2Caddress Then i2cexit	' Clear the address from the buffer
        
        readcnt = 0				' Mark as first read
        
        GoTo i2cexit


i2cwr:							' I2C write data to us

        datain = SSPBUF			' Put data into array
        GoTo i2cexit


i2crd:							' I2C read data from us

        IF D_A = 0 Then
                readcnt = 0		' Mark as first read
        EndIF

        SSPBUF = dataout[readcnt]	' Get data from array
        CKP = 1                 	' Release SCL line
        readcnt = readcnt + 1   	' Move along read count
        
        GoTo i2cexit            	' That's it


i2cexit:

		Return



mainloop:						' Main program loop
        

        IF SSPIF Then			' Check for I2C interrupt flag
                GoSub i2cslave
        EndIF

		ADCIN 0, result			' Read ADC channel 0
	
		dataout[5] = datain[0] - result		' Add offset to result value


        GoTo mainloop           ' Do it all forever
```


Y aca hay el otro:


```
' PicBasic Pro program to read and write to I2C slave
'
' Writes a 1-byte offset value, pauses, then reads an 8
' character string from the slave. Expects to find the
' ADC conversion value (- offset) in the 6th position of
' the string.
 
 
' Define LCD registers and bits
DEFINE  LCD_DREG        PORTD
DEFINE  LCD_DBIT        4
DEFINE  LCD_RSREG       PORTE
DEFINE  LCD_RSBIT       0
DEFINE  LCD_EREG        PORTE
DEFINE  LCD_EBIT        1

DEFINE  I2C_HOLD        1

SCL     VAR     PORTC.3				' Clock pin
SDA     VAR     PORTC.4				' Data pin
a		VAR	BYTE[8]					' Holds 8 characters read from slave



        ADCON1 = 7					' Set PORTA and PORTE to digital
        Low PORTE.2					' LCD R/W line low (W)
        Pause 100					' Wait for LCD to start up

        LCDOut $fe, 1, "I2CX"		' Display
		Pause 1000


loop:
        I2CWrite SDA,SCL,$02,[127], bogus	' Write offset to slave
        Pause 500               


        I2CRead SDA,SCL,$02,[STR a\8], bogus	' Read string from slave
        

        LCDOut $fe, 1, STR a\5,SDEC a[5]	' Display result, preceded by 5 character
        									' string received from slave.
        
        Pause 500

        GoTo loop					' Do it forever


bogus:
		LCDOut $fe,1, "timed out"	' I2C command timed out
		Pause 1000

		GoTo loop

        End
```


----------



## meledu (Sep 28, 2008)

sabes? yo estoy trabajando en el mismo proyecto y he logrado mostrar caracteres en mi pantalla de led pero tenemos el mismo problema (la eeprom) tengo los datos de como conectarlaal pic y como deveria ser la subrrutina para lleer los datos y enviarlos al integrado encargado de mostrar los datos en la pantalla pero mi problema radica en que no se que programa usar para generar el codigo de la eemprom y ni siquiera como deverian ser escritos estos por eso seria buena idea si compartimos datos y aver si juntos llegamos a la solucion.


----------



## Moyano Jonathan (Oct 1, 2008)

Para los que programan en C de CCS les dejo el siguiente link donde van a encontrar todo lo que necesitan http://picmania.garcia-cuervo.com/


----------



## zgouki (Oct 3, 2008)

meledu dijo:
			
		

> sabes? yo estoy trabajando en el mismo proyecto y he logrado mostrar caracteres en mi pantalla de led pero tenemos el mismo problema (la eeprom) tengo los datos de como conectarlaal pic y como deveria ser la subrrutina para lleer los datos y enviarlos al integrado encargado de mostrar los datos en la pantalla pero mi problema radica en que no se que programa usar para generar el codigo de la eemprom y ni siquiera como deverian ser escritos estos por eso seria buena idea si compartimos datos y aver si juntos llegamos a la solucion.


Amigo meledu:
          Disculpa que no te haya contestado antes, me surgieron algunos improvistos. Al final pude leer los datos de una eeprom y escribir en esta: Utilicé la familia 24LC, y como lenguaje el PIC BASIC del PIC SIMULATOR IDE. AL final, la solución estaba enfrente de mis narices  : Cuando instalás el PSI, se te generán un par de páginas HTML, en una de ellas esta el PIC BASIC COMPILER REFERENCE MANUAL (sino puedes entrar aquí 
http://www.oshonsoft.com/picbasiccompiler.html )
De todos modos, para terminar el post, aquí te dejo el código que te digo:

*● I2C communication with external I2C devices *
I2C communication can be implemented in basic programs using I2CWRITE and I2CREAD statements. The first argument of both statements must be one of the microcontroller's pins that is connected to the SDA line of the external I2C device. The second argument of both statements must be one of the microcontroller's pins that is connected to the SCL line. The third argument of both statements must be a constant value or Byte variable called 'slave address'. Its format is described in the datasheet of the used device. For example, for EEPROMs from 24C family (with device address inputs connected to ground) the value 0xA0 should be used for slave address parameter. Both statements will take control over bit 0 of slave address during communication. The forth argument of both statements must be a Byte or Word variable (this depends on the device used) that contains the address of the location that will be accessed. If a constant value is used for address parameter it must be in Byte value range. The last (fifth) argument of I2CWRITE statement is a Byte constant or variable that will be written to the specified address, and for I2CREAD statement it must be a Byte variable to store the value that will be read from the specified address. It is allowed to use more than one 'data' argument. For I2C devices that do not support data address argument there is short form of I2C statements (I2CWRITE1 and I2CREAD1) available where slave address argument is followed with one or more data arguments directly. For some I2C slave devices it is necessary to make a delay to make sure device is ready to respond to I2CREAD statement. For that purpose there is I2CREAD_DELAYUS parameter that can be set by DEFINE directive and has default value of 0 microseconds. Also, for slower I2C devices, it might be necessary to use longer clock pulses. That can be done by setting I2CCLOCK_STRETCH parameter using DEFINE directive. This parameter will set clock stretch factor. Its default value is 1. Here is one combined example with LCD module and 24C64 EEPROM (SDA connected to RC2; SCL connected to RC3): 

```
DEFINE LCD_BITS = 8 
DEFINE LCD_DREG = PORTB 
DEFINE LCD_DBIT = 0 
DEFINE LCD_RSREG = PORTD 
DEFINE LCD_RSBIT = 1 
DEFINE LCD_EREG = PORTD 
DEFINE LCD_EBIT = 3 
DEFINE LCD_RWREG = PORTD 
DEFINE LCD_RWBIT = 2 
DIM ADDR AS WORD 
DIM DATA AS BYTE 
SYMBOL SDA = PORTC.2 
SYMBOL SCL = PORTC.3 
LCDINIT 3 
WAITMS 1000 
FOR ADDR = 0 TO 31 
   LCDCMDOUT LcdClear 
   DATA = 255 - ADDR 
[b]   I2CWRITE SDA, SCL, 0xA0, ADDR, DATA [/b]
   LCDOUT "Write To EEPROM" 
   LCDCMDOUT LcdLine2Home 
   LCDOUT "(", #ADDR, ") = ", #DATA 
[b]   WAITMS 1000 [/b]
NEXT ADDR 
FOR ADDR = 0 TO 31 
   LCDCMDOUT LcdClear 
[b]   I2CREAD SDA, SCL, 0xA0, ADDR, DATA [/b]
   LCDOUT "Read From EEPROM" 
   LCDCMDOUT LcdLine2Home 
   LCDOUT "(", #ADDR, ") = ", #DATA 
[b]   WAITMS 1000 [/b]
NEXT ADDR
```

There is a set of low-level I2C communication statements available, if it is needed to have more control over I2C communication process. I2CPREPARE statement has two arguments that must be one of the microcontroller's pins. The first argument defines SDA line and second argument defines SCL line. This statement will prepare these lines for I2C communication. I2CSTART statement will generate start condition, and I2CSTOP statement will generate stop condition. One byte can be sent to the I2C slave using I2CSEND statement. After the statement is executed C bit in STATUS register will hold the copy of the state on the SDA line during the acknowledge cycle. There are two statements that can be used to receive one byte from I2C slave. I2CRECA or I2CRECEIVEACK will generate acknowledge signal during acknowlegde cycle after the byte is received. I2CRECN or I2CRECEIVENACK will generate not acknowledge signal during acknowlegde cycle after the byte is received. One example: 


```
DIM ADDR AS WORD 
DIM DATA(31) AS BYTE 
SYMBOL SDA = PORTC.4 
SYMBOL SCL = PORTC.3 
ADDR = 0 
I2CPREPARE SDA, SCL 
I2CSTART 
I2CSEND 0xA0 
I2CSEND ADDR.HB 
I2CSEND ADDR.LB 
I2CSTOP 
I2CSTART 
I2CSEND 0xA1 
FOR ADDR = 0 TO 30 
   I2CRECEIVEACK DATA(ADDR) 
NEXT ADDR 
I2CRECN DATA(31) 
I2CSTOP
```

Lo que está en negrita vendría a ser el code en sí que necesitas. Waitms puede ser menor, creo que lo más bajo que probé y me funcionó es 10ms :S, pero de todos modos te recomiendo que experimentes vos.

Saludos desde Argentina


----------



## Meta (Oct 3, 2008)

zgouki dijo:
			
		

> Que tal gente. Por mas que he leido y releido distintos posts y despues de cansarme de buscar en el buscador (valga la redundancia ), me vi obligado a iniciar este nuevo tema.
> Como siempre en mis post, aqui esta detallada mi situación:
> Acabo de construir una matriz de leds y mediante un PIC 16F628A, en ella escribo un mensaje pasante...Mi problema reside en que me gustaría escribir un texto bastante extenso e inevitablemente empezamos a hablar de memorias externas.
> Pero la verdad que nose nada sobre ellas...
> ...



Hola:

En este libro www.pic16f84a.org te cuenta teoría y mucha practica sobre la comunicación I2C y memoria EPROM externa. Muy pero que muy bueno. A pesar de que está en ASM, lo explica muy bien.


```
;************************************ I2C_EEPROM_01.asm *******************************
;
;	===================================================================
;	  Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;	  E. Palacios, F. Remiro y L. López.		[url]www.pic16f84a.com[/url]
; 	  Editorial Ra-Ma.  [url]www.ra-ma.es[/url]
;	===================================================================
;
; Programa para manejar la escritura y lectura en la memoria EEPROM serie 24LC256.
; Tiene dos partes:
;    1ª	Escribe un mensaje grabado en el programa del PIC16F84A a partir de la posición
;		3B00h dentro de la 24LC256.
;    2ª	Lee el mensaje grabado en la memoria 24LC256 anteriormente y lo visualiza en la
;		pantalla del módulo LCD.
;
; El mensaje tendrá menos de 16 caracteres, que es la máxima longitud de la pantalla.
;
; ZONA DE DATOS **********************************************************************

	LIST		P=16F84A
	INCLUDE		<P16F84A.INC>
	__CONFIG	_CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

	CBLOCK	0x0C
	ENDC

PAGINA	EQU	0x3B					; Escribe y lee en esta página, por ejemplo.

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

	ORG 	0
Inicio
	call	LCD_Inicializa
Principal
	movlw	PAGINA					; Escribe a partir de la dirección 0 de esta
	call 	M24LC256_EscribeMensaje	; página de la memoria.
	movlw	PAGINA					; Lee a partir de la dirección 0 de esta página
	call	M24LC256_Mensaje_a_LCD	; de la memoria.
	sleep							; Pasa a reposo.

; Subrutina "M24LC256_EscribeMensaje" ----------------------------------------------------------------
;
; Escribe la memoria M24LC256 con el mensaje grabado al final de este programa a partir
; de la posición 0 de la página de la memoria 24LC256, señalada por el contenido del
; registro de trabajo W.
; El tamaño de memoria que se puede grabar por este procedimiento es de 64 bytes como máximo.

	CBLOCK
	ValorCaracter					; Valor ASCII del carácter a escribir.
	ENDC

M24LC256_EscribeMensaje
	movwf	M24LC256_AddressHigh	; El registro W apunta a la página donde va a
	clrf	M24LC256_AddressLow		; grabar el mensaje a partir de la dirección 0.
	call	M24LC256_InicializaEscritura
M24LC256_EscribeOtroByte
	movf	M24LC256_AddressLow,W
	call	Mensaje					; Obtiene el código ASCII del carácter.
	movwf	ValorCaracter			; Guarda el valor de carácter que ha leído del
	call	I2C_EnviaByte			; mensaje y lo escribe en la 24LC256.
	call	Retardo_5ms				; Tiempo de escritura entre byte y byte.
	movf	ValorCaracter,F			; Lo único que hace es posicionar flag Z. En caso
	btfsc	STATUS,Z				; de que sea "0x00", que es código indicador final
	goto	FinEscribeMensaje		; del mensaje sale de la subrutina.
	incf	M24LC256_AddressLow,F
	goto	M24LC256_EscribeOtroByte
FinEscribeMensaje
	call	I2C_EnviaStop			; Termina la escritura.
	call	Retardo_5ms
	return

Mensaje
	addwf	PCL,F
	DT " Estudia D.P.E.",0x0

	INCLUDE  <BUS_I2C.INC>			; Subrutinas de control del bus I2C.
	INCLUDE  <M24LC256.INC>			; Subrutinas de control de la memoria 24LC256.
	INCLUDE  <RETARDOS.INC>
	INCLUDE  <LCD_4BIT.INC>
	END
	
;	===================================================================
;	  Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;	  E. Palacios, F. Remiro y L. López.		[url]www.pic16f84a.com[/url]
; 	  Editorial Ra-Ma.  [url]www.ra-ma.es[/url]
;	===================================================================
```

Un cordial saludos.


----------



## meledu (Oct 4, 2008)

pero me puedes dar un atillo mas en que esta la información que metiste en la memoria en binario hex. esque no lo tengo muy claro , se supone que deve ser 000 y 1111 por eewso es que no me queda claro.
porfarvo envame unos datos mas gracias de amtemano.


----------



## zgouki (Oct 7, 2008)

Amigo meledu:
Primero ante todo buscate el datasheet de la memoria que vas a utilizar, yo uso la página siguiente www.datasheets.org.uk, en el buscador pon las siglas de la eeprom. De todos modos, creo que todas las eeprom de la familia 24LC son iguales, cambian la capacidad de memoria nada mas.
Una vez que tengas el datasheet, fijate cuales son los pines de DATA y de CLOCK (SDA y SCL, respectivamente)
Cuando hagas las conexiones de dichos pines de la eeprom con el PIC que vas a utilizar (acuerdate que debes poner unas resistencias en configuración PULL-UP, osea a Vcc, cualquier duda pregunta),  si vas a utilizar el PSI, en el editor de PIC BASIC, el comando para escribir un byte (en binario, hexa, decimal, lo que tu quieras) en la EEPROM desde el PIC en una dirección que tu elijas es el siguiente 
*I2CWRITE SDA, SCL, 0xA0, ADDR, DATA *
Donde:
*SDA:* el pin del PIC el cual esta conectado con el pin de DATA de la eeprom externa (supongamos PORTA.2 (debes poner esto exactamente, no SDA), que es el PIN1 en el 16F628A y en el 16F84A)
*SCL:*lo mismo que antes pero el de CLOCK (supongamos PORTA.3 = PIN2)
*0xA0:* esto esta en hexadecimal, pero puedes poner en binario anteponiendo el simbolo %, representa el nº de memoria, es decir, por si quieres conectar mas de una memoria al bus de datos (hasta 8, lee el datasheet). En este caso, los 3 pines de la EEPROM que corresponden a A0,A1,A2 estan a GND (sino no funcionara).
*ADDR:* La direccion de la eeprom que quieres escribir (debes leer el datasheet de la eeprom para saber cuantas direcciones posibles puedes usar)
*DATA:* Finalmente, el dato que quieres que se aloje en la memoria (recuerda, un solo BYTE por dirección), por ejemplo en binario, puedes poner reeemplazando DATA por %10101111. 

Si tienes que leer luego ese dato de la eeprom usas la siguiente directiva:
I2CREAD SDA, SCL, 0xA0, ADDR, DATA 
Lo mismo que antes, solo que en DATA no debs escribir nada, ya que DATA es el nombre de la variable que alojara el Byte que lea de la eeprom, despues puedes usar ese dato dentro del programa de tu PIC cuando y como quieras.

Acuerdate del *WaitMs*, por lo menos de 5 milisegundos (seria *WAITMS 5*)entre instruccion, sino no funcionara (trata de experimentar con tiempos menores y despues comenta en el foro).

Espero que te sirva de ayuda. Recuerda que es solo para el lenguaje PIC BASIC del PIC SIMULATOR IDE (te lo recomiendo, es muy facil de usar), para assembler debes preguntarle a meta o a otro forista.
Saludos desde Argentina.


----------



## Meta (Oct 7, 2008)

Menuda explicación amigo.


----------



## avefenix586 (Mar 24, 2009)

hola yo tambien quisiera armarme una matrix de leds para pasar mensajes , pero tambien lo d ela conexion a la memoria eeprom me a sido un dolor de cabeza pero ahora que leo los datos y alcanzes que presentan , tratare de ponerlo en practica, y respecto al amigo que pregunta de que contenido poner en la eeprom externa no seria grabarle los mismos datos que escribio en la misma memoria interna del pic?, los programadores de pics tambien programan eeproms , asi que podrias cargar esa parte en un codigo hex aparte (la data 0101.. del mensaje) y grabarla directamente a la eeprom, antes de conocer los pics yo experimentaba manejar un panel de display por medio del puerto paralelo de la PC, y me cree una utilidad en turbopascal mediante tablas que le ponia un mensaje dentro de un archivo txt por ejemplo "hola bienvenidos a nuestra tienda..." y el programita este me  generaba el patron correspondiente en 1s y 0s en otro archivo hex, creo que quizas crearte una utilidad asi podria servirte.


----------



## jolmar2210 (Jul 17, 2009)

creo que ya ha pasado mucho tiempo desde la ultima respuesta, pero necesito ayuda urgente, a ver si alguien puede ayudarme, paso a exponer mi problema.

pues bien, mi intensión es hacer un letrero con leds, en el cual se pueda ver una palabra de al menos 10 letras, el detalle, es que esa palabra pueda modificarse ingresandola por medio de la pc, por puerto serie, y que ademas se almacene en una memoria externa del tipo 24lcxx.

mas detalles, pienso usar un pic16f628, que tiene el protocolo rs232, no hay problema con eso, ya consegui comunicarme con la pc, ahora voy con la memoria externa, hice la conexion como lo indican aqui, y oh maravilla, consegui guardar datos en la memoria, pero he aqui me desilucion, que por mas que trato no puedo leer nada de esta memoria, no se porque, o que esta mal, me imagino que es algo en el codigo, por que si no tampoco guardaria nada y se que lo hace porque al simular en proteus, veo que los datos estan guardados en sus respectivos registros, escribo pero no puedo leer........

me gustaria subir el codigo que uso, pero tampoco es seguro si alguien se interese en mi problema, o si alguien sabe de un codigo para leer y escribir, pero usando el basic del PSI, para la proxima subire mi codigo pero quisiera ver si alguien puede ayudarme o si se interesa en hacerlo.

es todo,  espero respuestas..........


----------



## idekel (Jul 22, 2009)

Hola, a todos quisiera participar tambien de este foro, con una duda mia, si alguien me pudiera responderla le estaria muy agradecido. Estoy utilizando Pic simulator ide, en mi programa que estoy compilando necesito que el valor de una variable no se borre cuando apague todo el circuito y la inicie de nuevo; me dijeron que tengo que grabarlo en la eeprom, ¿como hago esto? que comandos utilizar si mi variable es de tipo long? con un ejemplo me quedaria mejor, de antemano muchas gracias.


----------



## jolmar2210 (Jul 26, 2009)

mira, recurriendo al manual arriba mencionado del PSI, encontre esto, talvez te sirva, me imagino que si, ya que esta facil, prueba y comenta.....

● Using internal EEPROM memory 

Access to EEPROM data memory can be programmed using READ and WRITE statements. The first argument is the address of a byte in EEPROM memory and can be a constant or Byte variable. The second argument is data that is read or written (for READ statement it must be a Byte variable). It is suggested to keep interrupts disabled during the execution of WRITE statement. 
DIM A AS BYTE 
DIM B AS BYTE 
A = 10 
READ A, B 
WRITE 11, B


----------



## jolmar2210 (Jul 26, 2009)

mientras yo sigo esperando respuestas, como hago para leer mi memoria externa... bueno ahi les subo el codigo que estoy usando, aver si alguien me corrige o me ayuda en algo....


```
AllDigital

Dim addr As Byte
Dim data As Byte

Symbol sda = PORTA.1
Symbol scl = PORTA.0

TRISB = 00000000
PORTB = 00000000

'aqui se escribe en la memoria externa
For addr = 0 To 10

data = 20 - addr

I2CWrite sda, scl, 0xa0, addr, data
WaitMs 500
PORTB = data

Next addr

WaitMs 500

'aqui se lee en la memoria externa, aqui es el problema

For addr = 0 To 10

I2CRead sda, scl, 0xa0, addr, data
WaitMs 500
PORTB = data

Next addr

End
```


----------



## ponce1021 (Ago 3, 2009)

```
AllDigital

Dim addr As Byte
Dim data As Byte

Symbol sda = PORTA.2
Symbol scl = PORTA.3

TRISA = %00001100
TRISB = 00000000
PORTB = 00000000

'aqui se escribe en la memoria externa
For addr = 0 To 10

data = 20 - addr

I2CWrite sda, scl, 0xa0, addr, data
WaitMs 500
PORTB = data

Next addr

WaitMs 500

'asi me funciona con PIC16F628A y 24C01 en protoboard 

For addr = 0 To 10

I2CRead sda, scl, 0xa0, addr, data
WaitMs 500
PORTB = data

Next addr

End
```


----------



## moreno12 (Ago 5, 2009)

hola a todos:
estoy armando un medidor de RPM con un pic 16F628A , 
el programa funciona correcto, 
pero yo quiero agregarle la posibilidad de leer la ultima medicion una vez que ya fue realizada 
si no comprendi mal se hace con la memoria eeprom no? 
lo que necesito es que me digan si se puede guardar el valor de una variable(es el de las RPM) y luego 
poder leerla -en display lcd- nuevamente... 
no se cuales son las instrucciones para decirle al pic que haga esto 
me falto decir que el idioma que estoy usando es BASIC .. 

SALUDOS


----------



## jolmar2210 (Ago 18, 2009)

hola ponce 1021...
tengo una duda, es que a mi no me sale, por mas que pongo tu codigo al pie de la letra, nada,
o es que no me sirve el proteus para simular este circuito.
un favor, ahi subo el ckto, y dime si estoy haciendo mala alguna conexion...
o a cualquiera que pueda ayudarme porfa


----------



## jolmar2210 (Ago 18, 2009)

hola amigo moreno12

si quieres entender algo sobre como usar la memoria eeprom del pic, te recomiendo leer el tutorial sobre eso, claro que no te dice nada del lenguaje basic, pero al menos te da una introduccion al respecto.

ahora, sobre el basic, ya se menciono antes las instrucciones necesarias, solo tienes que buscar en el mismo manual del PSI....

espero poder ayudarte mas la proxima ves, yo tambien estoy estancado y estoy ocupando mi tiempo en eso.... suerte

https://www.forosdeelectronica.com/f24/usar-eeprom-pics-23626/


----------



## avefenix586 (Dic 12, 2009)

arme un circuito con un pic 16f628a y probe el codigo que han posteado y me funciona tal como esta con una memoria 24c08, pude leer y mostrar el contenido de las 10 posiciones de la eeprom por el puerto B, cambie el valor del bucle para leer 255 posiciones de memoria hasta alli todo bien , pero cuando deseo leer mayor capacidad pues el 24c08 tiene una capacidad de 1 kilobye, entonces elevo a 1023 el bucle pero ohh sorpresa el programa pide que cambie el tipo de variable asignada a ADDR, asi que efectivamente la cambio de BYTE a WORD , complio y ensamblo y todo bien luego cargo el programa al pic y ya no puede leer la memoria , en el manual del pic simulator tambien dice que ADDR debe ser word , pero que es lo que esta fallando? porque no lee la memoria 24c08? alguien que me de un alcanze porque quiero leer y grabar memorias de mayor capacidad


----------



## avefenix586 (Dic 13, 2009)

La razon por la que quiero poder grabar una memoria 24lc256 o incluso una de mas capacidad es un proyecto que podria parecer extraño habiendo tantos productos que lo hacen como una notebook, palm, celulares modernos etc etc, lo que se me a ocurrido es  construir un circuito soportado en un pic + 1 lcd de 16 x 2 lineas + 1 teclado estandar simplificado (unas 40 teclas para letras numeros, simbolos y funciones) para implementar un editor de texto basico portatil que puedas llevar a cualquier parte incluso en el transporte en esas largas horas muertas e las que uno esta atrapado en el trafico, puedes ir escribiendo tus trabajos (solo textos) y despues llegado a tu destino puedas transferir el contenido a una pc ( archivo de texto) donde terminarias el trabajo ya en un word con las de la ley,  bueno el artiicio en si debe ser lo mas pequeño posible y con los componentes minimos nesesarios y poder trabajar con baterias recargables al menos alcanzar una hora de autonomia seria un buen comienzo, y por ultimo que sea un equipo economico, con el tiempo podria agregarsele mas funciones como una calculadora , agenda etc etc, no se que les parece esta idea, haber si los expertos nos ayudan o guian en esto o s epueda tomar como un proyecto del tipo codigo abierto.


----------



## Meta (Dic 14, 2009)

Fuente:
http://www.infopic.comlu.com/joomla/index.php?option=com_content&view=article&id=45&Itemid=66






Fuente:
http://www.pic16f84a.org/index.php?...w=article&id=66&Itemid=87#Proteus_Capitulo_22


----------



## avefenix586 (Dic 14, 2009)

gracias por las imagenes, son una buena base, pero lo de usar un teclado ps/2 lo descarto porque queria armar un equipo que entrara facilmente en la mochila y no sea mas grande que un cuaderno


----------



## avefenix586 (Dic 22, 2009)

aunque ahora he visto en el comercio tecladitos pekeńos casi del tamańo del que usan en laptos, quizas mi artilugio podria entrar adentro, y la pantalla lcd asomar por una ranura, con el tiempo podria usarse una pantalla de esas GLC para tener una vista mas amplia del texto, pero por ahora la cuestion es un equipo de bajo costo que puedas sacar en el transporte sin riesgo de tener una gran perdida por robo versus perder un notebook o palmtop o celulares de ultima generacion que son costosos.  
sigo estancado en lo de la grabacion/ lectura del 24lc256 en todo su extencion, el codigo del mismo oshon basic ide no me esta muy claro, existen manuales de como usar el programa y sus herramientas  pero no de como utilizar mas ampliamente el juego de instrucciones, quizas con la compra del producto ellos den un manual mas completo de todas sus instrucciones.


----------



## Arol (Dic 28, 2009)

Hola a todos y disculpen por meterme en su discucion por q en vez de solucion traigo dudas. necesito grabar una eeprom 24c01a por medio de un pic 16f887. desde ya muchas gracias


----------



## Meta (Dic 28, 2009)

Arol dijo:


> Hola a todos y disculpen por meterme en su discucion por q en vez de solucion traigo dudas. necesito grabar una eeprom 24c01a por medio de un pic 16f887. desde ya muchas gracias



Mira aquí.
https://www.forosdeelectronica.com/f24/usar-eeprom-pics-23626/

Saludo.


----------



## tercules (Dic 30, 2009)

Estoy buscando la forma de aumentar eprom  externo a un cartel  de led  pero no se como  hacerlo pero con  los datos que me indicaron  veré  que puedo hacer gracias por su  respuesta .


----------



## falflores (Feb 7, 2010)

Hola, alguien sabe de que manera puedo agilizar la comunicacion entre PIC y memoria?, lo que pasa es que tengo una matriz de 16 X 80, utilizo registros de desplazamiento para las filas y para las columnas (10 y 2 respectivamente de 8 bits cada uno), lo que hago es leer un byte desde la memoria, partirlo en 8 bits, mostrar el primero en la entrada del 1er registro, esperar, cambiar el clock, esperar, volver a cambiar el clock y luego el segundo dato y asi, hasta acompletar 80 bits, luego prendo la fila correspondiente haciendo esta misma operacion con las columnas y sigo con la fila que sigue, pero hice cuentas y para llenar mi matriz me tardo alrededor de 120 milisegundos, el tiempo solo me alcanza para mostrar unos 8 o 9 frames y el minimo es de 24, no me alcanza!!! y eso que lo hice con un cristal de 20MHz.

alguien sabe un método más rapido? 

P.D. yo tenia problemas con el direccionamiento de la memoria, no guardaba, lo que estaba mal era que mi direccion la habia declarado como byte, siendo que debe estar como word, y el comando de control para leer lo puse como A1, si a alguien le sirve.

Para tercules:

para usar la EEPROM en mi matriz de LEDs lo que hice fue guardar el contenido en la memoria, para eso ya han explicado algunos que en Basic se hace con I2Cwrite, SDA, SCL, 0xA1, direccion, dato donde la direccion debe ser word, luego para utilizar esos datos en tu matriz, primero debes leer un byte y guardarlo en una variable del PIC, luego esa variable la reflejas bit por bit en el puerto donde tengas tus registros de desplazamiento, (solo si los usas, claro), haces tu rutina para sincronizar la linea de datos con el reloj de los registros, y presentas el sigueinte bit, esto se hace por medio de la instruccion portX.X = variable.0 a variable.7, y asi solo se muestra un bit a la vez.


----------



## elaveriguador (Mar 22, 2012)

zgouki dijo:


> Amigo meledu: Primero ante todo buscate el datasheet de la memoria que vas a utilizar, yo uso la página siguiente www.datasheets.org.uk, en el buscador pon las siglas de la eeprom. De todos modos, creo que todas las eeprom de la familia 24LC son iguales, cambian la capacidad de memoria nada mas. Una vez que tengas el datasheet, fijate cuales son los pines de DATA y de CLOCK (SDA y SCL, respectivamente) Cuando hagas las conexiones de dichos pines de la eeprom con el PIC que vas a utilizar (acuerdate que debes poner unas resistencias en configuración PULL-UP, osea a Vcc, cualquier duda pregunta), si vas a utilizar el PSI, en el editor de PIC BASIC, el comando para escribir un byte (en binario, hexa, decimal, lo que tu quieras) en la EEPROM desde el PIC en una dirección que tu elijas es el siguiente *I2CWRITE SDA, SCL, 0xA0, ADDR, DATA * Donde: *SDA:* el pin del PIC el cual esta conectado con el pin de DATA de la eeprom externa (supongamos PORTA.2 (debes poner esto exactamente, no SDA), que es el PIN1 en el 16F628A y en el 16F84A) *SCL:*lo mismo que antes pero el de CLOCK (supongamos PORTA.3 = PIN2) *0xA0:* esto esta en hexadecimal, pero puedes poner en binario anteponiendo el simbolo %, representa el nº de memoria, es decir, por si quieres conectar mas de una memoria al bus de datos (hasta 8, lee el datasheet). En este caso, los 3 pines de la EEPROM que corresponden a A0,A1,A2 estan a GND (sino no funcionara). *ADDR:* La direccion de la eeprom que quieres escribir (debes leer el datasheet de la eeprom para saber cuantas direcciones posibles puedes usar) *DATA:* Finalmente, el dato que quieres que se aloje en la memoria (recuerda, un solo BYTE por dirección), por ejemplo en binario, puedes poner reeemplazando DATA por %10101111. Si tienes que leer luego ese dato de la eeprom usas la siguiente directiva: I2CREAD SDA, SCL, 0xA0, ADDR, DATA Lo mismo que antes, solo que en DATA no debs escribir nada, ya que DATA es el nombre de la variable que alojara el Byte que lea de la eeprom, despues puedes usar ese dato dentro del programa de tu PIC cuando y como quieras. Acuerdate del *WaitMs*, por lo menos de 5 milisegundos (seria *WAITMS 5*)entre instruccion, sino no funcionara (trata de experimentar con tiempos menores y despues comenta en el foro). Espero que te sirva de ayuda. Recuerda que es solo para el lenguaje PIC BASIC del PIC SIMULATOR IDE (te lo recomiendo, es muy facil de usar), para assembler debes preguntarle a meta o a otro forista. Saludos desde Argentina.


 mira hermano usa proteus 7.7sp2 
por ejemplo
i2cwrite sda,scl,1010000,0,["y"] ;escribir la letra y en la posicion 0 de la eeprom
i2cwrite sda,scl,1010000,1,["s"] ;igual a la anterior solo que esta ves en la posision 1 de la eeprom
{{{{{{{}}
leer la eeprom
i2cread sda,scl,1010000,0,["y"]dato por de decir algo guardo la letra y en la variable datos
lcdout, dato;y te sale la y en la lcd
pause 500
i2Cread sda,scl,1010000,1,["s"]dato leo la direccion 1 de la eeprom y la guardo en dato
LCDOUT,dato ; y te sale la s 
pause 500
yo era igual que tu yo no eh tenido maestro solo lectura hermano
y escudriñando tutoriales por todos lados preguntando se llega a roma compadre


----------



## elaveriguador (Abr 8, 2012)

zgouki dijo:


> Amigo meledu: Primero ante todo buscate el datasheet de la memoria que vas a utilizar, yo uso la página siguiente www.datasheets.org.uk, en el buscador pon las siglas de la eeprom. De todos modos, creo que todas las eeprom de la familia 24LC son iguales, cambian la capacidad de memoria nada mas. Una vez que tengas el datasheet, fijate cuales son los pines de DATA y de CLOCK (SDA y SCL, respectivamente) Cuando hagas las conexiones de dichos pines de la eeprom con el PIC que vas a utilizar (acuerdate que debes poner unas resistencias en configuración PULL-UP, osea a Vcc, cualquier duda pregunta), si vas a utilizar el PSI, en el editor de PIC BASIC, el comando para escribir un byte (en binario, hexa, decimal, lo que tu quieras) en la EEPROM desde el PIC en una dirección que tu elijas es el siguiente *I2CWRITE SDA, SCL, 0xA0, ADDR, DATA * Donde: *SDA:* el pin del PIC el cual esta conectado con el pin de DATA de la eeprom externa (supongamos PORTA.2 (debes poner esto exactamente, no SDA), que es el PIN1 en el 16F628A y en el 16F84A) *SCL:*lo mismo que antes pero el de CLOCK (supongamos PORTA.3 = PIN2) *0xA0:* esto esta en hexadecimal, pero puedes poner en binario anteponiendo el simbolo %, representa el nº de memoria, es decir, por si quieres conectar mas de una memoria al bus de datos (hasta 8, lee el datasheet). En este caso, los 3 pines de la EEPROM que corresponden a A0,A1,A2 estan a GND (sino no funcionara). *ADDR:* La direccion de la eeprom que quieres escribir (debes leer el datasheet de la eeprom para saber cuantas direcciones posibles puedes usar) *DATA:* Finalmente, el dato que quieres que se aloje en la memoria (recuerda, un solo BYTE por dirección), por ejemplo en binario, puedes poner reeemplazando DATA por %10101111. Si tienes que leer luego ese dato de la eeprom usas la siguiente directiva: I2CREAD SDA, SCL, 0xA0, ADDR, DATA Lo mismo que antes, solo que en DATA no debs escribir nada, ya que DATA es el nombre de la variable que alojara el Byte que lea de la eeprom, despues puedes usar ese dato dentro del programa de tu PIC cuando y como quieras. Acuerdate del *WaitMs*, por lo menos de 5 milisegundos (seria *WAITMS 5*)entre instruccion, sino no funcionara (trata de experimentar con tiempos menores y despues comenta en el foro). Espero que te sirva de ayuda. Recuerda que es solo para el lenguaje PIC BASIC del PIC SIMULATOR IDE (te lo recomiendo, es muy facil de usar), para assembler debes preguntarle a meta o a otro forista. Saludos desde Argentina.


 buenas hermano mira soy principiante y al igual que el compañero no entiendo algo yo escribo en la eeprom 24lc1025 pero tengo una duda sustancial al problemita de la eeprom y es el siguiente programando en picbasic pro (pbp) y es si yo quiero meter en la eeprom 24lc1025 el programa para leer un sensor por Ejemplo el lm35 por decir algo como configuro el programa para utilizar el bus i2c o sea como hago para meter el programa de configuracion del conversor analogico a digital (adcin 0,data )osea todo lo conserniente a el programa del conversor gracias y disculpa tanta molestias algo mas si puedo usar en el mismo bus I2C con el dallas ho el relox d1307 sin que me afecte el desempeño de este gracias una ves mas


----------



## Turcoo (Oct 22, 2014)

Buenas realice un proyecto en el cual se realiza un muestreo de palabras, el problema es que programe en Basic, y utilice el comando Print aproximadamente 3 veces por palabra, en la memoria interna del 16F877A me permite tener unicamente 24 palabras.
Es factible utilizar una memoria 24LC256 para extender la cantidad de palabras? O el seguir utilizando muchas veces el comando Print no me permitiria expandir la cantidad de palabras?


----------



## Cristobal Zelaya Morales (Oct 22, 2014)

Hola. ¿Podría usar una memoria externa, ejemplo 24C04  y almacenar salidas para led por el puerto B?
Esto lo realicé documentándome sobre las memorias eeprom, pero no me funciona.
¿Alguien me puede dar una guía como hacerlo?

Gracias


```
DEFINE   I2C_SCLOUT  1  ;para que no necesite resistencia pull-up en SCL  
contro CON   %10100000       ;contro contiene valor constante %10100000
PinSCL   VAR   Porta.1                    ;pin señal de reloj I2C 
PinSDA   VAR   Porta.0                    ;pin de datos I2C 
dato         VAR BYTE                    ;variable para almacenar dato leído
a var portb.0 
b var portb.1 
c var portb.2 
d var portb.3 
e var portb.4 
f var portb.5 
g var portb.6 
h var portb.7 


Inicio:
I2CWRITE PinSDA,PinSCL,contro,0,[01]    
PAUSE 10                                  
I2CWRITE PinSDA,PinSCL,contro,1,[02]    
PAUSE 10                                  
I2CWRITE PinSDA,PinSCL,contro,2,[03]    
PAUSE 10                                   
I2CWRITE PinSDA,PinSCL,contro,3,[04]    
PAUSE 10
I2CWRITE PinSDA,PinSCL,contro,4,[05]    
PAUSE 10
I2CWRITE PinSDA,PinSCL,contro,5,[06]   
PAUSE 10                                  
I2CWRITE PinSDA,PinSCL,contro,6,[07]    
PAUSE 10                                   
I2CWRITE PinSDA,PinSCL,contro,7,[08]    
PAUSE 10                                   
lee
if porta.2=1 then goto ya
goto lee
ya
leer:        ;programa para leer la memoria serial. 
I2CREAD PinSDA,PinSCL,contro,0,[dato]       
dato=a                            
PAUSE 10                              
I2CREAD PinSDA,PinSCL,contro,1,[dato]       
dato=b                             
PAUSE 10                              
I2CREAD PinSDA,PinSCL,contro,2,[dato]        
dato=c                            
PAUSE 10                            
I2CREAD PinSDA,PinSCL,contro,3,[dato]        
dato=d                         
PAUSE 10
I2CREAD PinSDA,PinSCL,contro,4,[dato]      
dato=e                         
PAUSE 10
I2CREAD PinSDA,PinSCL,contro,5,[dato]        
dato=f                         
PAUSE 10
I2CREAD PinSDA,PinSCL,contro,6,[dato]        
dato=g                         
PAUSE 10
I2CREAD PinSDA,PinSCL,contro,6,[dato]         
dato=h                         
PAUSE 10


end
```


----------



## D@rkbytes (Oct 22, 2014)

Turcoo dijo:


> Buenas. Realicé un proyecto en el cual se realiza un muestreo de palabras.
> El problema es que programé en Basic y utilicé el comando Print aproximadamente 3 veces por palabra. La memoria interna del 16F877A me permite tener unicamente 24 palabras.


La memoria EEPROM interna del PIC16F877A tiene una capacidad de 256 Bytes.
¿A qué te refieres con palabras? (Tal vez un Word)   
Tampoco mencionas que tipo de compilador Basic estás usando. 


Turcoo dijo:


> ¿Es factible utilizar una memoria 24LC256 para extender la cantidad de palabras?
> ¿O el seguir utilizando muchas veces el comando Print no me permitiría expandir la cantidad de palabras?


Si no te son suficientes los 256 bytes de la memoria interna, entonces si es conveniente usar una externa.

Cuando nos des más información, te podremos responder mejor.



Cristobal Zelaya Morales dijo:


> Hola. ¿Podría usar una memoria  externa, ejemplo 24C04  y almacenar salidas para led por el puerto B?
> Esto lo realicé documentándome sobre las memorias eeprom, pero no me funciona.
> ¿Alguien me puede dar una guía como hacerlo?


Si se puede, pero mira bien por qué no funciona lo que haces.
En esta parte tienes lo siguiente...
*I2CREAD PinSDA,PinSCL,contro,0,[dato]       
dato=a                            
PAUSE 10                              
I2CREAD PinSDA,PinSCL,contro,1,[dato]*
*dato=b*

*a* lo definiste como el bit 0 del puerto B
*b* lo definiste como el bit 1 del puerto B
Etcétera.

Tendría que ser...
*a = dato
b = dato*
Etcétera.

Y por cada bit del puerto B tan sólo puedes colocar un 0 o un 1.
No puedes hacer por ejemplo, PORTB.0 = 5
Lo correcto sería que por cada locación de memoria almacenaras, ya sea un 0 o un 1 y ese valor enviarlo a cada pin del PIC.
O almacenar un byte de información y ese valor enviarlo directamente al puerto B.

Algo así:
*I2CWrite PinSDA,PinSCL,contro,0,[$0A]
Pause 10
I2CRead PinSDA,PinSCL,contro,0,[dato]
PORTB = dato

*Suerte.


----------



## alanchavez (Jun 6, 2016)

Hice un programa para grabar datos en una memoria i2c con el pic 16f877a, lamemoria es una  24lc04b, se supone que la primer aparte del programa graba los datos y la segunda los lee, y muestra en una lcd la dirección de la memoria, y la información que encuentra en esta, al parecer la graba bien, pero al leerla en todas las direcciones de la memoria que se supone deberían estar escritas, la lcd muestra un valor de 31, en que podría estar mal?  Wp de la memoria lo tengo a gnd junto con A0,A1 y A2  les adjunto el programa, esperando me puedan ayudar.


```
DEFINE OSC 4
DEFINE LCD_DREG		PORTB	'DEFINE EL PUERTO A USAR EL PIC
DEFINE LCD_DBIT		0 		'DEFINE EL PRIMER BIT A USAR EL PUERTO
DEFINE LCD_RSREG		PORTB	'DEFINE EL PUERTO A USAR PARA RS
DEFINE LCD_RSBIT		5		'DEFINE EL BIT DE RS EN EL PUERTO
DEFINE LCD_EREG		PORTB	'DEFINE EL PUERTO A USAR PARA E
DEFINE LCD_EBIT		4		'DEFINE EL BIT DE E EN EL PUERTO
DEFINE LCD_BITS		4		'DEFINE EL NUMERO DE BITS CONECTADOS AL LCD
DEFINE LCD_LINES		2		'DEFINE EL NUMERO DE LINEAS
DEFINE LCD_COMMANDAUS	1000	'RETARDO ENTRE ENVIO DE COMANDOS AL LCD
DEFINE LCD_DATAUS		50		'RETARDO ENTRE EL ENVIO DE DATOS ENVIADOS

PORTB=%00000000
TRISD=%00000100

SYMBOL SDA = PORTD.0
SYMBOL SCL = PORTD.1

START VAR PORTD.2
LED VAR PORTD.3

CONTROL VAR  BYTE
CONTROL= $A0
DIREC VAR WORD
DATO VAR BYTE
A1 VAR BYTE
X VAR BYTE 
A1=0

LCDOUT $FE,1	'LIMPIA LCD
LCDOUT $FE,2

INICIO:D

LCDOUT $FE,1, "  GRABADORA DE"
LCDOUT $FE,$C0,"  MEMORIAS I2C"
IF START ==1 THEN
GOTO RUTINA
ENDIF
PAUSE 2000

LCDOUT $FE,1	'LIMPIA LCD
LCDOUT $FE,2
IF START ==1 THEN
GOTO RUTINA
ENDIF
PAUSE 200

 LCDOUT $FE,1, "    PRESIONE"
LCDOUT $FE,$C0,"    START.."
IF START ==1 THEN
GOTO RUTINA
ENDIF
PAUSE 2000

IF START ==1 THEN
GOTO RUTINA
ENDIF

GOTO INICIO

RUTINA:

GRABAR:
LCDOUT $FE,1	'LIMPIA LCD
LCDOUT $FE,2

FOR DIREC =0 TO 207

GOSUB DATOS

LCDOUT $FE,1, "DATO.     DIREC."
LCDOUT $FE,$C0, DEC DATO ,"          ",DEC DIREC

LED=1
PAUSE 700
I2Cwrite SDA, SCL, CONTROL, DIREC, [DATO], {ERRORD}

LED=0
PAUSE 10

LCDOUT $FE,1	'LIMPIA LCD
LCDOUT $FE,2
PAUSE 20

LCDOUT $FE,1,"DATO GUARDADO"
PAUSE 700


LCDOut $fe, 1 ' Limpia la LCD
LCDOUT $FE,2
PAUSE 20

NEXT DIREC

FINAL:
LCDOUT $FE,1, "    GRABADO."
LCDOUT $FE,$C0,"   TERMINADO."
PAUSE 2000

LCDOUT $FE,1	'LIMPIA LCD
LCDOUT $FE,2

FOR DIREC =0 TO 207

LED=1
I2CRead SDA,SCL,CONTROL,DIREC,[A1], {ERRORD}
PAUSE 10

LCDOUT $FE,1, "DATO.     DIREC."
LCDOUT $FE,$C0, DEC A1 ,"          ",DEC DIREC

PAUSE 250
LED=0
PAUSE 500

NEXT DIREC

GOTO INICIO


ERRORD:
LCDOUT $FE,1, "    ERROR DE"
LCDOUT $FE,$C0,"    CONEXION"
PAUSE 2000

GOTO INICIO



DATOS:
lookup DIREC,[0,0,0,0,0,0,0,31,27,27,31,27,27,27,0,31,27,27,30,27,27,31,0,31,31,27,24,27,31,31,0,30,31,27,27,27,31,30,0,31,31,28,31,28,31,31,0 _
,31,31,24,30,24,24,24,0,31,31,24,27,25,31,31,0,27,27,27,30,27,27,27,0,31,31,14,14,14,31,31,0,31,31,6,6,22,31,31,0,27,27,30,28,30,27,27,0,24,24,24,24,27,31,31,0,27,31,21,17,17,17,17,0 _
,25,25,29,21,29,19,19,0,31,27,27,27,27,27,31,0,31,25,25,31,24,24,24,0,31,17,17,17,21,19,31,0,3,25,27,28,30,27,27,0,31,31,16,31,1,31,31,0,31,31,14,14,14,14,14,0,27,27,27,27,27,31,31,0 _
,27,27,27,27,27,31,14,0,17,17,17,21,21,31,27,0,17,17,10,4,10,17,17,0,27,27,27,17,4,4,4,0,31,31,1,14,16,31,31],DATO

RETURN
```


----------



## D@rkbytes (Jun 6, 2016)

Mira ahora las correcciones y el funcionamiento del programa.
Está adjunto con simulación.


----------



## nelsonr (Jun 10, 2016)

Hola saludos, tal vez mi pregunta sea llover sobre mojado, pero estoy algo confundido.
Trabajando en CCS Compiler, pic de estudio es el PIC16f877a. Antes cuando quería grabar algo en la memoria por ejemplo una clave  int clave =520,  yo lo grababa en un solo espacio o si  necesitaba mas de un espacio no tenia problema porque el tipo de dato es int.
 write_eeprom(1,clave);

  for( n=0;n<5;n++)
   {             
    write_eeprom(n,clave);//escribo el valor 0 en la dirección 0 de la memoria EEPROM
}  

Pero ahora quiero grabar una cadena por ejemplo “9999999999999999” Según he estado leyendo, es de forma similar write_eeprom( 1,“9999999999999999”);. He incluso no me manda error, pero al momento de presentarlo en un lcd no me sale  nada.
 Printf(Lcd_putc,"clave:%s",read_eeprom(1));  // ni presentado de esta forma 
 Printf(Lcd_putc,"clave:%c",read_eeprom(1));  // ni presentado de esta forma 

Les agradesco su ayuda, no se que me falta, o si grabar una cadena de forma directamente no se puede, o lleva otras funciones antes de grabarla.
** Es importante mencionar de mi parte, que decidí pasar a grabar en memoria datos tipo cadena porque ahora quiero manejar numero mucho mas grande (1 hasta 9999999999999999) y creo que es muy grande para manejarlo de forma entera y en un solo espacio de memoria.
ademas como solo es para presentar en un lcd me pareció bien de esta forma.


----------



## D@rkbytes (Jun 11, 2016)

Si lo que quieres es guardar el valor de una clave con 16 o más dígitos, lo correcto es que la clave la guardes en un arreglo. (Array)

A modo de ejemplo, de ésta manera:

```
void main (void)
{
   int8 clave[16] = {9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9};
   int8 a;
   
   lcd_init();
   
   while (true)
   {
      if(!input(PIN_B3))
      {
         lcd_putc("\fGrabando clave");

         for(a=0;a<sizeof(clave);a++)
         {
            write_eeprom(a,clave[a]);
            clave[a] = 0;
         }
         while(!input(PIN_B3));

         lcd_putc("\fLeyendo la clave");
         
         for(a=0;a<sizeof(clave);a++)
         {
            clave[a] = read_eeprom(a);       
            lcd_gotoxy(a+1,2);
            printf(lcd_putc,"%u",clave[a]);
         }
      }
   }
}
```
Ya que usando una variable tipo int32, tan sólo puedes ingresar hasta 999999999, o su valor máximo de 4294967295.
Y eso será usando la librería; "internal_eeprom.c"

Si quieres guardar los dígitos de la clave en la EEPROM interna al grabar el PIC, puedes hacerlo así:
*#ROM Dir_EEPROM = {9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9}
*Donde Dir_EEPROM, corresponde a la dirección de la memoria interna del PIC. P.E. *0x2100*


----------



## Hermi (Nov 9, 2016)

Hola saludos, estoy teniendo un problema con un programa que desarrollé y  no puedo encontrar una solución o el por qué de mi problema. 
El programa trata de lo siguiente: utilizo un sensor de temperatura y lo  conecto al pic 16F88 para utilizar un adc, las temperaturas las  registra cada 500ms, cada temperatura medida la guarda en una memoria  externa eeprom (24LC256), y luego de X cantidad de medidas guardadas  deberá imprimir en un lcd la temperatura más alta, que fue comparada  antes de ser guardada en la memoria.
Por lo tanto en la memoria en la  posición 0 se encuentra guardada la temperatura más alta y en las  siguientes posiciones todas las temperaturas medidas.

El problema es el siguiente cuando registra una temperatura y el compilador (CCS C Compiler) lee 
write_ext_eeprom(dir_ext_eeprom,dato); 
(donde dir_ext_eeprom es de tipo BYTE, y dato es de tipo char)
entra en un bucle infinito dentro de ese write y no sale de ahí, esto lo  se porque la memoria externa fue depurada con una opción del proteus  y se registró que sólo guardó el primer dato y después se quedó ahí sin  ejecutar la instrucción siguiente, donde hago que imprima cualquier  cosa en el lcd para corroborar que haya continuado con la ejecución del  programa pero esto no sucede.
¿Alguna idea de por qué puede suceder esto?

Como van a ver, por el tipo de pic se tuvo que modificar la librería de la memoria a lo siguiente, para cambiar los pines del pic.

_Libreria de la memoria:_

```
#ifndef EEPROM_SDA

#define EEPROM_SDA  PIN_B3
#define EEPROM_SCL  PIN_A1

#endif
```
_Programa:_

```
#include <16f88.h>
#device adc=10
#fuses HS, NOWDT, XT, NOPROTECT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=8000000)
#define lcd_data4 pin_b4
#define lcd_data5 pin_b5
#define lcd_data6 pin_b6
#define lcd_data7 pin_b7
#define lcd_rs_pin pin_b0
#define lcd_rw_pin pin_b1
#define lcd_enable_pin pin_b2
#include <lcd.c>
#include <24256.c>   //Libreria del 24LC256

void main ()
{

   init_ext_eeprom();                           //INICIALIZAMOS MEMORIA EXTERNA EEPROM
   int16 q;
   char p,aux;
   char t_max=0;                             //variable donde guardo Temperaturia máxima
   BYTE dir_ext_eeprom=1;                        //la direccion de memoria de la eeprom  externa. La ubico en la posición 1 porque la 0
                                                //tiene la temperatura maxima
   int cant_datos=6;                            //como tomamos datos cada 5seg. durante 5 minutos puedo tomar 60 datos.
    
    aux=1;                                       
   char t_max_mostrar=0;                            //variable que muestrea T max obtenida de eeprom ext.                                                  
   setup_adc_ports(0);                          //Selecciona el puerto a realizar la conversion
   setup_adc(adc_clock_internal);               //Selecciona el reloj de conversion
   lcd_init();
    
    
     write_ext_eeprom(dir_ext_eeprom,aux);                       //NO PASA DE ACA!
   printf(lcd_putc,"lala");                             //esto es para probar si salia del write
 
   while (1) {

      set_adc_channel(0);                         //Selecciona el canal de conversion
      lcd_gotoxy(1,1);
      q=read_adc();
      p=((5.0*q)/1024.0)*100;                    //aca guardo la temperatura 
    
      if(cant_datos!=0){
         lcd_gotoxy(1,1); 
         printf(lcd_putc,"Colectando datos"); //imprimo temperatura maxima
         printf(lcd_putc,"\n %d",cant_datos);
        
         cant_datos = cant_datos - 1;                //decremento cant_datos
         
         write_ext_eeprom(dir_ext_eeprom,p);       //guardo en memoria externa el dato sensado
         dir_ext_eeprom= dir_ext_eeprom+1;           //estaba comentado              //incremento una posicion de memoria la eeprom externa. 

          //comparacion de p con t_max
         if (p>t_max){                              //si p>t_max lo reemplazo, sino sigo igual
            t_max=p;     
           write_ext_eeprom(0,t_max);          //estaba comentado         //reemplazo la t_max.
         } 
         
      } else {
         t_max_mostrar=read_ext_eeprom(0);            //tomo la T_max almacenada en la posicion 0 de la eeprom ext.
      
         printf(lcd_putc,"\f");
         printf(lcd_putc,"\n\f");
         printf(lcd_putc,"Temperatura");            //imprimo temperatura maxima
         printf(lcd_putc,"\n%s",t_max_mostrar);
         lcd_gotoxy(6,2);
         printf(lcd_putc,"C");
         break;
      }
      delay_ms(500);
      
      
       
   }
}
```
Muchas gracias y saludos.


----------



## D@rkbytes (Nov 9, 2016)

Hermi dijo:


> El problema es el siguiente cuando registra una temperatura y el compilador (CCS C Compiler) lee
> write_ext_eeprom(dir_ext_eeprom,dato);
> (donde dir_ext_eeprom es de tipo BYTE, y dato es de tipo char)
> entra en un bucle infinito dentro de ese write y no sale de ahí, esto lo  se porque la memoria externa fue depurada con una opción del proteus  y se registró que sólo guardó el primer dato y después se quedó ahí sin  ejecutar la instrucción siguiente, donde hago que imprima cualquier  cosa en el lcd para corroborar que haya continuado con la ejecución del  programa pero esto no sucede.
> ¿Alguna idea de por qué puede suceder esto?


Si se ejecuta la instrucción de escritura en la parte que mencionas en el programa:

```
write_ext_eeprom(dir_ext_eeprom,aux);                       //NO PASA DE ACA!
   printf(lcd_putc,"lala");                             //esto es para probar si salia del write
```
Lo que sucede, es que inmediatamente pasa a las siguientes instrucciones del bucle y por eso no te dará tiempo de ver la escritura en pantalla.

Si pusieras un punto de ruptura en write_ext_eeprom, verás que se ejecuta y continúa con printf.
También puedes detener la ejecución del programa con sleep();
Como no tienes interrupciones, ahí sí podrás ver físicamente o en el simulador, cuando se escribe "lala" en la pantalla.
Por ejemplo:

```
aux = 0x0A;
   write_ext_eeprom(dir_ext_eeprom,aux);                       //NO PASA DE ACA!
   printf(lcd_putc,"lala");                             //esto es para probar si salia del write
   sleep();
```
Y en la ventana de depuración podrás ver que el dato de ejemplo (0x0A) se ha escrito en la dirección 1 (Dirección asignada por "dir_ext_eeprom")
​


----------



## Hermi (Nov 10, 2016)

Gracias por responder, hice lo del sleep e igualmente sigue sin funcionar, porque cuando graba un dato en la memoria no sale de la memoria, sino que se queda ahí dentro como esperando a recibir mas datos que no recibe. Por eso no me ejecuta la siguiente linea de imprimir en el lcd para asegurarme que salió de la memoria.
Adjunte la imagen de debugguear la memoria y se puede ver que recibe el dato que lo guarda y después se queda ahí en el bucle infinito de la memoria y no ejecuta más. (recibe con el ack el primer dato pero después en vez del ack aparece una N por lo tanto no hay envío y transmisión de información, solo tiene que escribir un solo dato y continuar con la ejecución del programa).

Gracias.


----------



## roberttorres (Nov 10, 2016)

Hermi dijo:


> Gracias por responder, hice lo del sleep e igualmente sigue sin funcionar, porque cuando graba un dato en la memoria no sale de la memoria, sino que se queda ahí dentro como esperando a recibir mas datos que no recibe. Por eso no me ejecuta la siguiente linea de imprimir en el lcd para asegurarme que salió de la memoria.
> Adjunte la imagen de debugguear la memoria y se puede ver que recibe el dato que lo guarda y después se queda ahí en el bucle infinito de la memoria y no ejecuta más. (recibe con el ack el primer dato pero después en vez del ack aparece una N por lo tanto no hay envío y transmisión de información, solo tiene que escribir un solo dato y continuar con la ejecución del programa).
> 
> Gracias.



Buenas.
No entiendo cual es el problema, a mi me funciona bien, solo había algunos detalles como la configuración del puerto Analógico. Tu lo has configurado así "setup_adc_ports(0);" y tiene que ser así "setup_adc_ports(sAN0);".
También la librería <24256.c> al modificarla tienes que guardar en la carpeta donde esta tu proyecto y llamarla desde el compilador así "24256.c" con las comillas, porque si no haces ese paso llama a la librería por defecto.
Adjunto la simulación y el código modificado:


----------



## D@rkbytes (Nov 10, 2016)

Eso yo también lo noté pero no le tomé importancia, de hecho en la imagen que subí se puede ver la corrección.
La configuración de pines para la EEPROM externa la realicé dentro del mismo programa para no modificar la librería.
Y es que se supone que el "problema" es que no sale de la escritura en la EEPROM externa.
Sin embargo, yo siempre he visto que sale y continúa normalmente.
Inclusive, se puede poner en 1 cualquier bit de un puerto para encender un LED después de escribir la memoria.


----------



## roberttorres (Nov 10, 2016)

Ahora entiendo, lo que esta pasando es que el esta usando la librería por defecto el cual los pines no coincide con su esquema, yo hice la prueba y efectivamente se queda en un bucle infinito en la eeprom.
La solución como digo el compañero D@rkbytes configurar los pines por software desde tu programa o como te dije yo modificando la librería y guardar en la carpeta de tu proyecto.


----------



## D@rkbytes (Nov 10, 2016)

Sí, de hecho ese problema también sucede si se llega a retirar la memoria.


----------



## Hermi (Nov 12, 2016)

Hola, gracias por las respuestas, perdón que no respondí antes, siempre compilé el programa desde mi computadora y tengo modificada la libreria desde mi pc así que eso no traería problema, sin embargo probé ambas cosas que me dijeron y sigo teniendo el mismo problema.
Lo que me di cuenta fue que entra a mi memoria con el write, guarda el primer dato y se queda en la memoria hasta que la llena completamente por asi decirlo, porque dejé el proteus ejecutandose 5minutos reloj, y luego de eso continuó con la ejecución normal del programa.
Ahora lo que me queda por averiguar es si hay una forma de "frenar" el llenado de la memoria en su totalidad y que simplemente guarde el dato y salga.

Saludos.


----------



## roberttorres (Nov 12, 2016)

Hermi dijo:


> Hola, gracias por las respuestas, perdón que no respondí antes, siempre compilé el programa desde mi computadora y tengo modificada la libreria desde mi pc así que eso no traería problema, sin embargo probé ambas cosas que me dijeron y sigo teniendo el mismo problema.
> Lo que me di cuenta fue que entra a mi memoria con el write, guarda el primer dato y se queda en la memoria hasta que la llena completamente por asi decirlo, porque dejé el proteus ejecutandose 5minutos reloj, y luego de eso continuó con la ejecución normal del programa.
> Ahora lo que me queda por averiguar es si hay una forma de "frenar" el llenado de la memoria en su totalidad y que simplemente guarde el dato y salga.
> 
> Saludos.


Buenas
Definitivamente algo estas haciendo mal, baja el archivo que subí en el post #42(https://www.forosdeelectronica.com/posts/1137243/) y prueba eso, porque repito a mi me funciona bien.
También podrías subir tu proyecto completo(simulación, código y librerías) compimido en un archivo .rar para ver si algo esta mal.


----------



## Hermi (Nov 12, 2016)

roberttorres dijo:


> Buenas
> Definitivamente algo estas haciendo mal, baja el archivo que subí en el post #42 y prueba eso, porque repito a mi me funciona bien.
> También podrías subir tu proyecto completo(simulación, código y librerías) compimido en un archivo .rar para ver si algo esta mal.



Muchas gracias! no había visto que estaba adjuntado el programa, lo probé y funciona a la perfección. Ahí adjunto mi programa con la simulación dentro. Sinceramente no entiendo porqué no está funcionando.

Gracias y saludos!


----------



## roberttorres (Nov 12, 2016)

Hermi dijo:


> Muchas gracias! no había visto que estaba adjuntado el programa, lo probé y funciona a la perfección. Ahí adjunto mi programa con la simulación dentro. Sinceramente no entiendo porqué no está funcionando.
> 
> Gracias y saludos!



Ya pude hallar el problema, era en la simulación, al parecer estaba mal configurado el tiempo de escritura del 24lc256, 10 segundos es una eternidad para el pic.
Forma incorrecta:


Forma Correcta:


----------



## D@rkbytes (Nov 13, 2016)

roberttorres dijo:


> Ya pude hallar el problema, era en la simulación.
> Al parecer estaba mal configurado el tiempo de escritura del 24LC256, 10 segundos es una eternidad para el PIC.


Por suerte, ese tipo de errores no se dan físicamente.


----------



## Hermi (Nov 15, 2016)

roberttorres dijo:


> Ya pude hallar el problema, era en la simulación, al parecer estaba mal configurado el tiempo de escritura del 24lc256, 10 segundos es una eternidad para el pic.
> Forma incorrecta:



Muchas gracias! con ese detalle de las fotos que subiste y el adjunto del otro comentario ya tengo todo solucionado!!
Gracias de nuevo


----------

