# ¿Como guardar caracteres en la memoria interna del PIC?



## RALD (Jun 4, 2010)

Buenas Expertos
Tengo la siguiente pregunta y hasta ahora no he logrado encontrar una respuesta que me ayude talvez alguien por aqui pueda ayudarme.
Tengo un PIC conectado a una PC por puerto serial, con un programa que yo voy hacer en visual, le voy a enviar datos al PIC, pero requiero que esos caracteres que le envio al pic sean almacenados en la memoria interna del microcontrolador para luego poder ejecutarlos en mi programa, estoy trabajando en CCS lo que he encontrado son las instrucciones write_eeprom y read_eeprom que parecen ser las instrucciones que requiero pero solo dice que guarda caracteres en hex, entonces no estoy seguro de como hacerlo, tambien quisiera saber como se cuales direcciones de la eeprom estan libres para utilizar...
Gracias por su ayuda.


----------



## rachelies (Jun 4, 2010)

la eeprom esta libre entera, si es que no la utilizas para otra cosa. Y ahora te digo de memoria como creo que debe ser la escritura de caracteres, pero te advierto que nunca lo he probado y que te hablo de memoria. tendrias que comprobarlo y tomarlo como una idea para seguir avanzando:
Los caracteres que envias desde el PC los meteria en una variable de tipo caracter, y luego enviaría esto a la eeprom con las instrucciones que has dicho, y luego al leerlo, meterlo de nuevo a un registro de tipo caracter. Pruebalo.


----------



## RALD (Jun 4, 2010)

rachelies gracias por responderme,
Ys realice la prueba con la eeprom y es mas sencillo de lo que pense, tenias razon se puede almacenar el caracter directamente en la memria, estoy todabia realizando pruebas para ver que no produsca errores y tan pronto este perfecto subo el programam para aquellos que lo necesiten, si tengo un pregunta: cuando dices que la memoria eeprom del PIC esta limpia eso quiere decir que puedo utilizar las direcciones 0x00 hasta el maximo de la memoria?... en donde se guarda el programa del PIC yo pensaba que usaban la misma memoria?


----------



## rachelies (Jun 4, 2010)

Puedes usar desde la 0x00 hasta la maxima que tengas. El programa se guarda en otra memoria Flash, en la memoria de programa. Y luego está la memoria RAM, que es la que utiliza el pic para ejecutar el programa. espero haberte aclarado.
Saludos


----------



## RALD (Jun 4, 2010)

Hola rachelies
ya logre hacer que en la eeprom se almacenen datos en formato char, pero requiero poder extraer esos datos convetirlos a int16 o int32 para luego dividirlo entre 100 o 100, te doy un ejemplo: si guardo 250, luego lo convierto a numeros decimales para dividirlo entre 1000 y obtener 0.25 pero no logro hacer que el atoi me haga esa conversion alguna idea?...
	
	



```
#include <16f882.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                     //Crystal/Resonator with PLL enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES PUT                      //Power Up Timer
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES MCLR                     //Master Clear pin enabled

#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_c6,rcv=PIN_c7)  
#include <string.h>
#include <stdlib.h>
#include <input.c>

#define on output_high
#define off output_low
#define led1 pin_c0

void main (void){
      int8 char1, char2, caracter, x2;
      char string [5], x;
      float valor_numerico;
      char1 = "w";
      char2 = "r";
      on (led1);
      delay_ms (1000);
      while (true){
      off (led1);
      printf ("para escribir el valor oprina (w) para verificar el valor oprima (r)\n\r");
      x = getc();
      if (x == char1){
         printf ("escriba el valor a dividir\n\r");
         gets (string);
         write_eeprom (0, string);
         printf ("precio almacenado: %s\n\r", string);
         printf ("espere por favor\n\r");
         delay_ms (2000);
         printf ("\n\r");
      }
      else if (x == char2){
         strcpy (string, read_eeprom (0));
         printf ("valor: %s\n\r", string);
         x2 = atoi32 (string[4]);
         valor_numerico = x2/1000;
         printf ("valor a dividir: %ld\n\r", valor_numerico);
         printf ("espere por favor\n\r");
         delay_ms (2000);
         printf ("\n\r");
      }
      }
}
```
no estoy muy seguro de que estoy haciendo mal ya que es la primera vez que hago esto....
gracias por tu ayuda


----------



## rachelies (Jun 5, 2010)

Ahora mismo sin el manual no se lo que hace el atoi
Con el ejemplo que diste de 250, para dividir entre 1000, haria lo siguiente y en una linea:
Teniendo declarada la variable donde tienes almacenado el 250 como caracter, y donde quieres guardar el 0.25 como float, es decir, por ejemplo, 

char caracter
float resultado

resultado=caracter/1000;

solo con esto ya te deberia guardar el resultado como un numero en decimales

Pruebalo


----------



## RALD (Jun 5, 2010)

Hola

ya trate con esa formula que me pasate pero igual me da resultado 0, ademas que no estoy seguro que funcione con lo que estoy tratando de hacer, ya que, como viste en mi programa estoy recibiendo un string de caracteres que como te dije puede ser 250 pero la division entre 1000 no me sale, aun cuando el valor_numerico es una float...
tienes alguna otra idea?

EL atoi lo que hace es convertir el string en un caracter numerico como por ejemplo:

char string[10];
int x;

strcpy(string,"123");
x = atoi(string);  // x is now 123


----------



## RALD (Jun 8, 2010)

rachelies
ya logre hacer que el programa funcionara casi perfectamente, primero el caracter que envio lo almaceno en la direccion 0 luego utilizo el atoi para convertirlo en una varible de 8 bits o 16, la division entre 1000 solo es sopotortada por unidades de 32 bits, pero aun hay algo que no me queda claro, el uso de la memoria por que al parecer no me esta leyendo las direcciones por separado si no que todo me lo guarda en la misma direccion de memoria.... estoy enviando dos string uno lo guardo en al direccion 0 y el otro en la direccion 10 pero no me los lee por separado, sabes a que se debe eso?


----------



## rachelies (Jun 8, 2010)

Pégame el código para verlo e intentaremos buscar el fallo. Las veces que he utilizado el write_eeprom me ha funcionado sin problemas.
Enhorabuena por el avance.
Un saludo


----------



## RALD (Jun 8, 2010)

aqui te dejo el programa que he estado usando para testear la eeprom

```
#include <16f882.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                     //Crystal/Resonator with PLL enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES PUT                      //Power Up Timer
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES MCLR                     //Master Clear pin enabled

#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_c6,rcv=PIN_c7)  
#include <string.h>
#include <stdlib.h>

#define on output_high
#define off output_low
#define led1 pin_c0

void main (void){
      char string [5], char1, char2, x;
      int16 x2, resultado;
      char1 = "1";
      char2 =  "2";
      on (led1);
      delay_ms (1000);
      while (true){
      off (led1);
      printf ("oprima  1 para guardar en direccion 0, 2 para guardar en direccion 10\n\r");
      x = getc();
      if (x == char1){
         printf ("caracter a guardar en direccion 0\n\r");
         gets(string);
         write_eeprom(0,string);
         printf ("%s\n\r", read_eeprom(0));
         printf ("\n\r");
      }
      else if (x == char2){
         printf ("caracter a guardar en direccion  10\n\r");
         gets (string);
         write_eeprom(10,string);
         printf ("%s\n\r", read_eeprom(10));
         printf ("\n\r");
      }
      printf ("%s\n\r", read_eeprom(0));
      printf ("%s\n\r", read_eeprom(10));
      }
}
```

si lo ejecutas en proteus veras que cuando guardas en una direccion y luego en otra se sobre escribe en las dos direcciones.


----------



## cptinoco (Jul 12, 2010)

hola amigos necesito de su ayuda tengo un proyecto y necesito guardar o almacenar en una variable o en su memoria interna una algo asi en el pic: 

LOOÿ.....ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿ....¨)....b.ÿÿÿÿÿÿÿÿ....................Áÿÿÿÿ..œØ


 para luego extraterlo y enviarlo mediante un modem

me puden ayudar

el pic sobre el cual trabajo es 16f877a

gracias
Ecuador


----------



## RALD (Jul 12, 2010)

hola cptinoco

los caracteres no aparecieron bien (creo), cuantos caracteres quieres guardar y de cuanto espacio?


----------



## cptinoco (Jul 13, 2010)

gracias RALD por tu respuesta los caracteres que te llegaron si estan bien pasa de que estos salen asi desde una consola estan encriptados y como no pude desencriptarlos por eso los dejo asi ya que  estos saldrían(que es lo que pienso hacer) tal y como llegan mediante un mensaje de texto a travez del modem......  bueno los caracters son todos esos son como 100:

*""  .LOOÿ.....ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿ....¨)....b.ÿÿÿÿÿÿÿÿ....................Áÿÿÿÿ..œØ  ""*

como puedo hacer para almacenarlos dentro del pic..... y leerlos para enviarlos...??????

gracias
Ecuador


----------



## rachelies (Jul 13, 2010)

yo creo que en la eeprom podrias guardar 100 caracteres. Si no me equivoco, cada caracter es un byte, y ese pic tiene 256bytes de memoria. Puedes hacer un bucle que los guarde en la memoria, y otro para leerlos y enviarlos.


----------



## dilmer (Sep 20, 2010)

Hola RALD estoy queriendo hacer un trabajo, pero primero tengo que convertir el estring a uno entero y ps me parecio muy interesante lo que estas haciendo, lo que yo estoy haciendo no me funciona o es que esta algo mal... Pues parta recibir el string solo lo puse gets(string). Y lineas arriba ya no lo pongo getc(...). Bueno no se si estoy haciendo bien. gracias de antemano


----------



## verogirl (Sep 20, 2010)

el getc() es para caraceres individuales segun lo que tengo entendido...



rachelies dijo:


> yo creo que en la eeprom podrias guardar 100 caracteres. Si no me equivoco, cada caracter es un byte, y ese pic tiene 256bytes de memoria. Puedes hacer un bucle que los guarde en la memoria, y otro para leerlos y enviarlos.



y supongo que si tu pic tiene mas memoria podras guardar mas, verdad?


----------



## RALD (Sep 25, 2010)

saludos Dilmer 

si hay una forma para convertir el string en datos para ser almacenados en la memoria del PIC, como cuando recibes un numero en caracteres y quieres convertir a un solo valor numerico.

Hola Verogirl
la respuesta es si, entre mas memoria mas caracteres se pueden almacener


----------



## jasg260894 (Jul 1, 2014)

Tengo un programa y no he encontrado la instrucción para guardar los datos en la memoria eeprom.
Quiero guardar cada diez minutos los valores que me arrojen la temperatura y la hora.


```
#include <16f877.h> // Pic a utilizar
#device adc=10 // Usa resolución de 10 bits
#use delay(clock=4000000) // Cristal a utilizar
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect // Fusibles
#include "internal_eeprom.c"
#include <lcd.c> // Libreria para utilizar LCD por el puerto D
#use standard_io (D)

void main (void)
{
set_tris_a(1);//CONFIGURACION DE PUERTO A COMO ENTRADAS ...
set_tris_b(1);//puerto B COMO ENTRADA....

float temper,medicion;
int hora,min,seg;

lcd_init(); // Inicia LCD
lcd_putc("Termometro\n y reloj"); // Saca texto
delay_ms(400);
lcd_putc("\f");
lcd_putc("Configure hora SI/NO?");
delay_ms(800);

for(;{// AQUI SE CONFIGURA HORA SOLO EN MINUTOS Y HORA...

if(input(pin_b0)==1){
min++;
if(min==60){min==00;hora++;}
}
if(input(pin_b1)==1){
hora++;
if(hora==24){hora==01;}
}

lcd_gotoxy(1,2); // Acomoda cursor LCD
lcd_putc("Hora");
lcd_gotoxy(8,2); // Acomoda cursor LCD

printf(lcd_putc,"%02u:%02u:%02u",hora,mi n,seg); // xxx.x °C
delay_ms(1000);

if(input(pin_b2)==1){goto a;} // BOTON DE STAR ....

}


a:

for(;{

seg++;
if(seg==60){seg=00;min++;}
if(min==60){min=00;hora++;seg==00;}
if(hora==24){min=00;hora=01;seg=00;}



lcd_putc("\f"); // Limpia pantalla
lcd_putc("Temp:"); // Saca texto
lcd_gotoxy(14,1); // Acomoda cursor LCD
lcd_putc("oC"); 



lcd_gotoxy(9,1); // Acomoda cursor LCD
lcd_putc(" "); // Limpia ese sector de pantalla
lcd_gotoxy(9,1); // Acomoda cursor LCD

setup_adc (adc_clock_internal);
setup_adc_ports (all_analog);
set_adc_channel (0); // Elige canal a medir RA0
medicion=read_adc (); // Hace conversión AD 
setup_adc (adc_off); // Apaga ADC
temper=medicion*(0.48875); // Pasa binario a °C


printf(lcd_putc,"%02.1f",temper); // GRADOS °C

lcd_gotoxy(1,2); // Acomoda cursor LCD
lcd_putc("Hora");
lcd_gotoxy(8,2); // Acomoda cursor LCD

printf(lcd_putc,"%02u:%02u:%02u",hora,mi n,seg); // xxx.x °C
delay_ms (800);

} 
}
```


----------



## D@rkbytes (Jul 1, 2014)

jasg260894 dijo:


> Tengo un programa y no he encontrado la instrucción para guardar los datos en la memoria eeprom.
> Quiero guardar cada diez minutos los valores que me arrojen la temperatura y la hora.


La instrucción para escribir en la memoria interna del PIC es: write_eeprom (*address*, *value*);
Solo admite 8 bits, pero en tu código estás usando una librería (internal_eeprom.c) que no adjuntas.

Para escribir los datos cada 10 minutos puedes hacer uso del Timer1 y generar una interrupción cada segundo.
Realizas un conteo en segundos y cuando se cumplan 600 segundos grabas los datos.

Para conseguir una interrupción cada segundo cargas el Timer1 con 3036 (0xBDC) y el prescaler a 1:8
Esto es si lo haces con el reloj principal a 4MHz.
Con reloj externo de 32768Hz. lo cargas con 32768 (0x8000) y con prescaler 1:1
Con la interrupción cada segundo también puedes realizar el reloj y con cristal externo es muy exacto.

Esto ya lo he tratado en otras ocasiones y es muy sencillo hacer lo que requieres.


----------



## jasg260894 (Jul 2, 2014)

me podrias ayudar en darme un ejemplo con eso e batallado mucho te lo agradeseria mucho


----------



## D@rkbytes (Jul 2, 2014)

jasg260894 dijo:


> ¿Me podrías ayudar en darme un ejemplo?
> Con eso he batallado mucho, te lo agradecería mucho.


Olvidé mencionar que al cargar el Timer1 con 3036 (0xBDC) con el oscilador principal a 4MHz, interrumpe cada 500Ms aprox.
En el ejemplo adjunto muestro como lograr un segundo y como escribir en la EEPROM interna cada 10 minutos.
Se puede establecer cualquier otro tiempo, todo depende del valor con el que se cargue la variable.

Utilicé el método con el oscilador principal porque he visto que les ha resultado difícil conseguir el cristal de 32768Hz.

Espero que puedas comprender el código, está comentado y verás que no tiene mucha ciencia.

Suerte.


----------

