4x4 薄膜键盘发出意想不到的信号
4x4 membrane keypad giving unexpected signals
我正在做一个项目,尝试为薄膜键盘编写自己的功能。我希望将 16 个关键状态存储在一个 uint16_t
变量中,因此我只有一个变量。代码编译。
问题是它无法正确显示按键状态。当我按下 1 键时,它会告诉我还有很多键被按下。它还会显示正在按下按键,而根本没有触摸任何东西。
小键盘的引脚 5-8 连接到 PORTD,Nano 上的引脚 4-7。
键盘的引脚 1-4 连接到 PORTB,Nano 上的引脚 0-3。
这是代码。
uint16_t keys = 0;
void setup() {
// put your setup code here, to run once:
DDRD |= 0xF0; //Set bit 4-7 as output on PORTD
DDRB &= 0xF0; //Set bit 0-3 as input on PORTB
Serial.begin(9600);
}
void loop() {
getKeys(&keys);
Serial.println("-----------------------");
delay(100);
}
void getKeys(uint16_t* keys){
*keys = 0; //Clear keys variable
for(int rows = 0; rows < 4; rows++){ //Loop through every row
PORTD &= 0x0F; //Turn pin 4-7 on PORTD off
PORTD |= (16 << rows); //Turn on pin.
Serial.print(String(PORTD) + String(" : ")); //Print current selected bit(row)
uint16_t temp = (PINB & 0x000F); //Take bit 0-3 from PORTB
Serial.println(temp, BIN); //Print the PINB values as binary
*keys |= (temp << (rows*4)); //Shift the PORTB values into keys.
}
}
这是串行监视器中的输出。
16 : 0
32 : 0
64 : 0
128 : 0
-----------------------
16 : 0
32 : 0
64 : 0
128 : 1
-----------------------
16 : 0
32 : 0
64 : 0
128 : 11
-----------------------
16 : 0
32 : 1000
64 : 10
128 : 1111
-----------------------
16 : 1000
32 : 1110
64 : 1110
128 : 1111
-----------------------
16 : 1000
32 : 1110
64 : 1110
128 : 1111
-----------------------
16 : 0
32 : 0
64 : 0
128 : 0
-----------------------
16 : 0
32 : 0
64 : 0
128 : 0
-----------------------
当您按下所有键时,您的输入就没有连接到任何东西。它们只是 "floating in the air" 并且可以接收来自外部的任何电气干扰。
键盘应该以其他方式工作。
在输入引脚 (PINB) 上打开上拉电阻 DDRB &= 0xF0; PORTB |= 0x0F
。那么您现在输入的所有内容都应读作逻辑 1,例如。 1111
.
在输出引脚 (PORTD) 上为所有行提供高电平(逻辑 1),除了要测量的行(这应该是低电平 - 逻辑 0),例如1110, 1101, 1011, 0111
.
然后您可以在输入引脚 (PINB) 上将按下的键读取为逻辑 0。之后,如果需要,您可以反转读取的数字(按位非运算符 ~
),例如temp = PINB; temp ~= temp; temp &= 0x0F
或 temp = (~PINB) & 0x0F
.
同样的方法你可以在输出前使用按位非运算符,例如PORTD = (~(16 << rows)) & 0x0F
.
这样,当您在 PORTD 的输出引脚上设置逻辑 0 时,您在 PINB 上的输入将始终连接到某个源 - 通过 AVR 芯片内的上拉电阻连接到 VCC (+5V),或者连接到 GND。而且您不会在它们上收到任何电噪声。
我正在做一个项目,尝试为薄膜键盘编写自己的功能。我希望将 16 个关键状态存储在一个 uint16_t
变量中,因此我只有一个变量。代码编译。
问题是它无法正确显示按键状态。当我按下 1 键时,它会告诉我还有很多键被按下。它还会显示正在按下按键,而根本没有触摸任何东西。
小键盘的引脚 5-8 连接到 PORTD,Nano 上的引脚 4-7。 键盘的引脚 1-4 连接到 PORTB,Nano 上的引脚 0-3。
这是代码。
uint16_t keys = 0;
void setup() {
// put your setup code here, to run once:
DDRD |= 0xF0; //Set bit 4-7 as output on PORTD
DDRB &= 0xF0; //Set bit 0-3 as input on PORTB
Serial.begin(9600);
}
void loop() {
getKeys(&keys);
Serial.println("-----------------------");
delay(100);
}
void getKeys(uint16_t* keys){
*keys = 0; //Clear keys variable
for(int rows = 0; rows < 4; rows++){ //Loop through every row
PORTD &= 0x0F; //Turn pin 4-7 on PORTD off
PORTD |= (16 << rows); //Turn on pin.
Serial.print(String(PORTD) + String(" : ")); //Print current selected bit(row)
uint16_t temp = (PINB & 0x000F); //Take bit 0-3 from PORTB
Serial.println(temp, BIN); //Print the PINB values as binary
*keys |= (temp << (rows*4)); //Shift the PORTB values into keys.
}
}
这是串行监视器中的输出。
16 : 0
32 : 0
64 : 0
128 : 0
-----------------------
16 : 0
32 : 0
64 : 0
128 : 1
-----------------------
16 : 0
32 : 0
64 : 0
128 : 11
-----------------------
16 : 0
32 : 1000
64 : 10
128 : 1111
-----------------------
16 : 1000
32 : 1110
64 : 1110
128 : 1111
-----------------------
16 : 1000
32 : 1110
64 : 1110
128 : 1111
-----------------------
16 : 0
32 : 0
64 : 0
128 : 0
-----------------------
16 : 0
32 : 0
64 : 0
128 : 0
-----------------------
当您按下所有键时,您的输入就没有连接到任何东西。它们只是 "floating in the air" 并且可以接收来自外部的任何电气干扰。
键盘应该以其他方式工作。
在输入引脚 (PINB) 上打开上拉电阻
DDRB &= 0xF0; PORTB |= 0x0F
。那么您现在输入的所有内容都应读作逻辑 1,例如。1111
.在输出引脚 (PORTD) 上为所有行提供高电平(逻辑 1),除了要测量的行(这应该是低电平 - 逻辑 0),例如
1110, 1101, 1011, 0111
.然后您可以在输入引脚 (PINB) 上将按下的键读取为逻辑 0。之后,如果需要,您可以反转读取的数字(按位非运算符
~
),例如temp = PINB; temp ~= temp; temp &= 0x0F
或temp = (~PINB) & 0x0F
.
同样的方法你可以在输出前使用按位非运算符,例如PORTD = (~(16 << rows)) & 0x0F
.
这样,当您在 PORTD 的输出引脚上设置逻辑 0 时,您在 PINB 上的输入将始终连接到某个源 - 通过 AVR 芯片内的上拉电阻连接到 VCC (+5V),或者连接到 GND。而且您不会在它们上收到任何电噪声。