库函数版独立按键用位运算方式实现(STC8)

位运算:更加简便,单片机的内存就小,占的内存空间小一点

案例:

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:去抖动
    }  
}
相关推荐
眰恦ゞLYF29 分钟前
嵌入式硬件——IMX6ULL时钟配置
单片机·嵌入式硬件·时钟·imx6ull
小莞尔1 小时前
【51单片机】【protues仿真】基于51单片机秒表系统(LCD1602多功能、可保持30条记录)
c语言·stm32·单片机·嵌入式硬件·51单片机
Tolines2 小时前
PCIe外接卡标准尺寸
嵌入式硬件·硬件工程·设计规范
寅双木2 小时前
常见的九种二极管
笔记·嵌入式硬件·稳压二极管·tvs·肖特基二极管·发光二极管·齐纳击穿
Black doncky prince2 小时前
QR反激电源副边整流二极管电压波形分析
单片机·嵌入式硬件·硬件工程
currycheng62 小时前
开关电源测试及方法
单片机·嵌入式硬件·硬件架构·硬件工程
SundayBear3 小时前
基于MCU的文件系统
linux·服务器·单片机
DIY机器人工房9 小时前
关于解决 libwebsockets 库编译时遇到的问题的方法:
服务器·stm32·单片机·嵌入式硬件·tcp
GilgameshJSS10 小时前
STM32H743-ARM例程3-SYSTICK定时闪烁LED
arm开发·stm32·单片机·嵌入式硬件·学习
云山工作室11 小时前
基于单片机的按摩椅系统的设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设