Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

27/01/2012 #1


guardar arreglo en memoria eeprom
Hola amigos tengo una enorme duda con respecto a la memoria eeprom de mi pic 16f88, no se como se puede guardar un arreglo de 1 fila por 10 columnas en este tipo de memoria, lo quiero hacer con picc, ademas de esto que les comentaba, los datos los quiero sacar del conversor análogo digital del pic, muchas gracias por su ayuda, estaré atento a sus comentarios y posibles ejemplos ilustrativos
31/01/2012 #2


Hola darxin, en realidad no se si esto te ayude pero estaba en algo similar y ya lo logre pero con el C18 compiler.


este fue el código para hacerlo;

Código:
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//escribir en la memoria eeprom interna del pic
/////////////////////////////////////////////////////////////////////////////////////////////////////////

#define USE_OR_MASKS
#include <p18f25k20.h>
#include "EEP.h"

unsigned char  EEPWrite[11] = {1,2,3,4,5,6,7,8,9,10};
unsigned char EEPRead[11];
unsigned char Error=0;

void main(void)
{
    unsigned char q=0;
    unsigned int  address= 0x0200;

      for(q=0;q<16;q++)
      {
      Write_b_eep (address, EEPWrite[q]);    // escribe en la  EEPROM
      address++;                            //incrementa la direccion de la eeprom a la proxima
      
      Busy_eep ();							/* chequea y espera el estado del bit ER */
      }

      address = 0x0200;        // inicializa la dirección de la eeprom
      Error = 0;            //borra la bandera ERROR
      
      for(q=0;q<16;q++)
      {
      EEPRead[q] = Read_b_eep (address++);        //lee la eeprom escrita previamente en su respectiva dirección
      if ( EEPRead[q] != EEPWrite[q] )            //chequea si la data leida es igual a la escrita
      {
        Error=1;                                //si no son iguales la data leida y la escrita, se activa la bandera ERROR
        while(1);                                
      }
      }

      while(1);                        //fin
 }

tu mencionas que lo quieres hacer con picc, nunca he usado ese compilador pero ve a ver si tiene predefinidas funciones para el manejo de la eeprom interna, como en este caso usé las funciones del C18.

Saludos!

---------- Actualizado después de 10 minutos ----------

Hola! no se si esto te sirva pero, estaba en lo mismo practicamente y ya ta listo. El problema es que lo hice fue en C18. este fue el codigo

Código:
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//escribir en la memoria eeprom interna del pic
/////////////////////////////////////////////////////////////////////////////////////////////////////////

#define USE_OR_MASKS
#include <p18f25k20.h>
#include "EEP.h"

unsigned char  EEPWrite[11] = {1,2,3,4,5,6,7,8,9,10};
unsigned char EEPRead[11];
unsigned char Error=0;

void main(void)
{
    unsigned char q=0;
    unsigned int  address= 0x0200;

      for(q=0;q<16;q++)
      {
      Write_b_eep (address, EEPWrite[q]);    // escribe en la  EEPROM
      address++;                            //incrementa la direccion de la eeprom a la proxima
      
      Busy_eep ();							/* chequea y espera el estado del bit ER */
      }

      address = 0x0200;        // inicializa la dirección de la eeprom
      Error = 0;            //borra la bandera ERROR
      
      for(q=0;q<16;q++)
      {
      EEPRead[q] = Read_b_eep (address++);        //lee la eeprom escrita previamente en su respectiva dirección
      if ( EEPRead[q] != EEPWrite[q] )            //chequea si la data leida es igual a la escrita
      {
        Error=1;                                //si no son iguales la data leida y la escrita, se activa la bandera ERROR
        while(1);                                
      }
      }

      while(1);                        //fin
 }
como vez es muy fácil porque uso las funciones que trae definidas el c18, deberías ver si el picc trae funciones para manipular la eeprom interna, yo no lo he usado y no te sabría decir. Si no, y si es muy urgente o necesario que lo hagas, te puedes descargar el hitech que también trae funciones para escribir en eeprom.

Saludos!
02/02/2012 #3


memoria eeprom y ADC
bueno antes de comentar sobre tus códigos user 556, te quería agradecer por tu tiempo y dedicación, mira te cuento un poco sobre mi proyecto, quiero realizar un medidor de la velocidad del viento, para eso quiero utilizar un pin del conversor análogo digital del pic y maestrear cada media hora durante un día esta entrada, ademas de esto después quiero utilizar un max232 para enviar los datos al computador, cree esta rutina basándome en lo que tu me enviaste y por supuesto con un poco de investigación extra, espero tus comentarios, muchas gracias,

PD: aunque ahora me surge una duda sobre la transmisión en el computador, los datos como se entregan desde el pic, como 8 bit o en ASCII, si alguien sabe y me quiere ayudar seria esplendido, gracias

#include <16f88.h>
#device ADC=8
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use standard_io(b)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B5)//Quiero usar un Circuito Integrado max232 para descargar los datos desde la eeprom hasta el computador


int valor=0x00;
setup_adc_ports(RA0_analog); //entrada 0 como analogica
unsigned int address= 0x0200; //Aqui no estoy seguro si debe ir en esa direccion, porque con lo de las direcciones no me manejo en lo absoluto
unsigned char q=0;


void toma_adc(void){ //metodo para la conversion analoga digital

set_adc_channel(0); // Lectura del canal 0
delay_ms(1);
valor=read_adc(); //Le asigno una variable al valor de la lectura del ADC
delay_ms(1); //para que se estabilice
}

void main() { //metodo para escibir lo del ADC en la memoria eeprom


set_tris_a(0xff); // se configura el puerto A como entrada
set_tris_b(0x00); // se configura el puerto B como salida

do {
delay_ms(1800000); //media hora en milisegundos
for(q=0;q<48;q++) // 48 muestras en un dia, cada media hora
write_eeprom (address,valor); //se escribe en la memoria eeprom algun valor
address++; //se incrementa el valor de la direccion de memoria

}while(true);
}
02/02/2012 #4

Avatar de arrivaellobo

El rango que le puedes pasar como parámetro a la función delay_ms() es de 0 a 65535.
Y para enviar los datos al pc, utiliza la función printf();

Un abrazo
02/02/2012 #5


muchas gracias arrivaellobo, tus consejos me sirven de mucho, mas aun cuando la fecha de entrega de mi proyecto se acerca jajajja, bueno por lo que me comentas tengo dos problemas, el primero es con el uso máximo de tiempo de la función delay_ms, ya que solo puede desde 0 hasta 65535, pero se me ocurrió repetir 30 veces delay_ms(60000) para poder completar media hora sin problemas (o también puede ser un circuito externo, aun nose cual, ni como jajjaajjaja), el segundo problema es con relación a la comunicación con el computador y la funcion printf(), yo pensaba que solo era necesario usar #use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B5), para poder lograr esta parte, pero gracias a tus consejos se abre una nueva ventana de explorarcion en esto de los microcontroladores, cuando tenga esto terminado lo vuelvo a subir para escuchar sus sabios consejos, hasta luego gracias!!!
03/02/2012 #6

Avatar de arrivaellobo

De nada darxin, para eso estamos
Si tienes alguna duda o problema consúltalo y te ayudaré en lo que pueda.

Un abrazo
05/02/2012 #7


bueno amigos, después de pedir sus consejos y largas horas de programación termine mi código, voy hacer una recapitulación de lo que quiero hacer como mi proyecto en el cual me juego un semestre de carrera, quiero medir a través de la variación en voltaje de una entrada del pic, la velocidad del viento, para eso quiero que los valores se guarden uno por uno en una dirección de la memoria eeprom del pic 16f88, luego quiero conectarlo a través de rs232 al pc, en donde se preguntara si quiere ver los datos el usuario, en case de ser la respuesta si o un 1, se comienza la descarga de los 48 valores, luego voy a mandarlos a un excel para graficarlos, tengo unas dudas, las voy a enumerar.
1) cuando guardo los valores en la eeprom, luego los leo y muestro en la pantalla del pc, no habrá error en la conversión de binario a numero enteros, con el código que genere?
2)no puedo hacer que la directiva #device adc=8 funcione en el picc, me muestra un error, que podrá ser?
3) cuando se le pregunta al usuario si quiere ver los datos, yo meti esto en un if, esto fue una invencion mía, pero funcionara?, al menos el compilador no arroja errores.
4) luego del printf he visto en otras partes que colocan un return 0, sera necesario?

bueno ahora comienza la construcción de la parte mecánica para generar variación en esa entrada del pic(lo quiero hacer con un motor dc de 3v), y también la construcción del hadware cuando tenga todo terminado prometo subir los archivos para compartirlo con los demás usuario, espero atento sus comentarios y en verdad muchas gracias por su tiempo, saludos


#include <16f88.h>
//#deviceADC=8 // esta linea no me funciona, o sera que no es necesaria?
#include <stdio.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use standard_io(b)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B5)//Quiero usar un CI max232 para descargar los datos hasta el computador


int valor=0x00;
unsigned int address= 0x0200; //Aqui no estoy seguro si debe ir en esa direccion, porque con lo de las direcciones no me manejo
unsigned char q=0;
char viento;
int respuesta;
int valor=0;
setup_adc_ports(RA0_analog); //entrada 0 como analogica


void main() {

set_adc_channel(0); // Lectura del canal 0
delay_ms(1);
valor=read_adc(); //Le asigno una variable al valor de la lectura del ADC
delay_ms(1); //para que se estabilice

set_tris_a(0xff); // se configura el puerto A como entrada
set_tris_b(0x00); // se configura el puerto B como salida

do {
delay_ms(60000); //1 minuto en milisegundos
for(q=0;q<47;q++){ // 48 muestras cada un minuto
write_eeprom (address,valor); //se escribe en la memoria eeprom algun valor obtenido
address++; //se incrementa el valor de la direccion de memoria
}

q=0;
address = 0x0200;
printf("\nDesea ver los datos 1/0:/r");// 1 es un si, 0 en un no
respuesta=getch();
if(respuesta==1)
{
output_high(PIN_B4); //para saber que el pic esta activo y hacer mas didactico el programa
delay_ms(750);
output_low(PIN_B4);
for(q=0;q<47;q++){ //repetir 48 veces esta instruccion
read_eeprom(address); //lee los valores guardados en address
viento=read_eeprom(address); //aqui viento lo declare como char, estara bien?
printf("\nvalor = %d", viento);// muestra en pantalla el valor de esa direccion
address++; //pasa al siguiente valor de la memoria eeprom
}

}
else{
output_high(PIN_B3);// esta parte es solo para hacer mas didactico el proceso
delay_ms(750); //cuando se presione la opcion no
output_low(PIN_B3);
}
}while(true);
}
08/02/2012 #8


amigos ahora estoy depurando mi código y en gran parte ya veo resultados positivos, pero existe una parte del código en la cual creo que existen problemas de sintaxis y es en el ciclo if, bueno primero voy a colocar el código que me resulta.

#include <16F88.h>
#use delay(clock=4000000)
#fuses XT,PUT,NOWDT
#use RS232(BAUD=9600, BITS=8, PARITY=N,xmit=PIN_B5,rcv=PIN_B2)


int respuesta;
void main()
{
do{
printf("Desea ver los datos 1/0: \r"); // 1 es un si 0, en un no
respuesta=getc();

if(respuesta=='1'){

output_high(PIN_B3);
delay_ms(750);
output_low(PIN_B3);

}else if (respuesta=='0'){

output_high(PIN_B7);
delay_ms(750);
output_low(PIN_B7);
}
}while (true);
}

No tengo idea si esto esta bien o si tendré problemas a futuro, pero lo intento como sale en otros tutoriales y no me deja, ya que siempre se cumple la sentencia verdadera, no importa si cumple o no con la condicion.

#include <16F88.h>
#use delay(clock=4000000)
#fuses XT,PUT,NOWDT
#use RS232(BAUD=9600, BITS=8, PARITY=N,xmit=PIN_B5,rcv=PIN_B2)


int respuesta;
void main()
{
do{
printf("Desea ver los datos 1/0: \r"); // 1 es un si 0 en un no
respuesta=getc();

if(respuesta==1){

output_high(PIN_B3);
delay_ms(750);
output_low(PIN_B3);

}else (respuesta==0){

output_high(PIN_B7);
delay_ms(750);
output_low(PIN_B7);
}
}while (true);
}
alguna sugerencia de como poder usar bien la sintaxis de este ciclo, por favor
08/02/2012 #9

Avatar de arrivaellobo

Hola darxin, yo te recomiendo que uses la interrupción por recepción de datos por puerto serie (RDA), ya que tu programa será más eficiente, y en el futuro te será muy útil.
Código:
#include <16F88.h>
#use delay(clock=4000000)
#fuses XT,PUT,NOWDT
#use RS232(BAUD=9600, BITS=8, PARITY=N,xmit=PIN_B5,rcv=PIN_B2)

char respuesta;

#int_RDA
void interrupción_serie(void){
    respuesta=getc();
}

void main(){
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_RDA);
    printf("Desea ver los datos 1/0: \r\n"); // 1 es un si 0 en un no
    while(1){
        if(respuesta=='1'){
            output_high(PIN_B3); 
            delay_ms(750); 
            output_low(PIN_B3);
            respuesta=' ';}
        }else if(respuesta=='0'){
            output_high(PIN_B7); 
            delay_ms(750); 
            output_low(PIN_B7);
            respuesta=' ';}
}
}
}
08/02/2012 #10


muchas gracias arrivaellobo, realmente genial tu comentario y me da otra mirada a mi problema, mira te explico estoy haciendo un debug en proteus y tengo un gran problema, la mitad del código se ejecuta super bien, pero cuando llega a la parte del printf me hace la pregunta en virtual terminal y coloco los valores (1/0) pero el programa simplemente no hace nada! podrá ser porque esta parte requiere de una interrupción como me mencionas?, porque cuando separo lo del printf y lo ejecuto aparte, como puse arriba funciona bien, en un comienzo pensé que era problema de sintaxis pero ahora con tu comentario creo que es la razón.

#include "C:\Users\hp\Desktop\Medidor de velocidad de viento\Programacion\viento.h"

int address= 0x00;
int q;
int y;
char viento;
int respuesta;
int valor=0;
//char fin;

void main()
{
setup_adc(ADC_CLOCK_DIV_8);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_a(0xff); // se configura el puerto A como entrada
set_tris_b(0x00); // se configura el puerto B como salida

do {
q=0;
address = 0x00;
for(q=0;q<47;q++)// 48 muestras cada un minuto
{
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(sAN0|VSS_VDD); // Lectura del canal 0
delay_ms(1);
valor=read_adc(); //Le asigno una variable al valor de la lectura del ADC
delay_ms(1); //para que se estabilice
write_eeprom(address,valor);
address++; //se incrementa el valor de la direccion de memoria
delay_ms(500);
}


//hasta aca funciona muy bien, luego muestra la pregunta sin problemas, pero al momento de responder y ejecutar el if no hace nada

printf("Desea ver los datos 1/0:\r");// 1 es un si, 0 en un no
respuesta=getch();
if(respuesta=='1')
{
y=0;
address = 0x00;
for(y=0;y<47;y++)//repetir 48 veces esta instruccion
{
read_eeprom(address); //lee los valores guardados en address
viento=read_eeprom(address); //aqui viento lo declare como char, estara bien?
printf("valor = %d\r", viento);// muestra en pantalla el valor de esa direccion
address++; //pasa al siguiente valor de la memoria eeprom
output_high(PIN_B3);// esta parte es solo para hacer mas didactico el proceso
delay_ms(750); //cuando se presione la opcion no
output_low(PIN_B3);
}
}
else if (respuesta=='0')
{
output_high(PIN_B4);// esta parte es solo para hacer mas didactico el proceso
delay_ms(750); //cuando se presione la opcion no
output_low(PIN_B4);
}
//printf("Desea salir del programa (s/n): \r")
//fin=getch();
}while(true);
}
aqui dejo los archivos, si por casualidad alguien quiere darme una mano, saludos!
https://rapidshare.com/files/2642775..._de_viento.rar
09/02/2012 #11


Por fin amigos funciono mi programa!!! lo único que me queda por resolver es un pequeño punto sobre el envió de los datos o mas bien, la forma en que se muestran estos valores ya que desde 0V hasta 2.5V muestra valores positivos (0......50.....127), pero desde 2.6V hasta 5V los muestra negativos( -77.......-52.......-1), si se dan cuenta siempre sube el valor en estos dos "intervalos" pero a mi me gustaría que fuera desde 0 hasta 255, sin ocupar numero negativos. Bueno si alguien me puede dar una pista se lo agradecería, muchas gracias, ya queda menos! jajajaja

Por fin amigos funciono mi programa!!! lo único que me queda por resolver es un pequeño punto sobre el envió de los datos o mas bien, la forma en que se muestran estos valores ya que desde 0V hasta 2.5V muestra valores positivos (0......50.....127), pero desde 2.6V hasta 5V los muestra negativos( -77.......-52.......-1), si se dan cuenta siempre sube el valor en estos dos "intervalos" pero a mi me gustaría que fuera desde 0 hasta 255, sin ocupar numero negativos. Bueno si alguien me puede dar una pista se lo agradecería, muchas gracias, ya queda menos! jajajaja

---------- Actualizado después de 2 minutos ----------

bueno aquí coloco los archivos para compartir con los demas usuarios, si alguien ve algo malo me avisa por favor, muchas gracias, saludos
Imágenes Adjuntas
Tipo de Archivo: jpg circuito.jpg (93,1 KB (Kilobytes), 23 visitas)
Archivos Adjuntos
Tipo de Archivo: rar Medidor de velocidad de viento.rar (43,9 KB (Kilobytes), 71 visitas)
10/02/2012 #12

Avatar de arrivaellobo

Eso ocurre porque la variable donde guardas el valor no tiene el suficiente rango.
Utiliza una variable tipo long.

Un saludo
10/02/2012 #13


muchas gracias por los consejos, bueno al final arregle el problema, cambie la variable a tipo long y aun así no cambio el problema, pero cambie una %d por una %u en el printf y se arreglo, nose si sera valido o lo mejor pero funciono, muchas gracias por los consejos, ahora voy a trabajar en el circuito

printf("valor = %u\r\n", viento);
16/02/2012 #14


hola amigos he vuelto, ahora mi problema es que todo la cirquiteria esta bien con respecto al max 232, pero no me muestra el típico mensaje como es el "hola mundo", me asegure q funcione bien esta parte primero puentiando en el db9 el tx y el rx, así lo q envió lo recibo, también lo hice en el max232 y hasta ahí todo perfecto, despues pense que era algo del pic, puse un simple programa con el encender un led.

1 primero se enciende un led despues puse un delay, resultado es q nunca se apago.
2puse un delay antes de encender un led, resultado, nunca prendio

puede ser que en pic wizard equivoque la configuración del cristal y este estè deshabilitado, porque quiero usar un cristal externo de 4M con dos condensadores a tierra, yo lo unico que seleccione en esta opcio nfue cristal externo, ayuda por favor, gracias

---------- Actualizado después de 3 minutos ----------

me falto agregar que en la simulación en proteus, prende y apaga de acuerdo al delay q le puse sin ningún problema
16/02/2012 #15


FUNCIONO FUNCIONO FUNCIONO jajajajja era porque el cristal lo había seleccionado mal en el picwizard, era otra opción al menos el "hola mundo" esta mostrándose ademas el led se enciende como deberia ahora tratare de probar mi programa que me interesa para ver su funcionamiento, al menos ya se que todo lo del max232, hyperterminal, conexiones del pic están bien ahora solo quedara ver que la programación del medidor de la velocidad del viento funcione perfecto, de ahí les comento.
16/02/2012 #16


Hola amigos tengo un nuevo problema jajja lo que pasa es lo siguiente trato de ejecutar esta simple sentencia para poder ver lo que pasa, ya que el hola mundo me salio a la perfección, pero esta vez ni siquiera muestra el mensaje en la pantalla, la programación que estoy intentando probar es la siguiente

#include "C:\Documents and Settings\emi\Escritorio\Programacion\viento.h"
#include <stdio.h>


char respuesta;
//int q;
//int y;
//long address;
//long valor;
//int viento;

#int_RDA
void RDA_isr(void)
{
respuesta=getc();
}


void main()
{

setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

printf("Desea medir la velocidad del viento? 1/0: \r\n"); // 1 es un si 0 en un no
while(true)
{
if(respuesta=='1')
{
output_high(PIN_B7);
delay_ms(750);
output_low(PIN_B7);
respuesta=' ';
}
else if(respuesta=='0')
{
output_high(PIN_B3);
delay_ms(750);
output_low(PIN_B3);
respuesta=' ';
}
}
}


mi pregunta es, debo activar la interrupción RS232 transmit buffer empty también en el wizard, en caso de ser si, como se programa para que funciones correctamente, ademas debo agregar que en proteus funciona bien incluso le hice un debug a las variables y funciona todo con lógica y no se que mas hacer, muchas gracias por su tiempo y saludos

---------- Actualizado después de 53 minutos ----------

ahora coloque unos led antes del printf y si funcionan ademas muestra el mensaje del printf, pero cuando coloco por ejemplo un 1, no pasa nada no se ejecuta el if, que podra ser amigos requiero de su sabiduria por favor, gracias y un abrazo para ustedes que se dan el tiempo de ayudarme
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.