Well I am programming a micro (ATmega328p) using C for a school project. The thing is I am trying to represent this truth table (A,B and C are just inputs, buttons to be more specific) and XOR is the output on a LED, there are other 3 LEDs but they are doing a different gate and right now they are working OK.
我正在为一个学校项目用C语言编程一个微型计算机(ATmega328p)。问题是,我试图代表这个真值表(A、B和C只是输入,更具体地说是按钮),XOR是LED上的输出,还有其他3个LED,但它们正在做不同的门,现在它们工作正常。
I am having problem with this specific part because the XOR is not working, it is supposed to be off when 2 buttons are pressed but is not. It just is only Off when all the buttons are not pressed:
我对这个特定的部件有问题,因为异或不工作,它应该是关闭的,当两个按钮被按下,但没有。只有当没有按下所有按钮时,它才会关闭:
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
}
I'll put the full code here just to reference.
我将把完整的代码放在这里以供参考。
#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));
}
Any ideas of what could be wrong? TY!! :D
有什么想法可能是错的吗?TY!!:D
I tried using this boolean expression y = A'B'C + A'BC' + AB'C' + ABC
我试着用这个布尔表达式y=A‘B’C+A‘BC’+AB‘C’+ABC
更多回答
Sure you want ||
and not |
?
您确定要||而不是|吗?
I tried and still the same :(
我试过了,还是一样的:
My straightforward understanding of xor caclulation is: XOR = A ^ B ^ C
. If so, the truth table (probably provided by a TA) looks incorrect in row 6 (1, 0, 1) and row 7 (1, 1, 0). Both should be 0, not 1.
我对XOR计算的直接理解是:XOR=A^B^C。如果是这样的话,真值表(可能由助教提供)在第6行(1,0,1)和第7行(1,1,0)中看起来不正确。两者都应为0,而不是1。
Welcome to StackOverflow! Please take the tour to learn how this site works, and read "How to Ask". Then come back and edit your question. -- Please do not post screenshots of text or tables. Add them as text or tables, the editor is able to help you. -- Your task is two-fold, finding the right equation, and implement it. Please extend your question showing the equation you want to implement, and perhaps some reasoning why you think it is correct. Then we can help you better.
欢迎来到StackOverflow!请参加导览,了解这个网站的工作原理,并阅读“如何提问”。然后回来编辑您的问题。--请不要发布文字或表格的截图。将它们添加为文本或表格,编辑器可以帮助您。--你的任务是双重的,找到正确的方程式,并实施它。请扩展你的问题,展示你想要实现的等式,也许还有一些你认为它是正确的推理。那么我们就能更好地帮助你。
Step 1 is to get the boolean logic done correct. Step 2 is to ponder how to write it in C. Step 3 is to adapt to some MCU hardware. You haven't done 1) and 2) so you can't do 3) either.
第一步是正确地完成布尔逻辑。第二步是思考如何用C语言编写;第三步是适配一些MCU硬件。你还没有做1)和2),所以你也不能做3)。
Your title talks about XOR of three variables which would just be
你的标题谈到了三个变量的XOR,这将是
EXOR = A ^ B ^ C;
However, your truth table:
然而,你的真实表:
is not a three variable XOR. For a three variable XOR the result in line 6 and 7 should be zero.
不是三变量XOR。对于三变量XOR,第6行和第7行的结果应该为零。
The truth table instead represents "B exclusive-or C or A", like:
取而代之的是真值表代表“B独占--或C或A”,例如:
EXOR = B ^ C | A;
Write some code to construct a truth table using your boolean expression and compare it to the table given in the assignment. Do they match? If not, think carefully about the truth table you were given and construct a boolean expression that will match. You can also search Google for something called a Karnaugh map, which can help you construct an expression from a truth table.
编写一些代码来使用布尔表达式构建真值表,并将其与作业中给出的表进行比较。它们相配吗?如果不是,请仔细考虑给出的真值表,并构造一个匹配的布尔表达式。你还可以在谷歌上搜索一种叫做卡诺图的东西,它可以帮助你从真值表中构造出一个表达式。
#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);
}
}
}
}
Note
注意事项
((BTS & _BV(BT1)) ^ (BTS & _BV(BT2))
Here XOR operation is a bitwise (not logical).
这里的XOR运算是按位的(非逻辑的)。
Since there is bitwise AND
in the both operands, each of them has all the bits reset, except for bit #BT1 at the left and #BT2 at the right.
因为在两个操作数中都有按位和,所以除了左侧的位#bt1和右侧的#bt2之外,每个操作数的所有位都被重置。
Bits #BT2 at the left and #BT1 at the right are zeros. That means, ^
here works exactly as bitwise OR, producing the result, where both bits are set, if they are set in both operands.
左边的位#bt2和右边的#bt1是零。这意味着,^在这里的工作方式与按位或完全相同,如果在两个操作数中都设置了这两个位,则会产生结果。
Probably you want to convert operands to some predefined values.
您可能希望将操作数转换为一些预定义的值。
E.g. you can use the ternary operator
你可以使用三元运算符
((((BTS & _BV(BT1)) ? 1 : 0) ^ (BTS & _BV(BT2)) ? 1 : 0))
(bts&_bv(Bt1)?1:0)^(bts&_bv(Bt2))?1:0))
Or you can achieve the same by simple comparison:
或者,您可以通过简单的比较来实现相同的效果:
((((BTS & _BV(BT1)) != 0) ^ ((BTS & _BV(BT2)) != 0))
(BTS&_BV(BT1))!=0)^((BTS&_BV(BT2))!=0)
Usually I ask beginners to use fewer variables in their code. In this case, using a trio of intermediate values compacts the code so that the reader can see what is going on.
通常,我会要求初学者在代码中使用较少的变量。在本例中,使用三个中间值来压缩代码,以便读者可以看到正在发生的事情。
That's an odd truth table for a 3-way XOR. The following might help you:
对于3向XOR来说,这是一个奇怪的真实表。以下内容可能会对您有所帮助:
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
}
It's a bad idea to use leading underscores even for macro identifiers. Use something different.
即使对宏标识符使用前导下划线也不是一个好主意。用一些不同的东西。
EDIT:
As mentioned above, that's an odd truth table you've presented in this question.
编辑:如上所述,这是你在这个问题中提出的一个奇怪的真理表。
Below goes one step further compacting the code to accentuate the logical operations you've used in your question. A couple of #define
macros instead of hieroglyphic code:
下面进一步压缩代码,以强调您在问题中使用的逻辑运算。有几个#定义宏,而不是象形码:
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);
}
EDIT 2:
In the acrimony raised by this question, the mislabelling of NAND as NOR has, until now, gone unremarked. Such is the distraction of too much code.
编辑2:在这个问题提出的尖锐批评中,到目前为止,NAND被错误地贴上NOR的标签并未被提及。这就是太多代码的干扰。
The following reduces the code such that readers can quickly satisfy themselves that all is in order. The issue of the odd truth table remains unresolved.
下面减少了代码,以便读者可以快速地确信一切都是正常的。奇数真值表的问题仍然没有得到解决。
// Two functions to set/reset a particular LED
void on( unsigned char led ) { LEDS |= _BV(led); }
void off( unsigned char led ) { LEDS &= ~_BV(led); }
// array of 2 where [0] invokes off() and [1] invokes on()
void (*set)[](unsigned char) = { off, on };
while(1) {
// ensure unknown bitmask results in either 0 or 1
bool btn1 = !!(BTS & _BV(BT1));
bool btn2 = !!(BTS & _BV(BT2));
bool btn3 = !!(BTS & _BV(BT3));
set[ btn1 & btn2 & btn3 ](LED0); // AND
set[ btn1 | btn2 | btn3 ](LED1); // OR
#ifdef ODD_EXOR_TRUTH_TABLE
set[ btn1 | btn2 ^ btn3 ](LED2); //EXOR (from OP)
#else
set[ btn1 ^ btn2 ^ btn3 ](LED2); //XOR (conventional)
#endif
set[ !( btn1 & btn2 & btn3 ) ](LED3); // NAND (not NOR)
set[ !( btn1 | btn2 | btn3 ) ](LED4); // NOR (LED #4 !!)
}
As Support Ukraine wrote, the truth table is for
正如支持乌克兰所写的那样,真相表是为了
EXOR = (B ^ C) | A;
Anyway, let A, B, and C are bits 2, 1 and 0 of input value (0000_0ABC)
无论如何,设A、B和C是输入值(0000_0ABC)的第2、1和0位。
out = (0xF6 >> (input & 0x03)) & 0x01;
Where 0xF6 is the bitmask of your EXOR column (the top line is bit 0 and the bottom one is bit 7).
其中0xF6是EXOR列的位掩码(顶行是位0,底行是位7)。
更多回答
I'm not sure what you are trying here. It's not a 3 variable XOR. It's not producing a result like OPs truth table. So what is it you are trying to show?
我不知道你在这里想要做什么。这不是一个三变量的异或运算。它不会产生像奥普斯真理表那样的结果。那么,你想展示的是什么呢?
Why ||
and &&
? This is bitwise arithmetic, not logic.
为什么||和&&?这是按位运算,而不是逻辑。
@user207421 One step at a time...
@user207421一步一个脚印...
"//EXOR (As given by the OP)" There are no special EXOR. XOR and the seldom used EXOR are just the same.
“//EXOR(由OP给出)”没有特殊的EXOR。XOR和很少使用的EXOR是一样的。
@SupportUkraine A recent question referred to an MSB as "the last bit" in their title, and "the first bit" in their description... You can vote to close if you feel the question lacks details or clarity.
@Support乌克兰最近的一个问题将MSB称为标题中的最后一位,以及描述中的第一位……如果你觉得问题缺乏细节或清晰度,你可以投票结束。
我是一名优秀的程序员,十分优秀!