找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2549|回复: 7
打印 上一主题 下一主题
收起左侧

我想实现长按k1按键3s开机再按3s关机 单片机程序为啥不行?请大神看下

[复制链接]
跳转到指定楼层
楼主


单片机源程序如下:
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit LED=P1^1;
sbit KEY=P2^0;
static uint i=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 delay (uint i) //延时函数
{
while(i--);
}

void main()
{
while(1) //一直检测按键是否按下 ?按下则进入中断
{
delay(1000);
if(KEY==0)
{
delay(1000); //按键消抖
if(KEY==0)
Timer0Init(); //定时器0初始化 申请中断
}
else
{
TR0=0; //无按键按下时,关闭定时器中断申请? 将i置零
i=0;
}
}
}
void Timer0() interrupt 1 //中断函数
{
TH0 = (65536-1000)/256;
TL0 = (65536-1000)%256;
i++;if(i>=3000) //超过3s开灯 i++至3000时 为3s
LED=~LED;
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:714987 发表于 2020-5-18 16:55 | 只看该作者
即lled的亮与灭
回复

使用道具 举报

板凳
ID:332444 发表于 2020-5-18 19:29 | 只看该作者
建议:既然有中断计时,循环延时就没必要了,完全可以由中断计时获得延时了。你这样写中断控制LED的代码与按键无关,只是每3秒变换LED而已。
回复

使用道具 举报

地板
ID:332444 发表于 2020-5-18 19:32 | 只看该作者
另外按键处理逻辑不清晰,应当把中断的判断3秒移出到按键代码中,再理清按键处理逻辑,应该就差不多了。
回复

使用道具 举报

5#
ID:562338 发表于 2020-5-18 21:23 | 只看该作者
#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
        }   
}
回复

使用道具 举报

6#
ID:712493 发表于 2020-5-18 22:43 来自手机 | 只看该作者
这个初始会不会老把定时器清除

IMG_20200518_224101.jpg (226.02 KB, 下载次数: 95)

IMG_20200518_224101.jpg
回复

使用道具 举报

7#
ID:213173 发表于 2020-5-19 07:27 | 只看该作者
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;
        }
}
回复

使用道具 举报

8#
ID:548551 发表于 2020-5-19 11:43 | 只看该作者

单片机源程序如下:
#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里面验证,如果有报错, 你自己解决一下,但是整体的一个按键思路是这样的.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表