我试图实现一些逻辑功能,以控制一个小型电力系统,包括两个标有T1和T2的变压器、两个发电机(G1和G2)和一个总线绑定(BT)。我不会用不必要的细节压倒你。我需要帮助找出为什么我的Arduino电路不能像预期的那样工作,即使代码编译正确!我花了太多时间在上面,但我还是搞不懂。我会附加电路,然后是注释的Arduino代码。
LEDS应该被一些继电器线圈所取代(一种用来控制电气设备开关的装置)。
以下是Arduino代码:
byte lastReading;
unsigned long lastReadingTimer;
byte UpdatedPortD;
void setup() {
lastReadingTimer = 0; //Debouncing Timer is 0 ms initially.
// Initialize ports to I/O directions:
DDRD = DDRD & B10000011; // Masking to perserve bits 0,1 and 7. (zeros for input)
DDRB = DDRB | 31; // Masking to perserve bits 6,7. PortB(8-13 pins) 0001 1111 (one=outputs).
PORTD &= B10000011; //Initially all inputs are LOWs.
lastReading = PORTD & B01111100;
UpdatedPortD = PORTD & B01111100; // Inputs to PortD, 3-7 pins.
}
//Pins from 3-7 map to switches T1,T2,G1,G2,BT respectively.
//Pins from 8-12 map to devices T1,T2,G1,G2,BT respectively.
void loop() {
if ((PORTD & B01111100) != lastReading) {
lastReadingTimer = millis();
}
if ( ((millis() - lastReadingTimer) > 50) && (UpdatedPortD != PORTD & B01111100) ) {
UpdatedPortD = PORTD & B01111100;
}
// For T1= G1`.(G2`+BT`) (Simplified LOGIC EQUATION from Truth Table)
if ( (~UpdatedPortD & (1 << 4)) && ((~UpdatedPortD & (1 << 5)) || (~UpdatedPortD & (1 << 6))) ) {
PORTB |= 1;
}
else if (PORTB & 1) { // if not reset the pin.
PORTB ^= 1;
}
// For T2= G2`.(G1`+BT`)
if ( (~UpdatedPortD & (1 << 5)) && ((~UpdatedPortD & (1 << 4)) || (~UpdatedPortD & (1 << 6))) ) {
PORTB |= 1 << 1;
}
else if (PORTB & 1 << 1) {
PORTB ^= 1 << 1;
}
// For G1= T1`.(G2`.T2` + BT`)
if ( (~UpdatedPortD & (1 << 2)) && ((~UpdatedPortD & (1 << 5)) && (~UpdatedPortD & (1 << 3)) || (~UpdatedPortD & (1 << 6))) ) {
PORTB |= 1 << 2;
}
else if (PORTB & 1 << 2) {
PORTB ^= 1 << 2;
}
// For G2= T2`.(G1`.T1` + BT`)
if ( (~UpdatedPortD & (1 << 3)) && ((~UpdatedPortD & (1 << 4)) && (~UpdatedPortD & (1 << 2)) || (~UpdatedPortD & (1 << 6))) ) {
PORTB |= 1 << 3;
}
else if (PORTB & 1 << 3) {
PORTB ^= 1 << 3;
}
// For BT= G1`.G2`+ T1`.T2`.(G1`+G2`)
if ( ((~UpdatedPortD & (1 << 4)) && (~UpdatedPortD & (1 << 5))) || (((~UpdatedPortD & (1 << 2)) && (~UpdatedPortD & (1 << 3))) && (~UpdatedPortD & (1 << 4) || ~UpdatedPortD & (1 << 5)))) {
PORTB |= 1 << 4;
}
else if (PORTB & 1 << 4) {
PORTB ^= 1 << 4;
}
lastReading = PORTD & B01111100;
}
非常感谢!
发布于 2019-12-13 11:33:15
byte
这样奇怪的自定义类型。始终使用stdint.h
中的类型。static
以缩小范围。0b
,因为它们是非标准的和不可移植的.此外,它们很难读懂。假定程序员能够读懂十六进制。31
这样的十进制数字来掩盖,这就更让人困惑了。0x1F
要清楚得多。DDRD = DDRD & B10000011;
这样的代码,您应该有类似于DDRD = DDRD0 | DDRD1 | DDRD7
的东西。这现在是自记录代码,因此注释“掩蔽0,1和7位”不再是必要的。void loop()
应该重写为: uint8_t portb = PORTB;uint8_t portd = PORTD;/* all if语句和算术使用上述2个RAM变量*/ uint8_t= portb;//写入端口一次,当完成时if ( ((~UpdatedPortD & (1 << 4)) && (~UpdatedPortD & (1 << 5))) || (((~UpdatedPortD & (1 << 2)) && (~UpdatedPortD & (1 << 3))) && (~UpdatedPortD & (1 << 4) || ~UpdatedPortD & (1 << 5))))
这样的表达式需要在几行中分成几个表达式。重要的是要认识到这样做不会导致更慢的代码。此外,您也可以使用有意义的变量名,而不是让程序使用“神奇端口号”。只是一个带有随机名称的例子,因为我不知道您的实际按钮在做什么: bool button_up = ~UpdatedPortD & (1u<<2);bool button_down = ~UpdatedPortD & (1u<<3);bool button_left = ~UpdatedPortD & (1u<<4);bool button_right = ~UpdatedPortD & (1u<<5);if(button_up && button_left) { /* do buttons */ }~UpdatedPortD
为您提供了一个16位签名的int
,其值为0xFF**
(负值),这不是您想要的。1 << 4;
在16位签名的int
上执行位移位。诸若此类。不要对有符号类型使用按位操作!要解决这个问题,总是将提升的表达式转换回预期的类型,并在重要的地方始终使用u
后缀整数常量。1 << 4
应该是1u << 4
。总的来说,传统的8位MCU很难编程,隐性促销是其中一个原因。我强烈建议初学者使用32位手臂代替,因为他们是更直截了当。https://codereview.stackexchange.com/questions/233961
复制相似问题