单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:403|回复:22

C51单片机如何利用矩阵键盘上的一个键实现一个设备的启停

[复制链接]
ID:65580发表于 2024-4-9 09:46|显示全部楼层
C51单片机如何利用矩阵键盘上的一个键实现一个设备的启停---下面的程序是想实现在矩阵键盘检测到13#键时,第一次为打开照明灯,松开后灯继续亮,第二次按这个键时,松开手灯灭的功能,单独运行本程序正常,加到switch--case语句中就不能运行了,怎样解决此问题,我测试时用过取反程序--由于按键持续按住,灯不停亮灭实现不了此功能。

       case 13:     ///*照明控制*/
                                           if(step==13)
                                           {
                                                 Delay_ms(10);
                                                 if(step==13)
                                                 {
                                 //                       LCD_ShowString(1,1,"           ");
                                                       LCD_ShowString(1,1,"lighting control");//在第1行照明控制
                                                      
                                                       LIGKZ_cnt++;
                                                      
                                                       if(LIGKZ_cnt==1)
                                                       {
                                                           LIGKZ=1;      
                                                           LCD_ShowString(2,1,"Status:  LightOn");//在第2行灯亮                          
                                                       }
                                                 if(LIGKZ_cnt==2)
                                                       {
                                                           LIGKZ=0;
                                                           LCD_ShowString(2,1,"Status: LightOff");//在第2行灯亮          
                                                           LIGKZ_cnt=0;
                                                       }                      
                                          
                                                       while(step==13)
                                                       {      
                                                           Delay_ms(20);
//                                                           LIGKZ=~LIGKZ;
                                                           led0=1;  //测试灯      

                                                       }
////                                                                 LIGKZ=~LIGKZ;
                                                 }      
                                           }      
//                                           led0=~led0;  //测试灯      
                                           break;

ID:161164发表于 2024-4-9 13:25|显示全部楼层
代码不完整
盲猜
1. step 用完没清零
2. step 在delay期间在哪更新?
if(step==13)
{
Delay_ms(10);
if(step==13)
ID:65580发表于 2024-4-10 11:18|显示全部楼层
1:step是采用矩阵键盘中的键输入数据,松键step=0.
2:好像问题在于松手检测--跳不出来:    
                                                   while(step==13)
                                                       {      
                                                           Delay_ms(20);
//                                                           LIGKZ=~LIGKZ;
                                                           led0=1;  //测试灯      

                                                       }
ID:65580发表于 2024-4-10 14:13|显示全部楼层
lkc8210 发表于 2024-4-9 13:25
代码不完整
盲猜
1. step 用完没清零

下面是全部的程序
void main(void)
{
     uchar PWKZ_cnt=0;//电源控制标志位,按钮次数
     uchar LIGKZ_cnt=0;//照明控制标志位,按钮次数
     PWKZ=0;//24V电源控制
     LIGKZ=0;//照明控制初始化
     P2=0;//所有电机不工作
     LCD_Init();//LCD初始化

     while(1)
     {
         if(S1==0) {step=13;} else {step=0;}//S1临时测试按钮,测试完成后由矩阵键盘输入step值
        
         switch(step)
         {
             case 0:{    
                         M1ZZ=0; //所有电机停止转动
                         M1FZ=0;
                         M2ZZ=0;
                         M2FZ=0;
                         M3ZZ=0;
                         M3FZ=0;
                         M4ZZ=0;
                         M4FZ=0;
                         LCD_ShowNum(1,13,step,2);
                         break;
                     }
             case 1:M1ZZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M1正转
             case 2:M2ZZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M2正转
             case 3:M3ZZ=1;M4ZZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M3,M4正转
             case 4:M3ZZ=1;M4FZ=1;LCD_ShowNum(1,13,step,2);break;   //电机M3正转,M4反转
                        
             case 5:M1FZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M1反转
             case 6:M2FZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M2发转
             case 7:M3FZ=1;M4FZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M3,M4反转
             case 8:M3FZ=1;M4ZZ=1;LCD_ShowNum(1,13,step,2);break;   //电机M3反转,M4正转
                        
             case 9:M1ZZ=1;M2ZZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M1与M2正转
             case 10:M1FZ=1;M2FZ=1;LCD_ShowNum(1,13,step,2);break;  //电机M1与M2反转
             case 11:M1FZ=1;M2FZ=1;M3FZ=1;M4FZ=1;LCD_ShowNum(1,13,step,2);break;  //所有电机电机M1,M2,M3,M4反转
             case 12:M1ZZ=1;M2ZZ=1;M3ZZ=1;M4ZZ=1;LCD_ShowNum(1,13,step,2);break;   //所有电机电机M1,M2,M3,M4正转
                        
             case 13:   /*照明控制程序*/      
                     if(step==13)  
                     {
                         Delay_ms(10);
                         if(step==13)
                         {
             //                 LCD_ShowString(1,1,"           ");
                             LCD_ShowString(1,1,"lighting control");//在第1行照明控制
                            
                             LIGKZ_cnt++;
                            
                             if(LIGKZ_cnt==1)
                             {
                                 LIGKZ=1;     //灯亮
                                 LCD_ShowString(2,1,"Status:  LightOn");//在第2行灯亮                    
                             }
                           if(LIGKZ_cnt==2)
                             {
                                 LIGKZ=0;//灯灭
                                 LCD_ShowString(2,1,"Status: LightOff");//在第2行灯亮        
                                 LIGKZ_cnt=0;
                             }                
                    
                             while(step==13)
                             {    
                                 Delay_ms(20);
                             }
                         }    
                     }    

                    
                             break;
                                
             case 14:
                     if(step==14)
                     {
                         Delay_ms(10);
                         if(step==14)
                         {
             //                 LCD_ShowString(1,1,"           ");
                             LCD_ShowString(1,1,"At stopped state");//在第1行照明控制-LCD显示
                            
                             PWKZ_cnt++;
                            
                             if(PWKZ_cnt==1)
                             {
                                 PWKZ=1;    
                                 LCD_ShowString(2,1,"Status:Operation");//在第2行灯亮-LCD显示                    
                             }
                           if(PWKZ_cnt==2)
                             {
                                 PWKZ=0;
                                 LCD_ShowString(2,1," Please unlock  ");//在第2行灯亮-LCD显示        
                                 PWKZ_cnt=0;
                             }                                
                    
                             while(step==14)
                             {        
                                 Delay_ms(10);
                             }
                            
                         }    
                     }        
                             break;
                            
             case 15:break;  //备用
             case 16:break;   //备用
                        
         }
     }
}
ID:161164发表于 2024-4-10 16:17|显示全部楼层
while(step==13)
step没地方更新,死循环了
ID:65580发表于 2024-4-11 09:42|显示全部楼层
lkc8210 发表于 2024-4-10 16:17
while(step==13)
step没地方更新,死循环了

这句S1按钮松开后,step=0,
if(S1==0) {step=13;} else {step=0;}//S1临时测试按钮,测试完成后由矩阵键盘输入step值
ID:161164发表于 2024-4-11 10:48|显示全部楼层
lss9310 发表于 2024-4-11 09:42
这句S1按钮松开后,step=0,
if(S1==0) {step=13;} else {step=0;}//S1临时测试按钮,测试完成后由矩阵键 ...

你了解while(step==13)是啥意思吗?
都死循环了,还咋跳出去跑if(S1==0) {step=13;} else {step=0;}?
ID:453974发表于 2024-4-11 13:33|显示全部楼层
lkc8210 发表于 2024-4-11 10:48
你了解while(step==13)是啥意思吗?
都死循环了,还咋跳出去跑if(S1==0) {step=13;} else {step=0;}?

他说的对,你程序卡死在while里面了,在while里面把条件清零跳出循环
ID:1109793发表于 2024-4-11 20:07|显示全部楼层
在case 13里面再搞个if(step==13),有意思吗?
ID:65580发表于 2024-4-12 08:33|显示全部楼层
本帖最后由 lss9310 于 2024-4-12 11:02 编辑
xiaobendan001 发表于 2024-4-11 20:07
在case 13里面再搞个if(step==13),有意思吗?

本意是松手检测,我的想法是这样的,如没有这句while(step==13)则LIGKZ_cnt++;一直在加。具体这个功能能实现吗,麻烦给一个程序。谢谢
ID:1109793发表于 2024-4-12 19:37|显示全部楼层
lss9310 发表于 2024-4-12 08:33
本意是松手检测,我的想法是这样的,如没有这句while(step==13)则LIGKZ_cnt++;一直在加。具体这个功能能 ...

case:后面加{},我还是不太习惯。
既然你要在松手时动作,那就放case 0:里面才对吧。
你试试看
uchar kt;
然后在case 13:里面kt = 13;
然后在case 0:里面
if(kt==13){}
这样行不行
ID:65580发表于 2024-4-13 13:49|显示全部楼层
xiaobendan001 发表于 2024-4-12 19:37
case:后面加{},我还是不太习惯。
既然你要在松手时动作,那就放case 0:里面才对吧。
你试试看

测试之后,不行。C51单片机利用矩阵键盘上的一个键(同样一个键值),实现同一台设备的第一次按按键启动,第二次按按键停止的控制,能否实现呢
ID:1109793发表于 2024-4-13 15:59|显示全部楼层
lss9310 发表于 2024-4-13 13:49
测试之后,不行。C51单片机利用矩阵键盘上的一个键(同样一个键值),实现同一台设备的第一次按按键启动 ...

当然可以实现啊,那里不行?把改动的代码发上来看看呗
ID:65580发表于 2024-4-14 08:45|显示全部楼层
xiaobendan001 发表于 2024-4-13 15:59
当然可以实现啊,那里不行?把改动的代码发上来看看呗

之前我的程序已经上传,而且要求也描述了,你看看怎么能实现此功能呢,请求帮助提供一个程序,因为之前我试了很多没成功,谢谢 !
ID:1109793发表于 2024-4-14 09:36|显示全部楼层
lss9310 发表于 2024-4-14 08:45
之前我的程序已经上传,而且要求也描述了,你看看怎么能实现此功能呢,请求帮助提供一个程序,因为之前我 ...

之前的不能用,我说的方法你可能没试过。然后我也没有硬件,没办法测试是否能用。只能靠你自己了。
ID:161164发表于 2024-4-15 11:17|显示全部楼层
lss9310 发表于 2024-4-11 09:42
这句S1按钮松开后,step=0,
if(S1==0) {step=13;} else {step=0;}//S1临时测试按钮,测试完成后由矩阵键 ...
  1. void main(void)
  2. {
  3.      uchar PWKZ_cnt=0;//电源控制标志位,按钮次数
  4.      uchar LIGKZ_cnt=0;//照明控制标志位,按钮次数
  5.      PWKZ=0;//24V电源控制
  6.      LIGKZ=0;//照明控制初始化
  7.      P2=0;//所有电机不工作
  8.      LCD_Init();//LCD初始化

  9.      while(1)
  10.      {
  11.          if(S1==0)
  12.          {
  13.              Delay_ms(10);
  14.              if(S1==0)
  15.              {
  16.                  step=13;   //S1临时测试按钮,测试完成后由矩阵键盘输入step值
  17.                  while(SI==0);
  18.              }
  19.          }
  20.          else
  21.          {
  22.              step=0;
  23.          }

  24.          switch(step)
  25.          {
  26.              case 0:
  27.              {
  28.                  M1ZZ=0; //所有电机停止转动
  29.                  M1FZ=0;
  30.                  M2ZZ=0;
  31.                  M2FZ=0;
  32.                  M3ZZ=0;
  33.                  M3FZ=0;
  34.                  M4ZZ=0;
  35.                  M4FZ=0;
  36.                  LCD_ShowNum(1,13,step,2);
  37.                  break;
  38.              }
  39.              case 1:
  40.                  M1ZZ=1;
  41.                  LCD_ShowNum(1,13,step,2);
  42.                  break;  //电机M1正转
  43.              case 2:
  44.                  M2ZZ=1;
  45.                  LCD_ShowNum(1,13,step,2);
  46.                  break;  //电机M2正转
  47.              case 3:
  48.                  M3ZZ=1;
  49.                  M4ZZ=1;
  50.                  LCD_ShowNum(1,13,step,2);
  51.                  break;  //电机M3,M4正转
  52.              case 4:
  53.                  M3ZZ=1;
  54.                  M4FZ=1;
  55.                  LCD_ShowNum(1,13,step,2);
  56.                  break;   //电机M3正转,M4反转

  57.              case 5:
  58.                  M1FZ=1;
  59.                  LCD_ShowNum(1,13,step,2);
  60.                  break;  //电机M1反转
  61.              case 6:
  62.                  M2FZ=1;
  63.                  LCD_ShowNum(1,13,step,2);
  64.                  break;  //电机M2发转
  65.              case 7:
  66.                  M3FZ=1;
  67.                  M4FZ=1;
  68.                  LCD_ShowNum(1,13,step,2);
  69.                  break;  //电机M3,M4反转
  70.              case 8:
  71.                  M3FZ=1;
  72.                  M4ZZ=1;
  73.                  LCD_ShowNum(1,13,step,2);
  74.                  break;   //电机M3反转,M4正转

  75.              case 9:
  76.                  M1ZZ=1;
  77.                  M2ZZ=1;
  78.                  LCD_ShowNum(1,13,step,2);
  79.                  break;  //电机M1与M2正转
  80.              case 10:
  81.                  M1FZ=1;
  82.                  M2FZ=1;
  83.                  LCD_ShowNum(1,13,step,2);
  84.                  break;  //电机M1与M2反转
  85.              case 11:
  86.                  M1FZ=1;
  87.                  M2FZ=1;
  88.                  M3FZ=1;
  89.                  M4FZ=1;
  90.                  LCD_ShowNum(1,13,step,2);
  91.                  break;  //所有电机电机M1,M2,M3,M4反转
  92.              case 12:
  93.                  M1ZZ=1;
  94.                  M2ZZ=1;
  95.                  M3ZZ=1;
  96.                  M4ZZ=1;
  97.                  LCD_ShowNum(1,13,step,2);
  98.                  break;   //所有电机电机M1,M2,M3,M4正转

  99.              case 13:   /*照明控制程序*/
  100.                  //                       LCD_ShowString(1,1,"           ");
  101.                  LCD_ShowString(1,1,"lighting control");//在第1行照明控制

  102.                  LIGKZ_cnt++;

  103.                  if(LIGKZ_cnt==1)
  104.                  {
  105.                      LIGKZ=1;       //灯亮
  106.                      LCD_ShowString(2,1,"Status:  LightOn");//在第2行灯亮
  107.                  }
  108.                  if(LIGKZ_cnt==2)
  109.                  {
  110.                      LIGKZ=0;//灯灭
  111.                      LCD_ShowString(2,1,"Status: LightOff");//在第2行灯亮
  112.                      LIGKZ_cnt=0;
  113.                  }
  114.                  step = 0;
  115.                  break;

  116.              case 14:
  117.                  if(step==14)
  118.                  {
  119.                      Delay_ms(10);
  120.                      if(step==14)
  121.                      {
  122.                          //                       LCD_ShowString(1,1,"           ");
  123.                          LCD_ShowString(1,1,"At stopped state");//在第1行照明控制-LCD显示

  124.                          PWKZ_cnt++;

  125.                          if(PWKZ_cnt==1)
  126.                          {
  127.                              PWKZ=1;
  128.                              LCD_ShowString(2,1,"Status:Operation");//在第2行灯亮-LCD显示
  129.                          }
  130.                          if(PWKZ_cnt==2)
  131.                          {
  132.                              PWKZ=0;
  133.                              LCD_ShowString(2,1," Please unlock  ");//在第2行灯亮-LCD显示
  134.                              PWKZ_cnt=0;
  135.                          }

  136.                          while(step==14)
  137.                          {
  138.                              Delay_ms(10);
  139.                          }

  140.                      }
  141.                  }
  142.                  break;

  143.              case 15:
  144.                  break;  //备用
  145.              case 16:
  146.                  break;   //备用

  147.          }
  148.      }
  149. }
复制代码
ID:65580发表于 2024-4-24 09:48|显示全部楼层

谢谢!这样用S1键模拟,达到同一个键按二次实现了设备的启动与停止。我的程序本意是通过485通信,主机接收到数据是13,即step=13,这个值二次实现设备的启动与停止,此程序修改为下面没能实现想要的控制:                     key_val=re_buf[0];//key_val--接收485传过来的数据
//                 if(key_val!=13) {step=key_val;s2=1;}
                 if(key_val==13) {s2=0;}
                 if(s2==0)
                 {
                                 Delay_ms(10);
                                 if(s2==0)
                                 {
                                                 step=13;   //S1临时测试按钮,测试完成后由矩阵键盘输入step值
                                                 while(key_val==0);
                                 }
                 }
                 else
                 {
                                 step=key_val;
                                 s2=1;
                 }

请教我怎么能实现此功能呢,麻烦给一个程序,谢谢!
ID:161164发表于 2024-4-24 10:31|显示全部楼层
lss9310 发表于 2024-4-24 09:48
谢谢!这样用S1键模拟,达到同一个键按二次实现了设备的启动与停止。我的程序本意是通过485通信,主机接 ...

你一开始就说是485就不用浪费15天
ID:1109793发表于 2024-4-24 10:59|显示全部楼层
lss9310 发表于 2024-4-24 09:48
谢谢!这样用S1键模拟,达到同一个键按二次实现了设备的启动与停止。我的程序本意是通过485通信,主机接 ...
  1. if(key_val==13){
  2.      key_val = 0;
  3.      s2 = !s2;
  4. }

复制代码
ID:344848发表于 2024-4-24 14:45|显示全部楼层

使用D触发器搭建的一个电路便可以实现!
ID:344848发表于 2024-4-24 14:52|显示全部楼层
单片机外围接一个D触发器,或使用CPLD搭建一个D触发器,接受485信号后,就可以实现上述功能。
ID:344848发表于 2024-4-24 14:58|显示全部楼层
实际工程讲究快速和可靠,以最短的时间完成项目。
ID:1109793发表于 2024-4-24 15:18|显示全部楼层
donglw 发表于 2024-4-24 14:45
使用D触发器搭建的一个电路便可以实现!

人家是要软件解决的

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

Powered by 单片机教程网