0
\$\begingroup\$

I have a PIC MCU and have 4 input pins. I need to check the status of inputs and set the value of flag. Like if input 1 is active, then value of flag should be 1, if input 1 and input 2 are activated then flag is 2. FOr input 1,2,3 flag=3. For this kind of logic, I though of using multiple if else condition:

if(input1==high)
{
  flag = 1;
  if(input2==high)
  {
    flag=2;
    if(input3==high)
    {
    flag=3;
    if(input4==high)
    {
      flag=4;
     }
  }
 }
}

Is there any way I can skip this if else and can use some other c logic. Please help.

\$\endgroup\$
6
  • \$\begingroup\$ It depends, can you read these 4 inputs at the same time (I mean one mcu operation)? Do they belong to the same port? \$\endgroup\$
    – Al Bundy
    May 17 '16 at 7:39
  • \$\begingroup\$ Yes they belong to same port and can be read at same time. These input can occur at the same time. Like 4inputs can be high at same time \$\endgroup\$
    – S Andrew
    May 17 '16 at 7:48
  • \$\begingroup\$ Why do you want to skip the if logic part and use something else???? \$\endgroup\$
    – Jasser
    May 17 '16 at 8:18
  • \$\begingroup\$ Because I thought there might a better option than using if \$\endgroup\$
    – S Andrew
    May 17 '16 at 8:25
  • \$\begingroup\$ Your question is unclear to me. Are you wanting the value of Flag to represent the NUMBER of bits that are high? In other words, what is the value of Flag when only input 3 is high?\ \$\endgroup\$ May 17 '16 at 13:59
2
\$\begingroup\$

I would consider using a pre-initialised table, like this:

static uint8 table[] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 };

port_val = Read_Port() & 0xf;
flag = table[port_val];

I'm more of an AVR hacker myself, and don't know what the PIC equivalent would be of using PROGMEM to put the table in ROM.

And for 8 bits instead of 4:

uint8 port_val = Read_Port() & 0xff;
flag = table[port_val & 0xf];
if (flag == 4) flag += table[port_val >> 4];
\$\endgroup\$
0
1
\$\begingroup\$

I am assuming that these 4 inputs are lower 4 bits of same port - Pin 0 to 3. You can change values if pins are different.

I would go with something like

port_val = Read_Port() & 0x0F;
switch(port_val)
{
  case 0x01: // Only input 1 is set
     flag = 1;
  break;

  case 0x03: // input 1 and 2 set
     flag = 2;
  break;

  case 0x07: // input 1,2 and 3 are set
     flag = 3;
   break;

  case 0x0F: //All 4 inputs are set
     flag = 4;
  break;
  default:
   //Optional
   flag = 0;
   break;
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ With input 5, the original program has input1 = 1 and input2 = 0 (and input3 = 1), so the result is flag = 1. Swanand's program gives flag = 0 in that case. I'm not 100% sure this matters in the OP's situation, but the two programs do behave differently. \$\endgroup\$ May 17 '16 at 16:10
0
\$\begingroup\$
flag =0 ;
port_val = Read_port() & 0x0F;
for(i=0;i<4;i++)
{
   if(port_val & (0x01<<i))
   {
     flag++;
   }
   else
   {
      break;
   } 
}
\$\endgroup\$
0
\$\begingroup\$

If you really want to do it as a loop, try this:

uint8 port_val = Read_Port() & 0xf;
flag = 0;
while (port_val & 1) {
    flag++; port_val = port_val >> 1;
}

But I would use the lookup table myself: it's faster and very probably smaller too.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I would vote against my own answer if I could. Sadly, SE doesn't seem to appreciate the irony. \$\endgroup\$ May 17 '16 at 14:29
0
\$\begingroup\$

You can do this with one concise line of C code as follows:

flag=x&1?x&2?x&4?x&8?4:3:2:1:0;   // set flag appropriately

It's very important to add comments as I did above to indicate precisely what the statement does. ;-)

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Sorry if this is me going into teacher mode, but this program will translate into object code that's very similar to the OP's original program: the conditional expressions written with ? and : will generate jumping code just like the conditional statements written with if and else. A nice alternative, though. \$\endgroup\$ May 17 '16 at 18:08
  • \$\begingroup\$ @MikeSpivey Of course, and when I compiled it for the AVR it took up exactly the same space. It might actually be worse than the original code for the PIC, I recall that the '?' operator was not very efficient- in fact the Hitech compiler won't handle nested ternary operators at all. Maybe (probably) XC8 works. \$\endgroup\$ May 17 '16 at 18:41
  • 1
    \$\begingroup\$ Ha! My students could do better than that -- but we sensibly target the ARM and save ourselves a lot of grief. \$\endgroup\$ May 17 '16 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.