带 Arduino 的 2 位加法器

2-bit adder with an Arduino

所以我的任务是使用面包板、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 上制作的:

电路图:

01+01=010

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

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

引脚的标签很好: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 个未完成。

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

代码运行后,您可以 post 在 code review 上运行它,您将获得关于如何优化它的各种建议。

根据 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);
}

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

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

1) 涵盖没有输入为 HIGH 的情况(即您首先关闭所有 LED)。 1 例。

2) 涵盖恰好有 1 个输入为高电平的情况。 4 例。

3) 涵盖恰好有 2 个输入为高电平的情况。 6 例。

4) 涵盖恰好有 3 个输入为高电平的情况。 4 例。

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

该方法可行,因为第 5 步优先于第 4 步,第 4 步优先于第 3 步,依此类推。也就是说,即使您在例如中设置了不正确的输出第 4 步,它将被第 5 步纠正(如果所有输入均为高电平)。

So what is wrong with your code?

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

你这里也有错别字:

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

此外,您的代码绝不会像此处那样检查 LOW:

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

LOW 值由 if-statements 的优先级隐式处理。

总共你必须有初始化加15if-statements.

所以你的代码应该是:

  // 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;

这取决于您的任务是模拟全加器还是仿真全加器。如果你正在模拟一个,你可以使用这样一个事实,即引脚(至少对于大多数变体)分配给 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 并想模拟一个,我会这样做。

如果 objective 是为了演示如何通过组合逻辑创建全加器,则使用半加器逻辑 sum = a xor bcarry = a and b 以及 full-adder 逻辑 sum = ( a xor b ) xor ccarry = ( 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
}

这里的不同之处在于它展示了工作原理,并告诉讲师您已经了解加法器的用途,而不是仅仅将事实 table 转化为一组 if 语句。对于 two-bit 加法器,您可能会侥幸逃脱,但您不想手动写出所有可能的输入和输出,比如说,一个 8 位加法器。