La forma más eficiente de crear una matriz bool en C - AVR

7

Estoy usando un Atmega32 para leer varios sensores usando su ADC.

Usando lógica digital y algunos multiplexores, multiplexé la totalidad de PORTA, usando PA0: 6 para la dirección y PA7 como entrada. Por lo tanto, puedo tener un máximo de 128 entradas desde un solo PUERTO.

Ahora, dado que el usuario operará el sistema a través de una computadora (utilizando RS232), será posible agregar o eliminar sensores, por lo que el sistema debe mantener un registro de qué direcciones son libres de agregar sensores y cuáles direcciones leer de.

Estaba pensando en usar una matriz booleana de 128 bits como indicadores para indicar si hay un sensor en una dirección determinada.

Si bien C no tiene soporte nativo para variables de un solo bit, es posible usar campos de bits para agrupar hasta 8 "variables bool" en un solo carácter sin signo.

Entonces, he creado la siguiente estructura:

typedef struct bool_s{
      uint8_t bit1:1;
}bool_t;

Luego, creé una matriz de tipo bool_t con un tamaño de 128, con la esperanza de que todo estuviera bien empaquetado, pero sizeof() me dice que el tamaño de la matriz es de 128 bytes en lugar de los 16 bytes que esperaba.

Técnicamente, podría crear una estructura única con 128 variables de 1 bit:

typedef struct Flag_s{
      uint8_t F1:1;
      uint8_t F2:1;
      uint8_t F3:1;
      [...]
      uint8_t F128:1;
}Flag_t;

El problema con este enfoque es que si bien reduce el uso de la memoria, no es muy práctico de usar y ocupa demasiado espacio en el código.

¿Hay alguna manera fácil de crear una gran cantidad de banderas o estoy pidiendo demasiado? Quiero decir, no es como si guardar 112 bytes suponga una gran diferencia cuando tengas 2K disponibles, pero ¿y si necesitara más banderas?

    
pregunta Chi

3 respuestas

12

Los campos de bits no funcionan así. La respuesta de Cventu muestra una forma correcta de usarlos, pero en este caso, recomiendo evitarlos por completo.

En su lugar, cree una matriz de valores de 8 bits y use desplazamiento y enmascaramiento para acceder a ella:

uint8_t flags[16];

//Initialize the flags
void init_flags(void)
{
    for (i = 0; i < 16; i++)
    {
        flags[i] = 0x00;
    }
}

//Set one flag based on the address
void set_flag(uint8_t address)
{
    flags[address/8] |= 0x1 << (address % 8);
}

//Clear one flag based on the address
void clear_flag(uint8_t address)
{
    flags[address/8] &= ~(0x1 << (address % 8));
}

//Check whether a flag is set
bool get_flag_state(uint8_t address)
{
    return (flags[address/8] & (0x1 << (address % 0x8))) != 0x00;
}

Esto es probablemente lo que hará el compilador con los accesos de campo de bits de todos modos, y es más fácil trabajar con él. Algunos optimizadores son malos para optimizar los campos de bits, por lo que el compilador podría hacerlo peor. Todos los compiladores que he visto giran la división y el módulo mediante una potencia constante de dos en el cambio a la derecha y las instrucciones AND. Puedes usar esas operaciones directamente si te sientes paranoico:

flags[address>>3] |= 0x1 << (address & 0x7);

Los campos de bits son más estructuras que matrices. En mi experiencia, solo son útiles para cosas que tienen nombres, como campos de registro.

    
respondido por el Adam Haun
8

Suena un poco confuso, pero tal vez algo como esto pueda ayudar:

struct bits_field {
                       unsigned char bit_7 :1;
                       unsigned char bit_6 :1;
                       unsigned char bit_5 :1;
                       unsigned char bit_4 :1;
                       unsigned char bit_3 :1;
                       unsigned char bit_2 :1;
                       unsigned char bit_1 :1;
                       unsigned char bit_0 :1;

                   };

union dt {
             struct bits_field a;
             unsigned char b;
         };

Después de definirlos, declare la siguiente variable:

union dt my_data;

Podrás escribir un grupo completo de ocho bits juntos usando: my_data.b

O puede escribir cada bit individualmente usando: my_data.a.bit_7 (o 6,5,4,3,2,1,0)

En caso de que te funcione, replica esto 16 veces (usando una matriz o estructura) y podrás manejar 128 bits individualmente.

Háganos saber si funcionó! Buena suerte

    
respondido por el cventu
0

Cree una estructura donde declare ocho indicadores de bit que terminen siendo un byte. Luego crea una matriz de estas estructuras de 8 bits.

    
respondido por el Michael Karas

Lea otras preguntas en las etiquetas