es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Existe una alternativa adecuada y limpia al enmascaramiento de bits?

Tengo un valor de 16 bits de longitud, en el que cada dos bits describen la configuración de un canal ADC (Bit0-1: Canal 0, Bit2-3: Canal 1, Bit4-5: Canal 2, …).
Ahora tengo una función para establecer la configuración de un canal específico y lo hago enmascarando los bits.

enum class AdcChannel{
  CH0, CH1, CH2, ...
};

uint16<em>t SampleClass::setAdcChannelActive(uint16</em>t configReg, AdcChannel channel){
  configReg &= ~(3 << (channel *2));
  configReg |= CHANNEL_ACTIVE << (channel * 2);
  return configReg;
}

Esto funciona bien, pero me pregunto si hay una forma mejor, donde no sea necesario el enmascaramiento.
En mi mente hay algo como esto:

union C{
 uint16<em>t config;
 struct _ {
   uint16</em>t channel0:2;
   uint16<em>t channel1:2;
   uint16</em>t channel2:2;
   uint16t channel3:2;
   uint16t unused:8;
 } config_struct;
};

enum class AdcChannel{
  CH0, CH1, CH2, CH3
};

uint16<em>t setAdcChannelActive(uint16</em>t configReg, AdcChannel channel){
  C cfg = {configReg};
  cfg.config<em>struct.channel0 = CHANNEL</em>ACTIVE; //Aquí debería poder usar el parámetro del canal
  return cfg.config;
Tags:  ,

Answer

  1. Avatar for davy.ai

    Solución para manipular las configuraciones de los canales de ADC en C++

    Para manipular las configuraciones de los canales de ADC en C++, existen dos posibles soluciones. La primera solución es utilizar el enmascaramiento de bits (bitmasking) y la segunda solución es utilizar estructuras y uniones.

    Solución de enmascaramiento de bits

    En esta solución, utilizamos un valor de 16 bits, en el cual cada dos bits describen la configuración de un canal de ADC. Para establecer la configuración de un canal específico, enmascaramos los bits utilizando desplazamiento de bits y el operador AND.

    enum class AdcChannel{
      CH0, CH1, CH2, ...
    };
    
    uint16_t SampleClass::setAdcChannelActive(uint16_t configReg, AdcChannel channel){
      configReg &= ~(3 << (channel * 2));
      configReg |= CHANNEL_ACTIVE << (channel * 2);
      return configReg;
    }
    

    Esta solución funciona bien, pero el código puede ser difícil de leer y entender. Aquí es donde entra en juego la segunda solución.

    Solución de estructuras y uniones

    En esta solución, utilizamos una unión que permite acceder a la misma ubicación de memoria como diferentes tipos de datos. También utilizamos una estructura para definir los bits que conforman el registro de configuración. El tipo de datos de la unión es la estructura.

    union C{
     uint16_t config; //valor de 16 bits
     struct _ {
       uint16_t channel0:2; //bits del canal 0
       uint16_t channel1:2; //bits del canal 1
       uint16_t channel2:2; //bits del canal 2
       uint16_t channel3:2; //bits del canal 3
       uint16_t unused:8; //bits no utilizados
     } config_struct; //estructura para manipulación de bits
    };
    

    También utilizamos una enum class para definir los diferentes canales de ADC.

    enum class AdcChannel{
      CH0, CH1, CH2, CH3
    };
    

    Para establecer la configuración de un canal de ADC específico, creamos una instancia de la unión C y establecemos los bits del canal correspondiente utilizando la enum class.

    uint16_t setAdcChannelActive(uint16_t configReg, AdcChannel channel){
      C cfg = {configReg}; //inicializar unión con configReg
      switch(channel){ //utilizar la enum class de canal para establecer los bits del canal
        case AdcChannel::CH0: cfg.config_struct.channel0 = CHANNEL_ACTIVE; break;
        case AdcChannel::CH1: cfg.config_struct.channel1 = CHANNEL_ACTIVE; break;
        case AdcChannel::CH2: cfg.config_struct.channel2 = CHANNEL_ACTIVE; break;
        case AdcChannel::CH3: cfg.config_struct.channel3 = CHANNEL_ACTIVE; break;
      }
      return cfg.config; //devolver configReg actualizado
    }
    

    Esta solución es más legible y más fácil de entender que la solución de enmascaramiento de bits, y también permite una expansión más fácil del código para adaptarse a más canales de ADC.

Comments are closed.