#学习
首先介绍一下按位与是:
按位与运算是一种二进制运算,它用来对两个二进制数的每个对应位进行逻辑与操作。按位与运算的规则如下:
对于每一个位的操作:
- 如果两个对应的位都是1,则结果位为1。
- 如果其中一个或两个对应的位是0,则结果位为0。
下面是按位与运算的示例:
```
10101011 (173 in decimal)
& 11001100 (204 in decimal)
-----------
10001000 (136 in decimal)
```
在上面的例子中,我们对二进制数10101011和11001100进行按位与运算。对于每个位的操作如下:
- 第1位:1 & 1 = 1
- 第2位:0 & 1 = 0
- 第3位:1 & 0 = 0
- 第4位:0 & 0 = 0
- 第5位:1 & 1 = 1
- 第6位:0 & 1 = 0
- 第7位:1 & 0 = 0
- 第8位:1 & 0 = 0
结果为10001000,对应的十进制数是136。
在实际编程中,按位与运算通常用于对某些位进行屏蔽或提取操作。例如,通过与一个掩码进行按位与运算,可以将某些位设置为0,保留其他位不变。
#define SHORT_PRESS_THRESHOLD 200 // Short press
#define LONG_PRESS_THRESHOLD 1000 // Long press
uint8_t Key_Scan(void)
{
static uint8_t previousState[4] = {1, 1, 1, 1}; // Record the previous key states, defaulting to not pressed
static uint32_t lastScanTime = 0; // Last key scan time
uint8_t currentState[4]; // Current key states
// Get the current time
uint32_t currentTime = HAL_GetTick();
// Check if it meets the cooldown time (assuming the cooldown time is 200ms)
if (currentTime - lastScanTime < 200)
{
return 0; // If still within the cooldown time, return 0, indicating no key press
}
currentState[0] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
currentState[1] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
currentState[2] = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);
currentState[3] = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
// Detect key state changes and return the corresponding key number
for (uint8_t i = 0; i < 4; i++)
{
if (currentState[i] == 0 && previousState[i] == 1) // When the key changes from not pressed to pressed
{
previousState[i] = currentState[i]; // Update the previous key state
lastScanTime = currentTime; // Record the current time
return i + 1; // 返回密钥编号(从 1 开始)
}
else if (currentState[i] == 0 && previousState[i] == 0) // When the key is being held down
{
if (currentTime - lastScanTime >= LONG_PRESS_THRESHOLD) // Long press detected
{
lastScanTime = currentTime; // Update the last scan time to avoid triggering multiple times
return (i + 1) | 0x80; // 返回键号,MSB 设置为 1 表示长按
}
}
else // When the key is released or not pressed
{
previousState[i] = currentState[i]; // Update the previous key state
}
}
return 0; // No key press detected, return 0
}
长按短按检测:
在这个例子中,`flag & 0x80` 的结果是 `10000000`,也就是 `0x80`。这是因为只有最高位为1的位在两个数中同时为1,其它位都为0。
在 C/C++ 中,非零值被视为真,而零被视为假。因此,当 `flag & 0x80` 的结果为非零值时,条件为真,意味着最高位为1,表示长按。当结果为零时,条件为假,表示不是长按。这样就可以通过 `if (flag & 0x80)` 来判断是否为长按。