我在尝试使用 3 个变量进行 XOR 时遇到问题

问题描述 投票:0回答:4

我正在为一个学校项目使用 C 语言编写一个微型(ATmega328p)程序。问题是我试图表示这个真值表(A、B 和 C 只是输入,更具体地说是按钮),XOR 是 LED 上的输出,还有其他 3 个 LED,但它们正在执行不同的门和正确的操作现在他们工作正常。

Truth table

我在这个特定部分遇到问题,因为 XOR 不起作用,当按下 2 个按钮时它应该关闭,但事实并非如此。仅当未按下所有按钮时才会关闭:

        if ( ((BTS & _BV(BT1)) ^ (BTS & _BV(BT2))) || ((BTS & _BV(BT2)) ^ (BTS & _BV(BT3)))) //EXOR
        {
            LEDS |= _BV(LED2); //Set 1 on LED2
        }
        else
        {
            LEDS &= ~_BV(LED2); //Set 0 on LED2
        }

我将完整的代码放在这里仅供参考。

#include <avr/io.h>
#define F_CPU 16000000UL 
#include <util/delay.h>

#define delay 500

//--Tags
//-Inputs
#define BTS PINB
#define BT1 PINB0
#define BT2 PINB1
#define BT3 PINB2

//-Outputs
#define LEDS PORTD
#define LED0 PORTD2
#define LED1 PORTD3
#define LED2 PORTD4
#define LED3 PORTD5

void init_ports(void);

int main(void)
{
    init_ports();
    
    while (1) 
    {
        //Output 1
        if ((BTS & _BV(BT1)) && (BTS & _BV(BT2)) && (BTS & _BV(BT3))) // AND 
        {
            LEDS |= _BV(LED0); //Set 1 on LED0
        }
        else
        {
            LEDS &= ~ _BV(LED0); //Set 0 on LED0
        }
        
        //Output 2
        if ((BTS & _BV(BT1)) || (BTS & _BV(BT2)) || (BTS & _BV(BT3))) // OR 
        {
            LEDS |= _BV(LED1); //Set 1 on LED1
        }
        else
        {
            LEDS &= ~ _BV(LED1); //Set 0 on LED1
        }
        
        //Output 3
        
        if ( ((BTS & _BV(BT1)) ^ (BTS & _BV(BT2))) || ((BTS & _BV(BT2)) ^ (BTS & _BV(BT3)))) //EXOR
        {
            LEDS |= _BV(LED2); //Set 1 on LED2
        }
        else
        {
            LEDS &= ~_BV(LED2); //Set 0 on LED2
        }
        
        //Output 4
        
        if (!((BTS & _BV(BT1)) && (BTS & _BV(BT2)) && (BTS & _BV(BT3)))) // NOR 
        {
            LEDS |= _BV(LED3); //Set 1 on LED3
        }
        else
        {
            LEDS &= ~_BV(LED3); //Set 0 on LED3
        }
    }
}

void init_ports (void)
{
    //--Inputs
    DDRB  &= ~(_BV(BT1) | _BV(BT2) | _BV(BT3));
    //-PULL-UP 
    PORTB &= ~(_BV(BT1) | _BV(BT2) | _BV(BT3));
    //--Outputs
    DDRD  |=  (_BV(LED0) | _BV(LED1) | _BV(LED2) | _BV(LED3));
    //-Off
    PORTD &= ~(_BV(LED0) | _BV(LED1) | _BV(LED2) | _BV(LED3));
}

有什么可能出问题的想法吗?泰! :D

我尝试使用这个布尔表达式 y = A'B'C + A'BC' + AB'C' + ABC

c avr atmega microchip atmelstudio
4个回答
1
投票

编写一些代码,使用布尔表达式构建真值表,并将其与作业中给出的表进行比较。他们匹配吗?如果没有,请仔细考虑给定的真值表并构造一个匹配的布尔表达式。您还可以在 Google 中搜索一种称为卡诺图的东西,它可以帮助您从真值表构建表达式。

#include <stdio.h>

int main()
{
   printf(" A   B   C   EXOR\n");
   printf("------------------\n");

   for (int a = 0; a <=1; a++) {
      for (int b = 0; b <=1; b++) {
         for (int c = 0; c <=1; c++) {
            int exor = (a ^ b) || (b ^ c);
            printf(" %i   %i   %i   %i\n", a, b, c, exor);
         }
      }
   }
}

1
投票

你的标题任务是关于三个变量的异或,这就是

EXOR = A ^ B ^ C;

但是,你的真值表:

不是三变量异或。对于三变量 XOR,第 6 行和第 7 行的结果应为零。

真值表代表“B异或C或A”,例如:

EXOR = B ^ C | A;

1
投票

注意

((BTS & _BV(BT1)) ^ (BTS & _BV(BT2))

这里XOR运算是按位(非逻辑)运算。

由于两个操作数中都有

bitwise AND
,因此除了左侧的位 #BT1 和右侧的位 #BT2 之外,每个操作数的所有位均已重置。

左侧的#BT2 位和右侧的#BT1 位为零。这意味着,这里的

^
与按位 OR 完全相同,产生结果,其中两个位都被设置(如果在两个操作数中都设置了这两个位)。

您可能想将操作数转换为某些预定义值。

例如您可以使用三元运算符

((((BTS & _BV(BT1)) ? 1 : 0) ^ (BTS & _BV(BT2)) ? 1 : 0))

或者通过简单的比较也可以达到同样的效果:

((((BTS & _BV(BT1)) != 0) ^ ((BTS & _BV(BT2)) != 0))


-1
投票

通常我会要求初学者在代码中使用“更少”的变量。在这种情况下,使用三个中间值压缩代码,以便读者可以看到发生了什么。 对于三向异或来说,这是一个奇怪的真值表。以下内容可能对您有帮助:

while (1) { bool btn1 = BTS & _BV(BT1); bool btn2 = BTS & _BV(BT2); bool btn3 = BTS & _BV(BT3); // AND if ( btn1 && btn2 && btn3 ) LEDS |= _BV(LED0); //Set 1 on LED0 else LEDS &= ~_BV(LED0); //Set 0 on LED0 // OR if( btn1 || btn2 || btn3 ) LEDS |= _BV(LED1); //Set 1 on LED1 else LEDS &= ~_BV(LED1); //Set 0 on LED1 //EXOR // if( btn1 ^ btn2 || btn2 ^ btn3 ) /* wrong! */ if( btn1 || btn2 ^ btn3 ) LEDS |= _BV(LED2); //Set 1 on LED2 else LEDS &= ~_BV(LED2); //Set 0 on LED2 // NOR if( !( btn1 && btn2 && btn3 ) ) LEDS |= _BV(LED3); //Set 1 on LED3 else LEDS &= ~_BV(LED3); //Set 0 on LED3 }

即使对于宏标识符,使用前导下划线也是一个坏主意。使用不同的东西。

编辑:

如上所述,您在这个问题中提出了一个奇怪的真值表。
下面进一步压缩代码,以强调您在问题中使用的逻辑运算。几个

#define

宏而不是象形文字代码:

    while (1)
    {
        bool btn1 = BTS & _BV(BT1);
        bool btn2 = BTS & _BV(BT2);
        bool btn3 = BTS & _BV(BT3);

#       define  ON(led) ( (LEDS) |= (_BV(led)) )
#       define OFF(led) ( (LEDS) &= ~(_BV(led)) )

// AND
        if ( btn1 && btn2 && btn3 )
            ON(LED0);
        else
            OFF(LED0);

// OR
        if( btn1 || btn2 || btn3 ) 
            ON(LED1);
        else
            OFF(LED1);

//EXOR (As given by the OP)
//      if( btn1 ^ btn2 || btn2 ^ btn3 ) /* wrong! */
        if( btn1 || btn2 ^ btn3 )
            ON(LED2);
        else
            OFF(LED2);

//XOR (Added to appease others)
        if( btn1 ^ btn2 ^ btn3 )
            ON(LED2);
        else
            OFF(LED2);

// NOR
        if( !( btn1 && btn2 && btn3 ) ) 
            ON(LED3);
        else
            OFF(LED3);
    }

© www.soinside.com 2019 - 2024. All rights reserved.