c
复制代码
#include "GPIO.h"
#include "Delay.h"
#include "UART.h" // 串口配置 UART_Configuration
#include "NVIC.h" // 中断初始化NVIC_UART1_Init
#include "Switch.h" // 引脚切换 UART1_SW_P30_P31
// 宏定义按键
#define KEY1 P51
#define KEY2 P52
#define KEY3 P53
#define KEY4 P54
// 按下抬起状态宏
#define DOWN 0
#define UP 1
/*
位运算:节省内存 抬起是1 按下是0
u8 last_state = 0x0f; // 0b0000 1111
0x0f
b3 b2 b1 b0 第几位
0b0000 1 1 1 1
k4 k3 k2 k1 标志第几个按键
如何知道第1个按键是按下还是抬起,取出第0位
如果第0位是1,那么第1个按键是抬起
如果第0位是0,那么第1个按键是按下
如何设置第1个按键为按下或抬起,给第0位置0或置1
设置第1个按键为抬起, 给第0位置1
设置第1个按键为按下, 给第0位置0
*/
// 位运算:节省内存 抬起是1 按下是0
u8 last_state = 0x0f; // 0b0000 111
// 宏定义的函数
#define IS_KEY_UP(i) ((last_state >> i & 1) == 1)
#define IS_KEY_DOWN(i) ((last_state >> i & 1) == 0)
#define SET_KEY_UP(i) (last_state |= (1 << i))
#define SET_KEY_DOWN(i) (last_state &= ~(1 << i))
void GPIO_config() {
GPIO_InitTypeDef info;
// ===== UART1 P30 P31 准双向
info.Mode = GPIO_PullUp; // 准双向
info.Pin = GPIO_Pin_0 | GPIO_Pin_1; // 引脚
GPIO_Inilize(GPIO_P3, &info);
//准双向口 P51 P52 P53 P54
P5_MODE_IO_PU(GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4);
}
// 串口配置函数的定义
void UART_config(void) {
// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
COMx_InitDefine COMx_InitStructure; //结构定义
COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
COMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200
COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLE
COMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLE
UART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4
NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
UART1_SW(UART1_SW_P30_P31); // 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}
void main() {
EA = 1; // 使能中断总开关
GPIO_config(); // GPIO配置
UART_config(); // 串口配置
while (1){
// =================KEY1===============
// 上一次和当前不同,才能进入条件
if (IS_KEY_UP(0) && KEY1 == DOWN) { // 上一次是抬起,当前是按下,按下才有效
SET_KEY_DOWN(0); // 上一次状态需要更新
printf("key1按下\n");
} else if (IS_KEY_DOWN(0) && KEY1 == UP) { // 上一次是按下,当前是抬起,抬起才有效
SET_KEY_UP(0); // 上一次状态需要更新
printf("key1抬起\n");
}
// =================KEY2===============
// 上一次和当前不同,才能进入条件
if (IS_KEY_UP(1) && KEY2 == DOWN) { // 上一次是抬起,当前是按下,按下才有效
SET_KEY_DOWN(1); // 上一次状态需要更新
printf("key2按下\n");
} else if (IS_KEY_DOWN(1) && KEY2 == UP) { // 上一次是按下,当前是抬起,抬起才有效
SET_KEY_UP(1); // 上一次状态需要更新
printf("key2抬起\n");
}
// =================KEY3===============
// 上一次和当前不同,才能进入条件
if (IS_KEY_UP(2) && KEY3 == DOWN) { // 上一次是抬起,当前是按下,按下才有效
SET_KEY_DOWN(2); // 上一次状态需要更新
printf("key3按下\n");
} else if (IS_KEY_DOWN(2) && KEY3 == UP) { // 上一次是按下,当前是抬起,抬起才有效
SET_KEY_UP(2); // 上一次状态需要更新
printf("key3抬起\n");
}
// =================KEY4===============
// 上一次和当前不同,才能进入条件
if (IS_KEY_UP(3) && KEY4 == DOWN) { // 上一次是抬起,当前是按下,按下才有效
SET_KEY_DOWN(3); // 上一次状态需要更新
printf("key4按下\n");
} else if (IS_KEY_DOWN(3) && KEY4 == UP) { // 上一次是按下,当前是抬起,抬起才有效
SET_KEY_UP(3); // 上一次状态需要更新
printf("key4抬起\n");
}
delay_ms(50); // 适当的延时,很有必要的,作用1:去抖动
}
}