单片机源程序如下: #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里面验证,如果有报错, 你自己解决一下,但是整体的一个按键思路是这样的. |
void key_scan() { static unsigned int count=0; static bit key_lock=0; if(!KEY) { if(++count>=65000 && key_lock==0) { key_lock=1; LED=~LED; } } else { count=0; key_lock=0; } } |
这个初始会不会老把定时器清除 |
IMG_20200518_224101.jpg (226.02 KB, 下载次数: 120)
#include "stc15w.h" #include <intrins.H> //函数运算头文件 #define uint unsigned int //宏定义变量0-6553 #define uchar unsigned char //宏定义变量0-255 #define MAIN_Fosc 11059200L //定义主时钟 #define key_S 80 //宏定义短按(约20ms) #define key_L key_S*50 //宏定义长按(约1s) void readkey(void) //按键读取函数 { static uint count=0; //计数变量 if(!key) { count++; if(count==key_L) //长按 ON=~ON; //长按要运行的 if(count>key_L) //防止count溢出 count=key_L+1; } else //按键抬起 { if(count>key_S && count<key_L)//短按 { if(ON==1) //开机状态有效 HL=~HL; //短按要运行的 } count=0; //count清0 } } |
另外按键处理逻辑不清晰,应当把中断的判断3秒移出到按键代码中,再理清按键处理逻辑,应该就差不多了。 |
建议:既然有中断计时,循环延时就没必要了,完全可以由中断计时获得延时了。你这样写中断控制LED的代码与按键无关,只是每3秒变换LED而已。 |
即lled的亮与灭 |