带有Arduino的2位加法器

时间:2018-03-27 05:21:49

标签: c++ if-statement arduino arduino-uno

所以我的任务是使用面包板,4个开关,3个LED和一个Arduino制作一个2位加法器。问题在于加法器做了两件冲突的事情(至少在我的代码中),首先是它只打开一个灯(001)打开一个开关,但它还需要计算10+之类的东西00,这只表示一个开关将打开,使得(如我的代码所述)它将最终打开对应于两者的灯而不是仅中间的(010),反之亦然(001)。我知道它与if语句的第一位有关,这里是代码:

int A0Pin = 12;
int A1Pin = 11;
int B0Pin = 10;
int B1Pin = 9;

int LED0Pin = 6;
int LED1Pin = 5;
int LED2Pin = 4;

void setup()
{
  pinMode(A0Pin, INPUT);
  pinMode(A1Pin, INPUT);
  pinMode(B0Pin, INPUT);
  pinMode(B1Pin, INPUT);

  pinMode(LED0Pin, OUTPUT);
  pinMode(LED1Pin, OUTPUT);
  pinMode(LED2Pin, OUTPUT);
}

void loop()
{
  int b1Value = digitalRead(A0Pin);
  int b2Value = digitalRead(A1Pin);
  int b3Value = digitalRead(B0Pin);
  int b4Value = digitalRead(B1Pin);

  digitalWrite(LED0Pin, LOW);
  digitalWrite(LED1Pin, LOW);
  digitalWrite(LED2Pin, LOW);

  if (b1Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,LOW);
  }
  if (b2Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,LOW);
  }
  if (b3Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,LOW);
  }
  if (b4Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,LOW);
  }
  if(b1Value == HIGH && b3Value == HIGH )
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,HIGH);
    digitalWrite(LED2Pin,LOW);
  }
  if(b2Value == HIGH && b4Value == HIGH )
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,HIGH);
  }
  if(b2Value == HIGH && b3Value == LOW && b4Value == LOW)
  {
   digitalWrite(LED0Pin,LOW);
   digitalWrite(LED1Pin,HIGH);
   digitalWrite(LED2Pin,LOW);
  }
  if(b1Value == LOW && b2Value == LOW && b4Value == HIGH)
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,HIGH);
    digitalWrite(LED2Pin,LOW);
  }
  if(b1Value == HIGH && b2Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,HIGH);
    digitalWrite(LED2Pin,LOW);
  }
  if(b3Value == HIGH && b4Value == HIGH)
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,HIGH);
    digitalWrite(LED2Pin,LOW);
  }
  if(b1Value == HIGH && b2Value == HIGH && b4Value == HIGH)
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,HIGH);
   }
  if(b2Value == HIGH && b4Value == HIGH && b2Value == HIGH)
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,HIGH);
  }  
  if(b1Value == HIGH && b2Value == HIGH && b3Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,HIGH);
  }
   if(b3Value == HIGH && b4Value == HIGH && b1Value == HIGH)
  {
    digitalWrite(LED0Pin,HIGH);
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,HIGH);
  }
  if(b1Value == HIGH && b2Value == 
     HIGH && b3Value == HIGH && b4Value == HIGH)
  {
    digitalWrite(LED0Pin,LOW);
    digitalWrite(LED1Pin,HIGH);
    digitalWrite(LED2Pin,HIGH);
  }
  delay(10);
}

请原谅缺乏优化(可以在我弄清楚灯光问题之后),任何有关优化的帮助也会非常感激,但是现在我只需要帮助制作它以便像01+这样的东西00不要因为只有一个开关打开而感到困惑,导致两个灯都打开或只打开一个,但不正确。我是在Tinkercad上做的:

电路图:

Circuit diagram

01 + 01 = 010

01+01=010

第一次开启(01 + 00 = 001)

Just the first switch on (01+00=001)

只是第二次开启,但被误解为10 + 00 = 010(反之亦然)

just the second switch on, but misinterpreted as 10+00=010 (or visa versa)

4 个答案:

答案 0 :(得分:2)

嗯,首先:有比你选择的更好的方法。但是,这个答案将坚持你的方法并解释你的代码失败的原因。

据我所知,你的方法背后的想法是:

1)覆盖没有输入为高电平的情况(即通过转动所有LED启动)。 1例。

2)覆盖恰好1输入高的情况。 4例。

3)覆盖恰好2个输入高的情况。 6例。

4)覆盖正好3个输入高的情况。 4例。

5)覆盖所有4个输入都很高的情况。 1例。

该方法将起作用,因为步骤5优先于步骤4,步骤4优先于步骤3,依此类推。也就是说,即使您在例如步骤4,它将在步骤5中更正(如果所有输入均为高电平)。

  

你的代码出了什么问题?

问题是您没有涵盖所有情况。例如,您永远不会将b1b4都视为高。

此外你还有一个拼写错误:

if(b2Value == HIGH && b4Value == HIGH && b2Value == HIGH)
   ^^^                                   ^^^

此外,您的代码永远不会像在此处一样检查LOW:

if(b2Value == HIGH && b3Value == LOW && b4Value == LOW)

LOW值由if语句的优先级隐式处理。

总的来说,你必须有初始化加上15个if语句。

所以你的代码应该是:

  // Handle 1 case with no input high
  digitalWrite(LED0Pin, LOW);
  digitalWrite(LED1Pin, LOW);
  digitalWrite(LED2Pin, LOW);

  // Handle 4 cases with exactly 1 input being high
  if (b1Value == HIGH)
  {
      ...
  }
  else if (b2Value == HIGH)
  {
      ...
  }
  else if (b3Value == HIGH)
  {
      ...
  }
  else if (b4Value == HIGH)
  {
      ...
  }

  // Handle 6 cases with exactly 2 input being high
  if(b1Value == HIGH && b2Value == HIGH )
  {
    ...
  }
  else if(b1Value == HIGH && b3Value == HIGH )
  {
    ...
  }
  else if(b1Value == HIGH && b4Value == HIGH)
  {
    ...
  }
  else if(b2Value == HIGH && b3Value == HIGH)
  {
    ...
  }
  else if(b2Value == HIGH && b4Value == HIGH)
  {
    ...
  }
  else if(b3Value == HIGH && b4Value == HIGH)
  {
    ...
  }

  // Handle 4 cases with exactly 3 input being high
  if(b1Value == HIGH && b2Value == HIGH  && b3Value == HIGH)
  {
      ...
  }
  else if(b1Value == HIGH && b2Value == HIGH  && b4Value == HIGH)
  {
      ...
  }
  else if(b1Value == HIGH && b3Value == HIGH  && b4Value == HIGH)
  {
      ...
  }
  else if(b2Value == HIGH && b3Value == HIGH  && b4Value == HIGH)
  {
      ...
  }

  // Handle 1 cases with exactly 4 input being high
  if(b1Value == HIGH && b2Value == HIGH && b3Value == HIGH && b4Value == HIGH)
  {
      ...
  }

以上解释了为什么您的代码无法正常工作以及如何修复它。

但是你可以看到这种方法非常容易出错(即很容易错过一个案例)。除此之外,它还有糟糕的表现。所以我建议采用更简单的方法。

int temp = 2 * digitalRead(A1Pin) +
               digitalRead(A0Pin) +
           2 * digitalRead(B1Pin) +
               digitalRead(B0Pin);

output0 = (temp & 1) == 1;
output1 = (temp & 2) == 2;
output2 = (temp & 4) == 4;

答案 1 :(得分:1)

这些引脚标记得很好:A1PinA0Pin等。变量名称应遵循相同的惯例:a1Valuea0Value等。这将使if语句更易于理解。

然后你需要系统地了解if陈述。有4个输入,有16种可能的组合,每个都需要if语句。每个if语句都应检查每个输入值。

所以前两个if语句是

if (a1Value == LOW && a0Value == LOW && b1Value == LOW && b0Value == LOW)
{
    digitalWrite(LED0Pin,LOW);   // 0 + 0 = 0
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,LOW);
}
else if a1Value == LOW && a0Value == LOW && b1Value == LOW && b0Value == HIGH) 
{
    digitalWrite(LED0Pin,HIGH);  // 0 + 1 = 1
    digitalWrite(LED1Pin,LOW);
    digitalWrite(LED2Pin,LOW);
}

和最后一个if语句是

else if (a1Value == HIGH && a0Value == HIGH && b1Value == HIGH && b0Value == HIGH)
{
    digitalWrite(LED0Pin,LOW);   // 3 + 3 = 6
    digitalWrite(LED1Pin,HIGH);
    digitalWrite(LED2Pin,HIGH);
}

还有13个要去。

现在当然还有其他方法可以做到这一点,但我想我会帮助你完成你的开始。

让代码正常工作后,您可以将其发布到code review,然后就如何优化代码提供各种建议。

答案 2 :(得分:1)

根据Yunnosch评论这是他的意思,你可以预先计算加法的价值,然后将其显示给LED,这大大简化了代码 下面的代码应该起作用 - 或者至少作为指导 我在一个例子中评论了你理解逻辑,希望它有所帮助

注意:因为我不在Arduino的前面这个代码没有经过测试 - 但它确实编译了

int A0Pin = 12;
int A1Pin = 11;
int B0Pin = 10;
int B1Pin = 9;

int LED0Pin = 6;
int LED1Pin = 5;
int LED2Pin = 4;

void setup()
{
  pinMode(A0Pin, INPUT);
  pinMode(A1Pin, INPUT);
  pinMode(B0Pin, INPUT);
  pinMode(B1Pin, INPUT);

  pinMode(LED0Pin, OUTPUT);
  pinMode(LED1Pin, OUTPUT);
  pinMode(LED2Pin, OUTPUT);
}

void loop()
{
  int b1Value = digitalRead(A0Pin);
  int b2Value = digitalRead(A1Pin);
  int b3Value = digitalRead(B0Pin);
  int b4Value = digitalRead(B1Pin);

  // b1 is set to represent 1 and b2 will represent 2 same with b3 and b4 pair
  // lets assume b1 = 1 b2 = 0 the number is 1
  // b3 is set to 1 and b4 is set to 1
  // input : b2|b1 + b4|b3
  //          0| 1    1| 1
  // sum = 1*1 + 0*2 + 1*1 + 1*2 = 4 - which is represented in binary as b100
  int sum = (b1Value * 1) + (b2Value * 2) + (b3Value * 1) + (b4Value * 2);

  if (sum & 0x1) //binary rep b001 - following the example will result in 0
    digitalWrite(LED0Pin, HIGH);
  else
    digitalWrite(LED0Pin, LOW);

  if (sum & 0x2) //binary rep b010 - following the example will result in 0
    digitalWrite(LED1Pin, HIGH);
  else
    digitalWrite(LED1Pin, LOW);

  if (sum & 0x4) //binary rep b100 - following the example will result in 1
    digitalWrite(LED2Pin, HIGH);
  else
    digitalWrite(LED2Pin, LOW);

  delay(10);
}

答案 3 :(得分:1)

这取决于您是否负责模拟完整加法器或模拟完整加法器。如果您正在仿真一个,您可以使用这些引脚(至少对于大多数变体)分配给AVR端口的事实。

void loop() {
    int a = (PORTB >> 3) & 3; // take the two 'A' bits from the input port and make a number between 0 and 3
    int b = (PORTB >> 1) & 3; // likewise for 'B'
    PORTD = ( a + b ) << 4;   // add them together and shift to light the LEDs
}

如果我没有7482并希望效仿,那么我该怎么做。

如果目标是通过组合逻辑来演示如何创建完整加法器,那么使用半加法器逻辑sum = a xor bcarry = a and b以及全加法逻辑sum = ( a xor b ) xor c来创建它。 carry = ( a and b ) or ( c and ( a xor b ) )

void loop() {
    // input a as two separate bits
    bool a0 = digitalRead(A0Pin);
    bool a1 = digitalRead(A1Pin);

    // input b as two separate bits
    bool b0 = digitalRead(B0Pin);
    bool b1 = digitalRead(B1Pin);

    // half adder for digit 0 of output sum and carry
    bool s0 = a0 ^ b0;
    bool c0 = a0 & b0;

    // full adder for digit 1 of output sum and carry
    bool s1 = (a1 ^ b1) ^ c0;
    bool c1 = (a1 & b1) | (c0 & (a1 ^ b1));

    digitalWrite(LED0Pin, s0);
    digitalWrite(LED1Pin, s1);
    digitalWrite(LED2Pin, c1); // digit2 of output will be carry from digit 1
}

这里的不同之处在于它显示了工作,并告诉教师您已经理解了加法器的用途,而不仅仅是将真值表转换为一组if语句。对于两位加法器,您可能会使用它,但是您不想手动写出所有可能的输入和输出,例如,一个8位加法器。