Autor Tema: ¿Cambiar tipo de una variable en tiempo de ejecución?  (Leído 2112 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado Neutrino

  • PIC10
  • *
  • Mensajes: 29
¿Cambiar tipo de una variable en tiempo de ejecución?
« en: 24 de Enero de 2018, 15:58:00 »
Buenos días chicos, soy nuevo por acá y en un proyecto en el que estoy trabajando tengo un problema:

Tengo un PIC18F2550 y necesito que almacene unos valores de 10bits (500 valores) y otros de 1bit (1000) la selección de la longitud de bits a leer se hace por comandos  usando el puerto serial.

El punto es que 1000*char me gasta 50% de la memoria del uC y por lo tanto 500*int me gasta también 50% de la memoria del uC lo que me dejaría sin memoria para la lógica y el resto de cosas que tengo que hacer.

Mi idea es recolectar estos datos en dos "pasadas", la primera para llenar el array con los valores de 10bits y la segunda para llenar el array con los 1000 datos de un bit.

Si uso un array de 1000 posiciones de tipo char, no puedo almacenar los valores de 10bits y si uso un array de 500 posiciiones de tipo entero solo puedo almacenar 500 datos de 1bit.

Como sé que tengo memoria suficiente, (más del 50% destinada solo para este array) hay alguna forma de eliminar el array y crear uno nuevo con un tipo distinto? teniendo en cuenta que la cantidad de memoria es exactamente igual?

¿Hay alguna otra forma de hacerlo? O directamente no se puede.

Saludos y muchas gracias de antemano por cualquier ayuda.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #1 en: 24 de Enero de 2018, 21:16:47 »
Citar
10bits (500 valores)

Eso equivale a un minimo de 5000bits, un char que es de 8 bits no alcanza para representar los 10, lo mas simple en este caso es usar variables de 16 bits.

Ahora 500 valores es bastante, son 1000 bytes (en 16bits)  por lo que si, tenes el 50% del valor ocupado de tu RAM de comienzo.

Por un lado tenes eso.
Por otro lado para acceder bit a bit, podes crear un programa, en que reciba el numero de bit a leer (siendo el primero el 0), de alli lo divida por 8, el resultado te va a dar en que byte se encuentra y luego el resto te va a dar la posicion del bit.

Por ejemplo el valor 9, tendrias que al dividirlo por 8 ( rotar 3 veces a la derecha ) es de 1, y el resto es 1, entonces usando un array de 8bits (char) podes obtener el valor de ese bit. Y eso te ocuparia unos 125bytes.

Dejando unicamente 2048 - (1000 + 125 ) = 923 bytes para el micro ( variables/stack/etc )

Pienso que dentro de tenes un 45% destinado a eso.

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

Citar
Como sé que tengo memoria suficiente, (más del 50% destinada solo para este array) hay alguna forma de eliminar el array y crear uno nuevo con un tipo distinto? teniendo en cuenta que la cantidad de memoria es exactamente igual?

No tenes memoria dinamica, pero si estas dispuesto a "eliminar" el array para poder poner otro array, entonces quiere decir que no tenes problema de REUTILIZAR el mismo array para cualquiera de los valores ( sean los de 10bits o los de 1bit)

La diferencia aca es que vas a crear 1000 posiciones de un array de 8bits, y luego con punteros, castearlo a 16bits cuando quieras almacenar y usar los de 10bits. Aunque ahora valores de 1 bits vas a poder guardar 1000 * 8 = 8000  si usas el metodo que nombre antes en el mismo array.
Eso si, o es el array con valores de 10bits o es el de 1bits.

El tema es que si o si vas a ocupar esos 50%, a no ser que puedas almacenar menos valores.

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #2 en: 25 de Enero de 2018, 03:25:38 »
¿No se podría utilizar una union?

Código: [Seleccionar]
union {
    uint16_t array_10bits[500];
    uint8_t   array_1bit[1000];
}

Así ambos arrays se ubican en la misma memoria, así que tendrías que utilizar uno, al terminar de utilizarlo poner todo a 0 (¿o no?) y utilizar el otro array.
o conseguir un pic con mayor memoria, que a veces termina siendo más fácil/barato.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #3 en: 25 de Enero de 2018, 04:32:08 »


Tal vez puedes probar con malloc/calloc/free, para asignar y liberar bloques de memoria en tiempo de ejecución.


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #4 en: 25 de Enero de 2018, 06:55:18 »
La de Carl47D esta mas simple si no queres usar punteros. Tanto esta como mi opcion vas a tener uno u otro, y que vas a tener que poner a 0 al momento de cambiar de uno a otro.
Con un memset.

La de planeta9999 creo que no tiene sentido aplicarlo en el PIC, ya que no solo vas a ocupar mas espacio en la Flash para poder crear todo el sistema de memoria dinamica, sino que ademas vas a tener que crear un HEAP del tamaño del array que tenias antes, y ese HEAP lo vas a poder aprovechar unicamente cuando no tengas el array, que segun el creador del post es nunca. Sino el HEAP va a quedar vacio pero no se cuenta como una RAM para usarla a voluntad por el compilador.

Desconectado Neutrino

  • PIC10
  • *
  • Mensajes: 29
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #5 en: 25 de Enero de 2018, 13:22:36 »
Citar
10bits (500 valores)

Eso equivale a un minimo de 5000bits, un char que es de 8 bits no alcanza para representar los 10, lo mas simple en este caso es usar variables de 16 bits.

Ahora 500 valores es bastante, son 1000 bytes (en 16bits)  por lo que si, tenes el 50% del valor ocupado de tu RAM de comienzo.

Por un lado tenes eso.
Por otro lado para acceder bit a bit, podes crear un programa, en que reciba el numero de bit a leer (siendo el primero el 0), de alli lo divida por 8, el resultado te va a dar en que byte se encuentra y luego el resto te va a dar la posicion del bit.

Por ejemplo el valor 9, tendrias que al dividirlo por 8 ( rotar 3 veces a la derecha ) es de 1, y el resto es 1, entonces usando un array de 8bits (char) podes obtener el valor de ese bit. Y eso te ocuparia unos 125bytes.

Dejando unicamente 2048 - (1000 + 125 ) = 923 bytes para el micro ( variables/stack/etc )

Pienso que dentro de tenes un 45% destinado a eso.

Hola KILLERJC, muchas gracias, justo estaba pensando algo así, aunque solo había ideado la forma de escribir en el array, no de leerlo, mi idea era tener un buffer de 16bits y un contador hasta 15 (0 a 15) y otro hasta 500 (para llenar el array) e ir rotando los bites que me van llegando de modo que el primero quede en el bit más significativo y el último en el menos significativo una vez lleno el buffer (leídos los 16bits) lo guardo en la posición del array correspondiente.

Con la forma de leer el array que me propones creo que tengo suficiente.

¿No se podría utilizar una union?

Código: [Seleccionar]
union {
    uint16_t array_10bits[500];
    uint8_t   array_1bit[1000];
}

Así ambos arrays se ubican en la misma memoria, así que tendrías que utilizar uno, al terminar de utilizarlo poner todo a 0 (¿o no?) y utilizar el otro array.
o conseguir un pic con mayor memoria, que a veces termina siendo más fácil/barato.

Hola, Carl47D la verdad en mi clase de uC no vimos estructuras de datos y no estoy muy familiarizado con C, pero si funciona como dices, se parece mucho a lo que tenía en mente cuando hice la pregunta y me ahorra codear un par de funciones, me voy a documentar un poco a ver cómo funciona esta estructura. Muchas gracias.

Así a simple vista me surge una duda: ¿Qué significan los tipos uint8_t y uint16_t? o es lo mismo que usar un char e int respectivamente?


Tal vez puedes probar con malloc/calloc/free, para asignar y liberar bloques de memoria en tiempo de ejecución.

Hola planeta9999 justo despues de publicar el post, me acordé que hace años cuando estaba aprendiendo C leí sobre malloc(), pero Microchip me mató la ilusión cuando leí en las FAQ que ese tipo de funciones no están habilitadas para el XC8 (http://microchipdeveloper.com/faq:15) igual muchas gracias.


Saludos y muchas gracias a todos por responder.

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #6 en: 25 de Enero de 2018, 18:18:08 »
Citar
Hola, Carl47D la verdad en mi clase de uC no vimos estructuras de datos y no estoy muy familiarizado con C, pero si funciona como dices, se parece mucho a lo que tenía en mente cuando hice la pregunta y me ahorra codear un par de funciones, me voy a documentar un poco a ver cómo funciona esta estructura. Muchas gracias.

Así a simple vista me surge una duda: ¿Qué significan los tipos uint8_t y uint16_t? o es lo mismo que usar un char e int respectivamente?

En internet hay algunos tutoriales o puedes consultar a tu profesor, las uniones son fáciles de entender, solo hay que tener cuidado al utilizarlas.

Los tipos uint8_t y uint16_t estan definidos en el header stdint.h, el uintX_t es un entero sin signo de X bits, por lo tanto el uint8_t es un entero sin signo de 8 bits y el uint16_t es un entero sin signo de 16 bits, es buena practica utilizarlos.

La ventaja que tienen sobre el char e int es que el tamaño de estos últimos puede cambiar dependiendo de la arquitectura que estés utilizando, en la PC el char e int pueden ser un entero con signo de 8 bits y un entero con signo de 64 bits respectivamente, en otras arquitecturas el int es de 32 bits, en PICs creo que el int es de 24 bits (de esto ultimo no estoy muy seguro).
« Última modificación: 25 de Enero de 2018, 18:20:17 por Carl47D »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #7 en: 25 de Enero de 2018, 18:45:17 »
En caso de que quieras hacer aprovechar los 8 bits de cada byte incluso usando una union como dice Carl47D el codigo seria simple:

Código: C
  1. const uint8_t mascara[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  2.  
  3. bool func(uint16_t posicion) //Hasta 2047 valores
  4. {
  5.    uint8_t numbyte, numbit;
  6.    numbit = posicion & 0x7;
  7.    numbyte = posicion >> 3;
  8.    return array1_bit[numbyte] & mascara[numbit];
  9. }

Como dice Carl,
el problema de usar char/int etc es que cambia no solo segun la arquitectura, sino el compilador, si usas CCS el int es de 8bit, y en XC8 es de 16bits, lo bueno es que si usas los int8_t o uint8_t vas a poder trasladar tu codigo a otros compiladores y vas a saber que si o si va atener 8 bits, solo algunos casos en que micros que no soportan 8 bits por ejemplo entonces por mas que pongas uint8_t el compilador se va a asegurar que al menos tengas 8 bits.

Por otro lado, tambien es raro que encuentres manejo de memoria dinamica ( malloc/calloc/free ) en microcontroladores, por lo mismo que nombre antes, el costo computacional es alto y no resulta provechoso, no solo en XC8, sino que parte por el extra que se le da al micro. Ahora en micros mas grande si es posible usarlos.

Desconectado Neutrino

  • PIC10
  • *
  • Mensajes: 29
Re:¿Cambiar tipo de una variable en tiempo de ejecución?
« Respuesta #8 en: 08 de Febrero de 2018, 10:31:58 »
Hola chicos,

Perdón por no responder antes, pero tuve que salir de improvisto de la ciudad y acabo de regresar.

Muchas gracias por las respuestas y por el código. Pueden dar el tema por solucionado.

Gracias de nuevo.

Saludos.