单片机源程序如下:
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit P_LED=P1^1;
sbit P_KEY=P2^0;
///////////////////////////////
bit F_4MS=0;
bit f_key_press=0; //按下弹起标志位:0 弹起 1 按下
bit f_key_ctrl=0; //长按标志位
bit F_WORK_ON=0; //开关机标志位:1开机 0关机
/////////////////////////////////
unchar press_cnt=0;
unint ctrl_cnt=0;
unchar show_time=0;
void Timer0Init() //定时器0初始化
{
TMOD |= 0x01; //模式1
TMOD &= 0x0F;
TH0 = (65536-1000)/256;
TL0 = (65536-1000)%256; //定时1ms
EA=1;
ET0=1;
TR0=1; //T0中断溢出请求标志位
///////这个作为主程序的定时,所有的定时都是在这上面进行计算
}
void main(void)
{
POWER_INIT(); //单片机初始化:配置IO口输出输出属性,这个你没有配置,输入的情况是否要开上拉,这个你也没有配置.
//IO口为输出时,该IO口的初始化电平是高还是低,如果共阴的IO口初始化电平给低,如果共阳的就给高,
//你这原理图上是共阳的,所以初始化IO口需要给高电平,防止没有开机的情况下就亮了, 因为你没有配置IO
//口的电平一般初始化模式是配置给底电平.
Timer0Init(); //T0初始化
while(1) //一直检测按键是否按下 ?按下则进入中断
{
if(F_1MS)
{
F_1MS=0;
//清看门狗 //你自己找下清理看门狗的代码是什么
KEY_SCAN(); //按键扫描
LED_DISPLAY(); //灯显示
}
}
}
/*按键扫描子函数模块,记得给IO口设置为输入,并且开内部上拉*/
void KEY_SCAN(void)
{
if(!f_key_press) //检测按下
{
if(P_KEY){press_cnt=0;} //按键检测到有高电平就清零计数
press_cnt++; //按键变量++
if(press_cnt>=40) //累加到40次,也就是消抖完成了
{
press_cnt=0; //清零计数变量
f_key_press=1; //把这个标志位置1,表示已经按下了
f_key_ctrl=1; //长按标志位置1,
}
}
else
{
if(!P_KEY){press_cnt=0;} //检测弹起
press_cnt++;
if(press_cnt>=40)
{
press_cnt=0;
f_key_press=0;
if(F_WORK_ON&&f_key_ctrl) //开机短按后可以增加功能
{
//功能自己添加
}
f_key_ctrl=0; //这个标志位不能漏,因为短按的时候这个标志位容易漏掉
}
}
//////////////////////
if(f_key_ctrl) //检测长按
{
ctrl_cnt++;
if(ctrl_cnt>=3000) //加到3000次 ,也就是3S
{
ctrl_cnt=0; //清零累加计数
f_key_ctrl=0; //清标志位
F_WORK_ON=!F_WORK_ON; //开机或者关机
}
}
else //这个标志位为0的时候清零累加计数
{
ctrl_cnt=0;
}
}
void LED_DISPLAY(void)
{
if(F_WORK_ON)
{
P_LED=0;
}
else
{
P_LED=1;
}
}
void Timer0() interrupt 1 //中断函数
{
TH0 = (65536-1000)/256;
TL0 = (65536-1000)%256;
F_1MS=1; //这个标志位看主程序
}
前面那个POWER_INIT();这个函数你要自己配置,就是IO口的输入输出属性,开不开上拉,初始电平的高低. 思路是这个思路. 这是一个模版.希望你可以看看,并且希望对你有帮助.因为我是在网页上编辑的,所以没有在KEIL里面验证,如果有报错, 你自己解决一下,但是整体的一个按键思路是这样的. |