【51单片机学习】(2)定时器扫描实现按键长按和短按

news/2024/10/18 14:23:42/

        用Delay消抖时会导致主程序中的一些进程受到影响,所以在这里借鉴江科大使用定时器扫描按键状态进行消抖的方法。在实际使用中加入了长按功能

按键驱动代码key.c

#include <REGX52.H>unsigned char Key_KeyNumber,KeyTime,KeyCount,i;
unsigned int times;/*** @brief  获取按键键码* @param  无* @retval 返回值Temp暂存按下按键的键码,范围:0-6共七位   其中键码值为0时表示无按键按下*/
unsigned char Key(void)
{unsigned char Temp=0;Temp=Key_KeyNumber;Key_KeyNumber=0;return Temp;
}/*** @brief  获取当前按键的状态,无消抖及松手检测* @param  无* @retval 返回值KeyNumber表示按下按键的键码,范围:0-6共七位   其中键码值为0时表示无按键按下*/
unsigned char MatrixKey_GetState()
{unsigned char KeyNumber=0;P3=0Xff;P3_4=0;			 if(P3_5==0){KeyNumber=6;}if(P3_6==0){KeyNumber=4;}if(P3_7==0){KeyNumber=5;}P3=0Xff;P3_3=0;if(P3_5==0){KeyNumber=3;}if(P3_6==0){KeyNumber=1;}if(P3_7==0){KeyNumber=2;}return KeyNumber;
}/*** @brief  按键驱动函数,在中断中调用* @param  无* @retval 无*/
void Key_Loop(void)
{static unsigned char NowState,LastState;LastState=NowState;				NowState=MatrixKey_GetState();   //更新键码值if(LastState==1 || LastState==2  || LastState==3  || LastState==4)  //1-4号键单击功能{if(NowState==0){Key_KeyNumber=LastState;		}}if(LastState==5 || LastState==6){i++;times++;if(NowState==0){KeyCount=i;i=0;if(LastState==5 && KeyCount<=50){Key_KeyNumber=5;KeyCount=0;}//短按时间小于1selse if(LastState==6 && KeyCount<=50){Key_KeyNumber=6;KeyCount=0;}//长按时间大于1sif(LastState==5 && KeyCount>=100){Key_KeyNumber=9;KeyCount=0;}//短按时间小于1selse if(LastState==6 && KeyCount>=100){Key_KeyNumber=10;KeyCount=0;}//长按时间大于1s}if(NowState){if(times>=50){KeyTime++; if(KeyTime>=10){if(LastState==5 && NowState==5){Key_KeyNumber=7;KeyTime=0;}//检测长按松手,防止长按后又判定到短按else if(LastState==6 && NowState==6){Key_KeyNumber=8;KeyTime=0;}		}}}else {times=0;}}
}//定时器中断函数
void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count++;if(T0Count>=20){T0Count=0;Key_Loop();//每隔20ms扫描一次}
}

定时器0初始化代码(20ms扫描一次按键状态)

#include <REGX52.H>/*** @brief  定时器0初始化,1毫秒@12.000MHz* @param  无* @retval 无*/
void Timer0Init(void)
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0=1;EA=1;PT0=0;
}

主函数main.c

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"unsigned char KeyNum;void main()
{Timer1Init();while(1){KeyNum=Key();		//获取独立按键键码if(KeyNum==1)	//如果K1按键按下{//执行相应动作}}
}


http://www.ppmy.cn/news/733521.html

相关文章

【32单片机学习】(7)STM32时钟周期

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1.理论时间 2.官方设计标准时间 3.时钟周期的应用 前言 在学习stm32的I2C部分时&#xff0c;发现和C51的有所不同&#xff0c;stm32在SCL翻转IO口后要一定的等…

【32单片机学习】(6)STM32串口+DMA收发不定长数据

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1.DMA介绍 2.串口接收数据 3.实验现象 1.实验电路图 2.串口收发不定长数据视频演示 3.OLED 显示接收数据 4.代码部分 1.1串口模块 serial.c serial.h …

【32单片机学习】(8)STM32滴答定时器

1.选择时钟源 在misc.c文件中&#xff0c;配置SysTick时钟源 void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); 可以选择系统时钟或者系统时钟的8分频&#xff1a; arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.…

【C语言学习】(1)冒泡法排序在ADC采样数据中的使用

复习冒泡排序&#xff0c;学习ADC采样数据滤波 目录 前言 一、使用场景 二、使用步骤 2.冒泡法排序 总结 前言 排序是C语言经常使用的基础算法&#xff0c;最简单的就是使用冒泡法对数组进行排序。 一、使用场景 在ADC采集到一次数据时&#xff0c;可能会因为干扰导致单…

【32单片机学习】(9)FSMC不同位宽操作

在学习正点原子FSMC访问外部存储器时遇到的一个地址偏移问题&#xff0c;在这里记录一下 HADDR&#xff1a;来自STM32内部AHB总线上地址线。 FSMC_A[25:0]&#xff1a;外部存储器接口信号上的地址总线&#xff0c;连接TFT的数据/命令选择RS端&#xff0c;只用到了FSMC_A[0]。 F…

【32单片机学习】(3)霍尔编码器减速直流电机控制及测速

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1.实验现象 2.实验接线及原理图 接线图 原理图 电机接线图 3.代码部分 1.主函数 main.c 2.按键部分 key.c key.h pwm代码 pwm.c pwm.h 电机驱动 motor.c mot…

【32单片机学习】(11)STM32启动过程详解

目录 前言 一、系统架构 二、启动配置 三、启动流程 1.首先复位MCU,获取栈顶指针MSP和PC指针的内容 2.根据PC的值找到复位中断处理函数Reset_Handler 1.进入中断处理函数Reset_Handler 2.进入SystemInit函数 3._main函数 3.进入main函数 总结 前言 通过查阅官方手册…

golangci-lint检查项说明

golangci-lint 说明 集成各项golang的静态检查工具英文原版说明地址内容涉及到编码风格&#xff08;style&#xff09;、错误处理&#xff08;error&#xff09;、会导致代码&#xff08;bugs&#xff09;、检查测试代码&#xff08;test&#xff09;、metalinter、sql相关判…