Autor Tema: Se puede realizar reset y mantener los registros?  (Leído 2387 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado nestoriano

  • PIC10
  • *
  • Mensajes: 19
Se puede realizar reset y mantener los registros?
« en: 11 de Octubre de 2011, 02:55:26 »
Esa es mi duda, estoy por realizando un proyecto en la que trato de hacer la rutina lo mas simple posible.

Tengo una serie de registros (unos 200 o mas) que comienzan todos en 0, luego dentro del programa esos registros van cambiando de valor (en tarea1) y lo que necesito es que tras resetear, esos registros se mantengan. El reset es para el cambio instantaneo a otra subrutina (tarea 2, 3 o 4).

En ASM había visto la función "ORG xxx" que tras el reset, el programa comience desde la linea ORG,  hay algo parecido pero en C? La funcion ORG iría después de colocar todo los datos  a 0 así tras resetear no se me borre los registros.   

Mi idea seria algo asi

--------------
inicio

int8 valor1=0;
...
...
...

int8 valor100=0;

#####org                    /////////// tras el reset que comience desde aqui asi no vuelve a poner todo a 0

main()

if(input(pin_a0)==1)

tarea1                            ///////////en esta rutina va asignando los valores correspondiente a todos los registros

else

tarea2                           


if(input(pin_a1)==1)

tarea3

else

tarea4

--------------------------------



Y otra pregunta de principiante, no pasa nada por meterle 5v o  masa directo a las patas de entrada sin resistencias?


Espero ayuda. Gracias.




Desconectado AKENAFAB

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3227
Re: Se puede realizar reset y mantener los registros?
« Respuesta #1 en: 11 de Octubre de 2011, 03:35:45 »
Si puedes realizar reset y mantener el contenido de los registros("RAM")

Algunos registros del micro pueden o no ser afectados.Tienes que leer el apartado RESET CONDITION FOR SPECIAL REGISTERS aparte de eso hay unas tablitas que indican que cambios hay al ocurrir un reset.

Ahora , hay varios tipos de reset y para hacer lo que tu deseas es revisar el tipo de reset y sobre el origen de este determinar si inicias los registros o no.
Hay un registro en el cual indica el tipo de reset.Deberás revisar al inicio de tu programa ese registro.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
No debería pasarle nada si ingresas los 5v directos , en especial si esos 5v vienen de algun circuito digital.
Como recomendación ponle alguna resistencia pequeñita de 100 ó  220 ohms si estas conectando esos 5v de la alimentación o algun otro lado.

Saludos!
« Última modificación: 11 de Octubre de 2011, 03:38:34 por AKENAFAB »

Desconectado nestoriano

  • PIC10
  • *
  • Mensajes: 19
Re: Se puede realizar reset y mantener los registros?
« Respuesta #2 en: 11 de Octubre de 2011, 14:58:12 »
Hola gracias por responder. Me falto aclarar que el tipo de reset que queria realizar es por un pulsador en la pata MCLR. El pic con el que estoy trabajando es un 16f628a.

Estuve leyendo el tema del reset y si no entendí mal con el reset por MCLR durante funcionamiento normal, los registros RAM se mantienen y otros registros (no dice pero supongo que serán los resultados de ADC, contadores, etc) se resetean.

Mi programa seria este:

------------------------------------------------------------------------------------

#include <pr13 secuencia prog.h>
#byte portb=6

long   tiempo   =   400 ;

int8   byte01   =   0   ;
int8   byte02   =   0   ;
int8   byte03   =   0   ;
int8   byte04   =   0   ;
int8   byte05   =   0   ;
int8   byte06   =   0   ;
int8   byte07   =   0   ;
int8   byte08   =   0   ;
int8   byte09   =   0   ;
int8   byte10   =   0   ;
int8   byte11   =   0   ;
int8   byte12   =   0   ;
int8   byte13   =   0   ;
int8   byte14   =   0   ;
int8   byte15   =   0   ;
int8   byte16   =   0   ;




short   us01   =   1   ;
short   us02   =   1   ;
short   us03   =   0   ;
short   us04   =   0   ;
short   us05   =   0   ;
short   us06   =   0   ;
short   us07   =   0   ;
short   us08   =   0   ;
short   us09   =   0   ;
short   us10   =   0   ;
short   us11   =   0   ;
short   us12   =   0   ;
short   us13   =   0   ;
short   us14   =   0   ;
short   us15   =   0   ;
short   us16   =   0   ;





void mostrar(void); 
void programar(void);


void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);

   //TODO: User Code
   do{
   set_tris_a(0b00000111);
   
   if(input(pin_a0)==1)
   programar();
   
   else
   
   mostrar();
   }while(true); 
}

////////////////////////////////////////////////////////////
void mostrar(void)
{
set_tris_b(0);

do{
if(us01==1)
   {
   portb=byte01;
   delay_ms(tiempo);
   }
   
   
   
   if(us02==1)
   {
   portb=byte02;
   delay_ms(tiempo);
   }
   
   
   
   if(us03==1)
   {
   portb=byte03;
   delay_ms(tiempo);
   }
   
   
   
   if(us04==1)
   {
   portb=byte04;
   delay_ms(tiempo);
   }
   
   
   
   if(us05==1)
   {
   portb=byte05;
   delay_ms(tiempo);
   }
   
   
   
   if(us06==1)
   {
   portb=byte06;
   delay_ms(tiempo);
   }
   
   
   
   if(us07==1)
   {
   portb=byte07;
   delay_ms(tiempo);
   }
   
   
   
   if(us08==1)
   {
   portb=byte08;
   delay_ms(tiempo);
   }
   
   
   
   if(us09==1)
   {
   portb=byte09;
   delay_ms(tiempo);
   }
   
   
   
   if(us10==1)
   {
   portb=byte10;
   delay_ms(tiempo);
   }
   
   
   
   if(us11==1)
   {
   portb=byte11;
   delay_ms(tiempo);
   }
   
   
   
   if(us12==1)
   {
   portb=byte12;
   delay_ms(tiempo);
   }
   
   
   
   if(us13==1)
   {
   portb=byte13;
   delay_ms(tiempo);
   }
   
   
   
   if(us14==1)
   {
   portb=byte14;
   delay_ms(tiempo);
   }
   
   
   
   if(us15==1)
   {
   portb=byte15;
   delay_ms(tiempo);
   }
   
   
   
   if(us16==1)
   {
   portb=byte16;
   delay_ms(tiempo);
   }
   

   
}while (true);
}



///////////////////////////////////////////////////////////

void programar(void)
{
   do{
   byte01=input_b();
   delay_ms(200);
       }while(true);
}

------------------------------------------------------------------------------------


En la rutina "programar" que todavía no esta terminado es para leer el puerto b y guardar el resultado a los registros bytes, acompañado de un bit para validar o ignorar el resulado para la rutina mostrar.

El programa ahora como esta debería leer el puerto b y después de resetear, debería parpadear mostrando por el puerto b el registro byte01. Cuando lo reseteo se borra el registro que había guardado según el simulador ISIS. Acaso el simulador no mantiene la RAM despues de resetear?

Saludos!


Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Se puede realizar reset y mantener los registros?
« Respuesta #3 en: 11 de Octubre de 2011, 15:21:36 »
no te viene mejor usar un for() y los datos con corchetes? [] byte[15] ?? asi para ponerlo a 0 es mucho mas simple con 3 lineas.


lo de ORG que dices es para poner esa funcion, variable o codigo en una direccion de memoria, es decir si pones org 0x90 lo que venga despues empezara en la direccion 0x90, sin embargo desconozco lo que dices que al hacer reset volvia a esa parte de codigo, yo diria que no, cuando haces reset el pic vuelve a empezar por la direccion 0x00.

Al hacer reset solo se resetean los registros SFR (en el datasheet vienen cuales, y que datos se le asignan al hacer reset). Sin embargo puede que tus datos en la RAM sean pisados en la inicializacion (esto ya es cuestion del compilador), la memoria RAM queda intacta a no ser que el voltaje baje de determinado (en el datasheet).

De todas formas al poner int8 byte01 = 0; probablemente en el reset el mismo compilador genere el codigo que ponga a 0 esa variable ya que se consideraria idata (datos inicializados).

Desconectado manwenwe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2211
Re: Se puede realizar reset y mantener los registros?
« Respuesta #4 en: 11 de Octubre de 2011, 16:28:01 »
Aunque parezca obvio: ¿te has planteado utilizar una EEPROM externa?
Ojo por ojo y todo el mundo acabará ciego - Mahatma Gandhi -

Desconectado nestoriano

  • PIC10
  • *
  • Mensajes: 19
Re: Se puede realizar reset y mantener los registros?
« Respuesta #5 en: 11 de Octubre de 2011, 16:51:03 »
Hola gracias por resonder. Empece a programar en C hace poco y se que el programa no esta optimizando. Una vez que termine con esto empezare a mejorarlo y ver si le puedo agregar mas funciones. Por ahora esta es la forma en que lo puedo hacer.

Ya pude solucionar mi problema quitandole el " = 0" en los valores iniciales de mis registros. Ahora tras el reset mis valores se siguen manteniendo segun el simulador.

Ahora... si pongo

int8 byte01;

cuanto le doy el encendido al pic, byte01 SIEMPRE comienza en cero en el primer arranque y tras resetear se mantienen los datos sin volver a cero?




-------------------------------

Inicialmente pense en colocar una eeprom  24c32 que tengo a mano para realizar DUMPs de la RAM para tener guardado varias secuencias.  Mi proyecto se trata de realizar un cartel de led de secuencia programable desde el mismo hardware sin usar PC. Por ahora desconozco como dumpear la ram a la eeprom asi que eso lo dejare para el futuro. En realidad creo que lo puedo hacer pero voy a tener que hacer 500 instrucciones para guardar 100 registros de la ram en la eeprom. Seguramente hay otra forma pero todavia no llegue a eso.


Gracias por la ayuda.

Desconectado manwenwe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2211
Re: Se puede realizar reset y mantener los registros?
« Respuesta #6 en: 11 de Octubre de 2011, 16:58:39 »
1º. Creo que serían unas pocas más de 500 isntrucciones :P. De todas formas: si lo haces sólo una vez al inicio no creo que te consumiera demasiado tiempo "real" si subes el reloj (creo que tu máximo es 20MHZ).

2º Si cambias de micro (el tuyo creo que no lo acepta) podrias guardar las las variables en flash: te ahorrarias la eeprom. Ten en cuenta que la eeprom suele admitir 100k ciclos de escritura mientras que la flash 10k cilcos

1 saludo
Ojo por ojo y todo el mundo acabará ciego - Mahatma Gandhi -

Desconectado nestoriano

  • PIC10
  • *
  • Mensajes: 19
Re: Se puede realizar reset y mantener los registros?
« Respuesta #7 en: 11 de Octubre de 2011, 19:45:22 »
Hola por fin pude hacer funcionar mi secuencia de led programable pero acabo de encontrar un fallo en mi hardware que puede mandar al pic al otro mundo. Si apreto alguno de los interruptores mientras muestra la secuencia haria un corto de 5v en una pata del pic.

Tambien tengo un problemita en la rutina "programar" que a veces me toma los datos y otras no.

-------------------------------------------

if(us01==0)
   do{
   
      byte01=input_b();
      if(input(pin_a1)==1)
      us01=1;
      }while(input(pin_a1)==0);
   
   delay_ms(500);
   
   if(us02==0)
   do{
   
      byte02=input_b();
      if(input(pin_a1)==1)
      us02=1;
      }while(input(pin_a1)==0);
   
   delay_ms(500);
   
 
----------------------------

Esto lo invente para guardar y validar la lectura del puerto B en el registro byteXX. Cuando aprete el pulsador por menos de medio segundo se pasa al otro bucle en espera de ser pulsado otra vez.

En teoría eso funciona? El efecto rebote creo que esta eliminado con el delay_ms.


Creo que este proyecto sera mejor si lo hago con un 16f877a que tambien tengo a mano.

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: Se puede realizar reset y mantener los registros?
« Respuesta #8 en: 11 de Octubre de 2011, 21:07:42 »
realmente no entiendo que tiene que hacer tu codigo, es bastante confuso, lo digo porque si lo que necesitas es esperar que se pulse 2 veces es mucho mas sencillo que el codigo que has puesto ahi xD

Desconectado nestoriano

  • PIC10
  • *
  • Mensajes: 19
Re: Se puede realizar reset y mantener los registros?
« Respuesta #9 en: 11 de Octubre de 2011, 23:43:23 »
Seguramente hay otra forma de hacer lo mismo que yo pero mas optimizado y mas claro pero por ahora esta es la forma en que me salio a mi.

#include <pr13 secuencia prog.h>
#byte portb=6

long   tiempo   =   400 ;
long   tiempo2  =   500 ;

int8   byte01         ;
int8   byte02         ;
int8   byte03         ;
int8   byte04         ;




short   us01         ;
short   us02         ;
short   us03         ;
short   us04         ;



void mostrar(void);  
void programar(void);


void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);

   //TODO: User Code
   do{
   set_tris_a(0b00000111);                                ////////////// habilito algunas patas para pulsador


   if(input(pin_a0)==1)                                    /////////////  si el pin A0 esta en 1, se va al ciclo eterno de "programar"


   programar();
  
   else
  
   mostrar();                                               /////////////// si al contrario esta a 0, se va al ciclo eterno de "mostrar" , la unica forma de salir del ciclo eterno es con un reset y
                                                                //////////////// cambiando el pin A0.

   }while(true);  
}
                                                                

void mostrar(void)                            /////////// por puerto B sale los 8 bits del byte01. Un retardo y sale los 8 bits siguientes del byte02. Luego muestra byte03 y 04.
{
set_tris_b(0);
portb=0;

do{

   if(us01==1)                                  ////////// este registro "us01" es un flag. inicialmente todos los byteXX y usXX estan en cero. si byte01 esta acompañado
                                                      ////////// por su flag "us01" en 1, sale por portb los 8 bits del byte01. Si us01 esta en cero quiere decir que aun no se le
                                                      ///////// asigno ningun valor al byte01, en ese caso se ignora.
   {
   portb=byte01;
   delay_ms(tiempo);
   }
  
  
  
   if(us02==1)                                /////////// resumiendo, los unicos bytesXX que se muestra en la secuencia de leds son los que tienen su flag en 1.
                                                    /////////// esto es para poder hacer secuencias menores a lo maximo que se puede. Osea hacer secuencias de 2 bytes a 100 bytes.
   {                                               /////////// los bytesXX que no se usan se ignoran y no se muestran.
   portb=byte02;
   delay_ms(tiempo);
   }
  
  
  
   if(us03==1)
   {
   portb=byte03;
   delay_ms(tiempo);
   }
  
  
  
   if(us04==1)
   {
   portb=byte04;
   delay_ms(tiempo);
   }
  
  
  
   }while(true);
  
}



void programar(void)                            //////////// en esta seccion es para asignarle valores a mis registros bytesXX usando llaves y un pulsador.
{                                                      
   set_tris_b(0);                        
   portb=255;
   delay_ms(tiempo);                             //// parpadea todas las luces para saber que entre a modo programacion
   portb=0;
   delay_ms(tiempo);
   portb=255;
   delay_ms(tiempo);
   portb=0;
   delay_ms(tiempo);
  
   set_tris_b(255);
   do{
  
  
   if(us01==0)                                //////////// lo que hace aca es leer el puerto B y guardarlo en byte01. El programa se queda aca hasta que aprete el pulsador A1.
   do{                                            //////////// Cuando apreto el pulsador A1, a este byte01 se lo acompaña con un flag para saber que  ya no es
                                                    //////////// mas el valor inicial, sino el valor de la lectura del portb.
      byte01=input_b();                  
      if(input(pin_a1)==1)
      us01=1;
      }while(input(pin_a1)==0);       /////////// una ves asignado el valor del primer byte hace lo mismo con el resto, los bytes no asignados se ignoran en la rutina "mostrar"
  
   delay_ms(tiempo2);
  
   if(us02==0)
   do{
  
      byte02=input_b();
      if(input(pin_a1)==1)
      us02=1;
      }while(input(pin_a1)==0);
  
   delay_ms(tiempo2);
  
   if(us03==0)
   do{
  
      byte03=input_b();
      if(input(pin_a1)==1)
      us03=1;
      }while(input(pin_a1)==0);
  
   delay_ms(tiempo2);
  
   if(us04==0)
   do{
  
      byte04=input_b();
      if(input(pin_a1)==1)
      us04=1;
      }while(input(pin_a1)==0);
  
   delay_ms(tiempo2);
  
  
  
   }while(true);
  
}

/////////////////////////////////////////////////

Estoy teniendo problemas por ahora para asignarle valores a mis registros "bytes" usando mis 8 llaves. A veces programa y otras veces no lo hace. Programo 4 bytes y me programa 2 o 3 o a veces 1 solo byte.


Alguien tiene una mejor idea para reemplazar mi rutina de "programar"? Si el programa sigue sin entenderse voy a tratar de explicarlo mejor.


####################################################################
####################################################################
####################################################################

Me edito. Ya tengo el proyecto (casi) terminado. Faltaría probarlo en una protoboard para ver si funciona como en la simulación. Si todo va bien voy a agregar algo para poder variar el tiempo de la secuencia y tambien conectarlo con una eeprom externa.

Grabe la simulacion en un AVI de 1 min, si lo miran sabrán que es lo que intente hacer durante todo el dia. Comprimido pesa 150kb :shock: Changos que comprime jeje.

Saludos!!!
« Última modificación: 12 de Octubre de 2011, 01:36:33 por nestoriano »