4 votos

Cómo eliminar varios if else para manejar los datos fácilmente

Estoy haciendo un proyecto que tiene un tablero hecho a medida basado en PIC32 MCU . Tiene 30 Inputs y 10 Output . Tengo que monitorear las entradas y enviar la información a la UART. Cada entrada tiene un código definido. Por ejemplo: si la entrada 1 está en ON, entonces los datos a enviar son 11 {'1'--> Input 1, '1' --> ON} . Si la entrada 1 está en OFF, los datos a enviar son 10 {'1'--> Input 1, '0' --> OFF} . Del mismo modo, si la entrada 24 está activada, entonces 241 si está apagado, entonces 240 y lo mismo ocurre con todas las entradas.

Ahora los datos finales que se enviarán por UART contendrán información sobre todas las entradas:

10 20 30 41 50 61.....271 280 291 300 

Como soy principiante en programación, lo que he hecho para lograr la sintaxis anterior es que he definido variables para cada entrada.

char input1ON[]  = "11";
char input1OFF[] = "10";
bool input1Stat  =  false;

char input2ON[]  = "21";
char input2OFF[] = "20";
bool input2Stat  = false;

y lo mismo para las 30 entradas completas. Ahora en la función principal:

if(PORTDbits.RD6 == 1)  // if input1 is high
{
  input1Stat = true; //make input1 status true
}
if(PORTDbits.RD6 == 0) //if input1 is low
{
  input1Stat = false; //make input1 status false
}
if(PORTDbits.RD7 == 1)  // if input2 is high
{
  input2Stat = true; //make input2 status true
}
if(PORTDbits.RD7 == 0) //if input2 is low
{
  input2Stat = false; //make input2 status false
}
/*
* same goes for rest of the inputs
*/

entonces después de todas las sentencias if, estoy comprobando si input1stat es verdadero y luego lo strcat, como abajo:

if(input1Stat == true) //if input 1 status is true
{
  strcat(inputs,input1ON); //concatenate input1ON variable with inputs variable 
}
else
  strcat(inputs,input1OFF); //concatenate input1OFF variable with inputs variable 

if(input2Stat == true) //if input 2 status is true
{
  strcat(inputs,input2ON); //concatenate input2ON variable with inputs variable 
}
else
  strcat(inputs,input2OFF); //concatenate input2OFF variable with inputs variable 

Así que al final sólo estoy poniendo inputs a la UART:

putsUART1(inputs);

así que como resultado estoy recibiendo la cadena de datos de arriba en UART. Pero el problema es que hay muchas sentencias if else en mi código, lo que hace que el código sea ilegible. Creo que puede haber alguna otra manera de manejar esto. Como soy principiante, no sé cómo eliminar todas estas declaraciones if else. Alguien puede dar una demostración para eliminar todas las sentencias if else. Gracias.

EDITAR

La entrada 1 y la entrada 2 no son más que PORTDbits.RD5 & PORTDbits.RD6 . He utilizado la entrada 1 y la entrada 2 sólo para la demostración. He hecho los cambios.

0 votos

Sólo para aclarar, ¿se trata de C o C++? Ya que estás usando un tipo bool.

1 votos

@VicenteCunha bool es la norma C desde hace 17 años.

0 votos

@pipe Es justo, mi error. En C estoy acostumbrado sobre todo al estándar avr-libc, que no incluye un <stdbool.h>.

4voto

GSerg Puntos 33571

Cuando se trata de un conjunto de entradas que son todos los pines individuales que pueden tener mapeos arbitrarios a los pines físicos del chip, lo primero que hago es crear una función que mapea desde el número de entrada lógica al pin físico:

bool pin_read (int n)
{
  switch (n) {
  case 0: return PORTDbits.RD6;
  case 1: return PORTDbits.RD7;
  /* ... etc. */
  }
}

Tenga en cuenta que una función de este tipo sería normalmente una función en una función compilada por separado pin que también contiene funciones como pin_write() y pin_direction() . Utilizo un <module>_<method>() para mis funciones en C, lo que realmente ayuda a mantener un seguimiento de las cosas a medida que el proyecto crece.

Una vez que se tiene dicha función, todo lo demás se puede manejar con bucles. Para capturar el estado de todos los pines:

for (i=0; i<N_INPUTS; ++i) {
  inputStat[i] = pin_read(i);
}

Para imprimir el estado capturado anteriormente:

for (i=0; i<N_INPUTS; ++i) {
  sprintf (temp_buffer, " %d%d", i, inputStat[i]);
  putsUART1(temp_buffer);
}
putsUART1("\n");

0 votos

¿Por qué los dos bucles? No podrías simplemente escribir sprintf (temp_buffer, " %d%d", i, pin_read(i)); El OP no dice nada sobre tener que recordar el estado de los pines.

0 votos

@tcrosley: Solo demostrando que cada operación se puede realizar de forma independiente. En el código del OP, recoge todo el estado y luego produce la salida. El punto es, mediante el uso de números de entrada lógica, puede hacer cualquiera de los bucles en todas las entradas o en algún subconjunto de ellos.

2voto

Passerby Puntos 28913

Ni siquiera deberías necesitar las declaraciones if.

input2Stat = input2;

Asignará el valor si es falso (0) o verdadero (cualquier cosa que no sea 0)

Sin embargo, en general, la mayor parte del desorden proviene de los comentarios redundantes y de los saltos de línea. No es necesario el mismo comentario en cada sección si el código es sencillo de leer, o el comentario puede aplicarse a todo, sólo hay que dejarlo claro.

Puede compactar la sentencia if en una línea si sólo hay una instrucción a la que sigue, omitiendo las llaves. Lo mismo para else.

 if (input2 == true) input2Stat = true;
 else input2Stat = false;

0 votos

O incluso más pequeño, definir InputStat[] e Input[] como arrays, y luego hacer un bucle a través de todos ellos en un for con una variable índice.

0 votos

@rdtsc tal vez, pero tratar de definir una entrada como una matriz es un poco redundante

1voto

xilun Puntos 261

Asumiendo que estás muestreando la entrada y enviando al mismo tiempo en un micro pequeño, normalmente no me molestaría en concatenar la cadena de salida, la enviaría directamente por la UART sobre la marcha. Tal vez podrías escribir una función como esta:

void send_in_state(uint8_t io_number, bool val)
{
    if (io_number >= 10)
        putcUART1(io_number / 10 + '0');
    putcUART1(io_number % 10 + '0');
    if (val)
        putcUART1('1');
    else
        putcUART1('0');
    putcUART1(' ');
}

Acabo de usar putcUART1 como un marcador de posición para la función de enviar un solo carácter, probablemente se llame de otra manera. Entonces en el código principal tendrías algo como

send_in_state(1, PORTDbits.RD6);
send_in_state(2, PORTDbits.RD7);
// etc...

Si quieres muestrear en un punto anterior antes de enviar podrías seguir utilizando la función anterior pero guardando los estados de entrada antes:

bool save_input1 = PORTDbits.RD6;
bool save_input2 = PORTDbits.RD7;
// ...
send_in_state(1, save_input1);
send_in_state(2, save_input2);

0voto

pipe Puntos 314

Para esta construcción:

if(input1 == true)  // if input1 is high
{
  input1Stat = true; //make input1 status true
}
if(input1 == false) //if input1 is low
{
  input1Stat = false; //make input1 status false
}

Suponiendo que input1 sólo puede ser true o false y no hay un tercer estado, puedes simplemente escribir:

input1Stat = input1 ? 1 : 0;
input2Stat = input2 ? 1 : 0;
...

Esto ya es mucho más fácil a la vista, pero es probable que compile el mismo código. Más adelante explicaré por qué estoy usando 1/0 en lugar de verdadero/falso.

if(input1Stat == true) //if input 1 status is true
{
  strcat(inputs,input1ON); //concatenate input1ON variable with inputs    variable 
}
else
  strcat(inputs,input1OFF); //concatenate input1OFF variable with inputs variable

De nuevo, sólo hay dos estados. Esto puede ser sustituido por:

const char *input1Stat[2] = { "10", "11" };
const char *input2Stat[2] = { "20", "21" };
....
strcat( inputs, input1msg[input1Stat] );
strcat( inputs, input2msg[input2Stat] );

Como input1Stat es ahora 0 o 1, seleccionará una de las dos entradas del array de punteros de cadena.

Como un comentario a otra respuesta señaló, en un sistema más grande con punteros "reales" y tal, usted implementaría esto con matriz de punteros. En un microcontrolador como el PIC, los accesos como ese pueden convertirse en mucho código, y a menudo me abstengo de ocultar el código demasiado.

Si no quieres repetirte, puedes manejar cada entrada en un lugar, ponerla en una macro, y luego escribir la macro tantas veces como necesites.

0voto

Jack B Puntos 278

Bueno, en primer lugar esto:

if(input1 == true)  // if input1 is high
{
  input1Stat = true; //make input1 status true
}
if(input1 == false) //if input1 is low
{
  input1Stat = false; //make input1 status false
}

Tiene exactamente el mismo efecto que esto:

input1Stat = input1;

Así te ahorrarás algo de espacio. De hecho, puede que no necesites la variable input1Stat en absoluto. Tal vez pueda utilizar input1 directamente en el otro bloque de código? La única diferencia es exactamente cuando se mide el valor del pin.


En segundo lugar, no necesitas códigos separados para cada estado de cada pin. Puedes construirlos automáticamente a partir del número de pin y el 0 o 1 para el apagado o el encendido. Así que puedes hacer algo como

// For pin one
strcat(inputs, "1");
if(input1Stat == true) 
{
  strcat(inputs,ON); 
}
else
{
  strcat(inputs,OFF);
}
strcat(inputs," ");
// and the same for the other pins

Donde se ha definido ON y OFF como "0" y "1" .


En tercer lugar, siempre que estés copiando casi el mismo código para cada pin, será mejor que hagas un bucle sobre esos pines. Lo único complicado es convertir el número de pin de un char a una cadena, y poner los valores de los pines en algún lugar donde puedas acceder a ellos por número. La función sprintf está diseñado para hacer cosas de int-a-cadena y mucho más, pero es una cosa complicada con un montón de sobrecarga ... así que tal vez no es la mejor opción para un PIC. Mira si la función itoa está disponible en tu entorno (puede depender de tu compilador). Si lo está, entonces puede escribir

bool inputStats[] = {input1, input2 ...};

for (char pin=1; pin<30; pin++)
{
    char buffer[3];
    itoa(pin, buffer, 10);
    strcat(inputs, buffer);
    if(inputStats[pin-1] == true) 
    {
      strcat(inputs,ON); 
    }
    else
    {
      strcat(inputs,OFF);
    }
    strcat(inputs," ");
}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X