库函数版独立按键用位运算方式实现(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:去抖动
    }  
}
相关推荐
Wave84510 小时前
基于 STM32 + ESP8266 + W25Q64 的双核 OTA 底层架构总结
stm32·嵌入式硬件·架构
xiangw@GZ11 小时前
WiFi 全世代(WiFi1~WiFi7)技术规范与核心参数总结
嵌入式硬件
振南的单片机世界11 小时前
CPU时钟:频率越高跑越快,但物理极限在“拖后腿”
stm32·单片机·嵌入式硬件
普中科技13 小时前
【普中 51-Ai8051 开发攻略】-- 第 20 章 输入捕获实验
单片机·嵌入式硬件·输入捕获·pca·普中科技·ai8051u·aicube
d111111111d13 小时前
直流电机位置式 PID 控制 和 舵机的区别
笔记·stm32·单片机·嵌入式硬件·学习
d111111111d15 小时前
了解Modbus
网络·笔记·stm32·单片机·嵌入式硬件·学习
三佛科技-1341638421215 小时前
主控FT32F031便携式吸尘器方案,迷你手持吸尘器MCU控制方案开发
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
一个平凡而乐于分享的小比特17 小时前
一文读懂MCU与FPGA:核心区别、协同之道与双修秘籍
单片机·fpga开发·职场发展·mcu开发
踏着七彩祥云的小丑17 小时前
嵌入式——认识电子元器件——微动开关系列
单片机·嵌入式硬件
调光IC-小雅17 小时前
解析FP62××系列限流保护机制:为何它是DC/DC芯片的安全底线
单片机·嵌入式硬件