找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于51单片机独立按键程序的快速切换

[复制链接]
跳转到指定楼层
楼主
ID:421426 发表于 2018-11-5 23:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
增加怎样的程序才能使51单片机上的独立按键控制的程序可以在第一个键还在执行的过程中就可以切换到下一个按键所操控的程序
#include <reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
typedef unsigned char u8;
typedef unsigned int u16;
uchar temp;      
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;   
void delay(u16 i)
{
while(i--);
}
void keypros()
{
u8 i=0;
if(k1==0)  
{   
  if(k1==0)
  {
  for(i=0;i<5;i++)  
  {   
   P2=0x55;
   delay(15000);
   P2=0xaa;
   delay(15000);
   break;
  }
  while(!k1);
}
P2=0xff;
}
{
u8 k=0;
if(k2==0)   
{   
  if(k2==0)         
  {
  {
  temp=0xfe;
  P2=temp;
  for(k=0;k<2;k++)
{
  while(temp!=0x7f)
  {
   temp=_crol_(temp,1);
   delay(5000);
   P2=temp;
  }
  temp=0x7f;
  P2=temp;
  while(temp!=0xfe)
  {
   temp=_cror_(temp,1);
   delay(5000);
   P2=temp;
  }
  break;
}
}
  while(!k2);
}
P2=0xff;
}
}
{  
u8 n=0;
if(k3==0)   
{   
  if(k3==0)
  {
  for(n=0;n<2;n++)  
  {   
   P2=0x00;
   delay(15000);
   P2=0xff;
   delay(15000);
   break;
  }
  while(!k3);
}
P2=0xff;
}
}  
if(k4==0)   
{   
  if(k4==0)  
  {   
  P2=0x00;
  }
  while(!k4);
}  
}
void main()
{
while(1)
{
  keypros();  
}  
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:401564 发表于 2018-11-6 01:07 | 只看该作者
想法很好,却很不现实,51是单线程的,除去外置的模块比如ADC,PWM,IIC之类的可以在执行指令之外同时进行,其它的,只能一条一条的去执行的

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:89515 发表于 2018-11-6 10:04 | 只看该作者
需要实时响应按键程序,那么就不能像你那样写。如果懂得状态机的方式那很简单。如果不懂可以用外部中断做按键程序来改变标志。在你的一个个for循环的最内层判断标志,如果标志改变就直接return。当然你的各个函数也必须工作在不同的标志之下

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:373093 发表于 2018-11-6 11:52 | 只看该作者
只能用外部中断,但是有一定限制,如按键数多了不现实。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:421426 发表于 2018-11-6 16:59 | 只看该作者
mengzhixinheng 发表于 2018-11-6 10:04
需要实时响应按键程序,那么就不能像你那样写。如果懂得状态机的方式那很简单。如果不懂可以用外部中断做按 ...

您好   我是一个初学者  您说的我有一点不是很懂  您能更详细的和我说说吗
回复

使用道具 举报

6#
ID:89515 发表于 2018-11-6 17:46 | 只看该作者
坐在分头调戏鬼 发表于 2018-11-6 16:59
您好   我是一个初学者  您说的我有一点不是很懂  您能更详细的和我说说吗

你需要的效果其实就是按下按键时,及时的响应对应按键的程序,而不是等待上一个按键的程序执行完再响应对不对。
回复

使用道具 举报

7#
ID:421426 发表于 2018-11-6 21:51 | 只看该作者
mengzhixinheng 发表于 2018-11-6 17:46
你需要的效果其实就是按下按键时,及时的响应对应按键的程序,而不是等待上一个按键的程序执行完再响应对 ...

是的     那我应该怎么办啊   没有什么思路   
回复

使用道具 举报

8#
ID:421426 发表于 2018-11-6 22:00 | 只看该作者
mengzhixinheng 发表于 2018-11-6 17:46
你需要的效果其实就是按下按键时,及时的响应对应按键的程序,而不是等待上一个按键的程序执行完再响应对 ...

对的     那我应该怎么办啊
回复

使用道具 举报

9#
ID:421426 发表于 2018-11-6 22:00 | 只看该作者
mengzhixinheng 发表于 2018-11-6 17:46
你需要的效果其实就是按下按键时,及时的响应对应按键的程序,而不是等待上一个按键的程序执行完再响应对 ...

对的     那我应该怎么办啊
回复

使用道具 举报

10#
ID:421426 发表于 2018-11-6 22:36 | 只看该作者
mengzhixinheng 发表于 2018-11-6 17:46
你需要的效果其实就是按下按键时,及时的响应对应按键的程序,而不是等待上一个按键的程序执行完再响应对 ...

对的    您说我应该怎么办呢
回复

使用道具 举报

11#
ID:89515 发表于 2018-11-7 15:15 | 只看该作者
void led1()
{
       for循环
      {
             // 假如此处进入中断;
             // 中断返回,标志改变;
              判断标志k,若改变return;
      }
}
void led2()
{
        for循环
      {         
             // 假如此处进入中断;
             // 中断返回,标志改变;
              判断标志k,若改变return;

      }
}
void led3()
{
        for循环
      {            
             // 假如此处进入中断;
             // 中断返回,标志改变;
              判断标志k,若改变return;

      }
}
void main(void)
{
      while(1)
     {
            if(k==1)led1();//k为执行相应函数的标志
            if(k==2)led2();
            if(k==3)led3();
     }
}
void  int()  interrupt//外部中断函数
{
      if(++k==3)k=1;//此处可以软件延时消抖,但不是好方法,这减弱了外部中断的作用。但又必须消抖,
                               怎么办??可以硬件消抖(积分电路),这是最简单的方法。那如果非要软件消抖呢,那就嵌套定时器(这说起来复杂)。
}
通常情况下按键扫描和其他程序处于顺序执行状态,各个按键也是顺序扫描的。这样当执行一个按键程序时就必须将他执行完才能扫描下一个按键。如果各个按键下的程序需要的执行时间很长,那么将造成按键响应不及时;这也就是你遇到的情况。
问题找到了,当然就要找解决方法;比较实用的方法很多但是都离不开中断,这是必须的。因为中断可以打断主程序的执行,从而及时改变各个函数的执行标志,但是并不是执行标志改变就能及时响应程序。这是为什么呢?????这是因为进入中断前是必须保存“上下文”的,自然从中断出去也必须从保存的“上下文”处开始执行,无法直接判断到标志是否改变。既然这样我们就人为的让它检测到标志已经改变,这是很简单的事情,只需要在各个函数循环的最内层判断标志,当标志改变直接返回主函数,返回主函数后再按照标志的值执行相应的函数就可以了。
以上的方法如果用外部中断可以直接照做;若用定时器中断,那就必须写按键函数,并将其嵌入定时器中断中。按键函数的写法最好是状态机的形式
(这个“状态机”涉及内容太多可以百度)
前面所说都是从按键的方向去解决问题;自然也可以从执行函数的方向去解决,按键响应不及时不就是函数执行时间太久了,那就把函数按时间间隙分成一个个状态。像LED类的程序是不难办到的……

在这里针对性的解决问题固然很好,但是适应性其实很差,而且过多的标志也烦。要在裸机的情况下解决实时性问题最好还是学会状态机程序的写法和时间片轮询框架的应用。



回复

使用道具 举报

12#
ID:390006 发表于 2018-11-7 19:03 | 只看该作者
延时读键程序只能用于学习,不能商用,单片机的要处理很多事情。用节拍扫描,或中断好一些。
回复

使用道具 举报

13#
ID:422650 发表于 2018-11-7 21:59 | 只看该作者
厉害了,很有用
回复

使用道具 举报

14#
ID:422661 发表于 2018-11-7 22:30 | 只看该作者
应该按按键ESC?
回复

使用道具 举报

15#
ID:612563 发表于 2020-5-3 11:32 来自手机 | 只看该作者
看不懂
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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