搜索
bottom↓
回复: 22

按键互锁的程序啊

[复制链接]

出0入0汤圆

发表于 2013-4-18 09:39:22 | 显示全部楼层 |阅读模式
自己做了个程序一直无法实现互锁,哪位有,借鉴下 ,谢谢

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2013-4-23 22:20:50 | 显示全部楼层
这几天一直在寻找解决方法,无奈啊,有人知道怎么做吗?,
#include "iom16v.h"
#include "macros.h"
#include <AVR_PQ1A.h>                //包含自定义常量头文件
#define uchar unsigned char
#define uint unsigned int
unsigned char  F_Rotation[4]={0xF1,0xF2,0xF4,0xF8}; //正转表格,换算成二进制 0000 0001,0000 0010,0000 0100,0000 1000
unsigned char  B_Rotation[4]={0xF8,0xF4,0xF2,0xF1}; //反转表格

unsigned char const Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,};//0~9
unsigned char leddata[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82, 0xF8,0x80,0x90,0xFF};
uchar i;//定义变量
uint num;//定义计数变量
#pragma data:code//数组存放位置
flash table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void delay(uint ms)
{
        uint i,j;
        for(i=0;i<ms;i++)
           {
           for(j=0;j<1141;j++);
       }
           }
//顺时针转动          
void MotorCW()
{

unsigned char i;
     {
    DDRB = 0xFF;
        for(i=0;i<4;i++)      //4相
          {
          PORTB=F_Rotation[i];  //输出对应的相 可以自行换成反转表格
          delay(1);        //改变这个参数可以调整电机转速 ,数字越小,转速越大
                 }
       }
}
//逆时针转动       
void MotorCCW()
{

unsigned char i;
     {
    DDRB = 0xFF;
        for(i=0;i<4;i++)      //4相
          {
          PORTB=B_Rotation[i];  //输出对应的相 可以自行换成反转表格
          delay(1);        //改变这个参数可以调整电机转速 ,数字越小,转速越大
                 }
       }
}
void MotorStop()
{   
    DDRB = 0xFF;
}
unsigned char KeyResult;
//键盘按下判断函数
uchar key_press()     //按键子函数 ,带返回值的子函数
{
    uchar j;      //定义变量J
        DDRD|=0X0F;  //按键低4位输出,其它不变
        PORTD|=0X0F;  //按键低4位输出高电平,其它不变
        DDRD&=0XF0;  //按键低4位输入,其它不变
        j=PIND;        //对变量J赋值
        j=j&0X0F;//00001111  进行与运算,判断按键是否有按下
     if(j==0X0F)  //如果按键没有按下返回0,如按下返回1给  key_press
        {
          return 0;
        }
        else
        {
         return 1;
        }
}
//*****************************扫描子函数**********************************
uchar key_scan()   
{
    uchar key;   //定义变量KEY  
    delay(10);   //延时10MS再次确定按键是否有被按下
        if(key_press())  //判断按键 是否有被按下,则key_press为1,如按下则执行如下语句
        {
        key=PIND;    //对变量KEY进行赋值
        key&=0X0F;   //进行运算判断一下是否真的有按下,如真的有按下,则有如下情况
        switch(key)    //条件语句
        {
           case 0X0E:key=0X0E;break; //a0按下所对应的数据 ,并执行KEY为1
           case 0X0D:key=0X0D;break;     //a1按下
           case 0X0B:key=0X0B;break;    //a2按下
           case 0X07:key=0X07;break;    //a3按下
           default:key=0;break;              //什么也没有按下
         }
          while(key_press());  //判断一下是否有松开
        }
         else    //如果没有按下则执行如下语句
        {
          key=0;    //变量赋值16
        }
        return key;   //返回KEY给key_scan扫描函数
}
void light()  

    {    DDRA=0xff;                                    //PA0~7为输出状态
             PORTA=0x01;                                //PA0为输出低电平,而其余为高电平,亦即打亮LED0
    }
void lightt()  
    {    DDRA=0xff;                                    //PA0~7为输出状态
             PORTA=0x02;                                //PA1为输出低电平,而其余为高电平,亦即打亮LED1               
    }
void lights()  
    {    DDRA=0xff;                                    //PA0~7为输出状态
             PORTA=0x04;                                //PA2为输出低电平,而其余为高电平,亦即打亮LED2               
    }
void lightf()  
    {   DDRA=0xff;                                    //PA0~7为输出状态
            PORTA=0x08;                                   //PA3为输出低电平,而其余为高电平,亦即打亮LED3               
    }
void lightm()  
    {   DDRA=0xff;                                    //灭灯
            PORTA=0x00;                               
            PORTA=0x80;               
    }
void light5()  
    {   DDRA=0xff;                                  
            PORTA=0x10;                                          
    }
void light6()  
    {   DDRA=0xff;                                  
            PORTA=0x20;                                          
    }       

//电机程序
void turn()
       { uint j;
             do
                 {
               uint i;
               delay(1);
               light();//******************第一台电机转动指示灯
                  for (i=0;i<100;i++)
               { MotorCW();//顺时针转动
                     }
                  delay(10);
                  MotorStop();  //停止转动
                  delay(10);
          for (i=0;i<100;i++)
               { MotorCCW();//逆时针转动
                     }
                  delay(10);
                  MotorStop();//停止转动
                  delay(1);       
                                  lightt();//****************第二台
                  for (i=0;i<100;i++)
              { MotorCW();//顺时针转动
                    }
                  delay(10);
                  MotorStop();  //停止转动
                  delay(10);
          for (i=0;i<100;i++)
              { MotorCCW();//逆时针转动
                   }
                  delay(10);
                  MotorStop();//停止转动
                  delay(1);               
                                  lights();//*******************第三台
                  for (i=0;i<100;i++)
              { MotorCW();//顺时针转动
                  }
                 delay(10);
                 MotorStop();  //停止转动
                 delay(10);
          for (i=0;i<100;i++)
              { MotorCCW();//逆时针转动
                 }
                 delay(10);
                 MotorStop();//停止转动
                 delay(1);       
                                 lightf();//*****************第四台
                  for (i=0;i<100;i++)
             { MotorCW();//顺时针转动
                 }
                 delay(10);
                 MotorStop();  //停止转动
                 delay(10);
          for (i=0;i<100;i++)
             { MotorCCW();//逆时针转动
                 }
                 delay(10);
                 MotorStop();//停止转动
                 delay(1);                                      
                             lightm();       
                                 delay(10);
                                 xianshi();
           }while(j!=0X0E);
           }

//数码管显示
void xianshi()
{
     
       uint i;
            
        for(i=0;i<20;i++)//显示20次,使整体看起来不闪烁
            {
         PORTC=table[num%10];
         delay(10);}
         if(PORTA=0x80)
                                num++;

}       
main(void)
{
    uint j,m;
       
       
       while(1)
    {   
      j=key_scan();
         switch(j)
          {
         case 0X0E:turn();xianshi;
         break;
         case 0X0D:num=0;light5();break;
     case 0X0B:MotorStop();light6();break;     
          }
         delay(10);
    }
          
}
       
       

出0入0汤圆

发表于 2013-4-23 22:54:25 | 显示全部楼层
怎么那么长?具体要实现什么样的功能?普通按键互锁的话汇编不用多少行程序就搞定了

出0入0汤圆

 楼主| 发表于 2013-4-24 07:41:36 | 显示全部楼层
chaily 发表于 2013-4-23 22:54
怎么那么长?具体要实现什么样的功能?普通按键互锁的话汇编不用多少行程序就搞定了 ...

就是普通的互锁,只能用C,我在论坛搜过,但是好像没有按键互锁方面的资料

出0入0汤圆

发表于 2013-4-24 08:29:41 | 显示全部楼层
jimmyfan 发表于 2013-4-24 07:41
就是普通的互锁,只能用C,我在论坛搜过,但是好像没有按键互锁方面的资料 ...

就是比如A和B两个按键,按A以后A被锁定,放开A后A仍然处于锁定状态,然后按下B,A会被释放,B被锁定,B松开后仍然被锁定,再按A又重新释放B锁定A这样子是吗?这种涉及逻辑的用汇编来写是超简单的,C应该也很简单的啊,简单逻辑问题而已。

出0入0汤圆

 楼主| 发表于 2013-4-24 09:25:03 | 显示全部楼层
chaily 发表于 2013-4-24 08:29
就是比如A和B两个按键,按A以后A被锁定,放开A后A仍然处于锁定状态,然后按下B,A会被释放,B被锁定,B松 ...

对的,虽说简单,会者不难啊 ,我把论坛所有关于按键的帖子看了都没见到

出255入0汤圆

发表于 2013-4-24 10:05:13 | 显示全部楼层
chaily 发表于 2013-4-24 08:29
就是比如A和B两个按键,按A以后A被锁定,放开A后A仍然处于锁定状态,然后按下B,A会被释放,B被锁定,B松 ...

这个么简单还纠结

出255入0汤圆

发表于 2013-4-24 10:06:38 | 显示全部楼层
jimmyfan 发表于 2013-4-24 09:25
对的,虽说简单,会者不难啊 ,我把论坛所有关于按键的帖子看了都没见到 ...

首先看你的键值是怎么来的
只要你对相应的键不处理就可以实现互锁

出0入0汤圆

发表于 2013-4-24 10:06:55 | 显示全部楼层
看马潮老师的状态机。
逻辑想不通的话先画个流程图。

出0入0汤圆

发表于 2013-4-24 10:12:35 | 显示全部楼层
本帖最后由 chaily 于 2013-4-24 10:23 编辑
jimmyfan 发表于 2013-4-24 09:25
对的,虽说简单,会者不难啊 ,我把论坛所有关于按键的帖子看了都没见到 ...


好吧,我写一个汇编的给你,看不懂汇编本身没关系,每一条我都注释了,看懂思路然后你再用C来写就好了,已经测试过OK没问题的。程序如下:

;备注说明:A和B按键按下为0,不按下为1

anjianA EQU P1.0 ;定义按键A的I/O口
anjianB EQU P1.1 ;定义按键B的I/O口
ORG 0030H ;伪指令可忽略不管

LOOP: ;主循环程序,用于扫描按键A和B
JNB anjianA,AA ;检测按键A,如果为0则跳转至程序AA,1则执行下一条语句
JNB anjianB,BB ;检测按键B,如果为0则跳转至程序BB,1则执行下一条语句
LJMP LOOP ;跳回主循环程序开头


AA: ;按键A程序
LCALL DELAY ;延时10mS
JNB anjianA,$ ;检测按键A,如果A依然按下为0则执行本行语句,松开变成1后则执行下一行
SETB anjianB ;把按键B置1,释放B按键的锁定状态
CLR anjianA ;把按键A置0,锁定A按键
LJMP LOOP2 ;锁定A以后跳入仅按键B检测程序LOOP2

BB: ;按键B程序
LCALL DELAY ;延时10mS
JNB anjianB,$ ;检测按键B,如果B依然按下为0则执行本行语句,松开变成1后则执行下一行
SETB anjianA ;把按键A置1,释放A按键的锁定状态
CLR anjianB ;把按键B置0,锁定B按键
LJMP LOOP3 ;锁定B以后跳入仅按键A检测程序LOOP3

LOOP2: ;按键B检测程序,仅检测按键B
JNB anjianB,BB ;检测按键B,若为0则跳至按键B程序BB,1则执行下一条
LJMP LOOP2 ;跳回LOOP2循环检测按键B

LOOP3: ;按键A检测程序,仅检测按键A
JNB anjianA,AA ;检测按键A,若为0则跳至按键A程序AA,1则执行下一条
LJMP LOOP3 ;跳回LOOP3循环检测按键A

DELAY: ;延时10mS子程序
    MOV R6,#0CCH
DL0:
    MOV R5,#17H
    DJNZ R5,$
    DJNZ R6,DL0
    RET

END

对于按键检测,一般需要加延时程序来进行程序滤波,避免干扰或者由于按键按下瞬间接触不良导致的误检测。

出0入0汤圆

 楼主| 发表于 2013-4-24 10:28:33 | 显示全部楼层
天使之翼 发表于 2013-4-24 10:05
这个么简单还纠结

不是纠结因为我第一个键按下红藕执行的是while(1),死循环

出0入0汤圆

 楼主| 发表于 2013-4-24 10:29:52 | 显示全部楼层
wxwdxx 发表于 2013-4-24 10:06
看马潮老师的状态机。
逻辑想不通的话先画个流程图。

在看的,尝试过用状态机,但是按键没反应,编译时没错误,但是不知道怎么办

出0入0汤圆

 楼主| 发表于 2013-4-24 10:30:47 | 显示全部楼层
chaily 发表于 2013-4-24 10:12
好吧,我写一个汇编的给你,看不懂汇编本身没关系,每一条我都注释了,看懂思路然后你再用C来写就好了, ...

汇编在学校学过,互锁是不难的,谢谢啦

出255入0汤圆

发表于 2013-4-24 10:32:54 | 显示全部楼层
jimmyfan 发表于 2013-4-24 10:28
不是纠结因为我第一个键按下红藕执行的是while(1),死循环

你的程序太乱了
写法跟51的写法一样
这样让移植或更改就比较麻烦

出0入0汤圆

 楼主| 发表于 2013-4-24 10:35:54 | 显示全部楼层
天使之翼 发表于 2013-4-24 10:32
你的程序太乱了
写法跟51的写法一样
这样让移植或更改就比较麻烦

我自己也觉得很乱啊,但是我刚接触AVR一个月左右,只能这样了,很多东西还不懂,其实我也很之着急的,没人教,所有的东西都是自己在搞,我想初学者都能体会这心情的

出0入0汤圆

发表于 2013-4-24 10:46:02 | 显示全部楼层
jimmyfan 发表于 2013-4-24 10:35
我自己也觉得很乱啊,但是我刚接触AVR一个月左右,只能这样了,很多东西还不懂,其实我也很之着急的,没 ...

这个月应该过得很充实吧。 按键用状态机的话可以去借一本马潮老师的《AVR单片机嵌入式系统原理与应用实践》,里面写得还清楚。 估计你常见问题都可以找到答案。

出255入0汤圆

发表于 2013-4-24 10:47:32 | 显示全部楼层
jimmyfan 发表于 2013-4-24 10:35
我自己也觉得很乱啊,但是我刚接触AVR一个月左右,只能这样了,很多东西还不懂,其实我也很之着急的,没 ...

你会pc机编程嘛?
你要实现我功能其实就是pc机里面的一些属性控制

出0入0汤圆

 楼主| 发表于 2013-4-24 10:47:58 | 显示全部楼层
wugang_1213 发表于 2013-4-24 10:46
这个月应该过得很充实吧。 按键用状态机的话可以去借一本马潮老师的《AVR单片机嵌入式系统原理与应用实践 ...

是啊 ,每天焦头烂额的,状态机在看的,书一开始就买了,还是不行啊,用状态机按键之后直接按键没反应

出255入0汤圆

发表于 2013-4-24 10:48:36 | 显示全部楼层
jimmyfan 发表于 2013-4-24 10:35
我自己也觉得很乱啊,但是我刚接触AVR一个月左右,只能这样了,很多东西还不懂,其实我也很之着急的,没 ...

对于你来说得到键值是不可改变的,但你对键的操作是可以通过自定义属性来完成

出0入0汤圆

 楼主| 发表于 2013-4-24 10:49:02 | 显示全部楼层
wugang_1213 发表于 2013-4-24 10:46
这个月应该过得很充实吧。 按键用状态机的话可以去借一本马潮老师的《AVR单片机嵌入式系统原理与应用实践 ...

#include "iom16v.h"
#include "macros.h"
#include <AVR_PQ1A.h>                //包含自定义常量头文件
#define uchar unsigned char
#define uint unsigned int
unsigned char  F_Rotation[4]={0xF1,0xF2,0xF4,0xF8}; //正转表格,换算成二进制 0000 0001,0000 0010,0000 0100,0000 1000
unsigned char  B_Rotation[4]={0xF8,0xF4,0xF2,0xF1}; //反转表格

unsigned char const Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,};//0~9
unsigned char leddata[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82, 0xF8,0x80,0x90,0xFF};
uchar i;//定义变量
uint num;//定义计数变量

flash table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void delay(uint ms)
{
        uint i,j;
        for(i=0;i<ms;i++)
           {
           for(j=0;j<1141;j++);
       }
           }
//顺时针转动          
void MotorCW()
{

unsigned char i;
     {
    DDRB = 0xFF;
        for(i=0;i<4;i++)      //4相
          {
          PORTB=F_Rotation;  //输出对应的相 可以自行换成反转表格
          delay(1);        //改变这个参数可以调整电机转速 ,数字越小,转速越大
                 }
       }
}
//逆时针转动       
void MotorCCW()
{

unsigned char i;
     {
    DDRB = 0xFF;
        for(i=0;i<4;i++)      //4相
          {
          PORTB=B_Rotation;  //输出对应的相 可以自行换成反转表格
          delay(1);        //改变这个参数可以调整电机转速 ,数字越小,转速越大
                 }
       }
}
void MotorStop()
{   
    DDRB = 0xFF;
}
#define key_input        PIND                        // 按键输入口

#define key_no               0b11111111
#define key_k1               0b00001110
#define key_k2               0b00001101
#define key_k3               0b00001011
#define key_k4               0b00000111
#define key_state_0        0
#define key_state_1        1
#define key_state_2        2

unsigned char read_key(void)              //按键扫描程序
{
        static unsigned char key_state = 0,key_old;
        unsigned char key_press,key_return = key_no;

        key_press = key_input;        // 读按键I/O电平
        switch (key_state)
        {
                case key_state_0:                                // 按键初始态
                        if (key_press != key_no)key_state = key_state_1;
                                          break;                                            // 键被按下,状态转换到键确认态
           case key_state_1:                    // 按键确认态  
            if (key_press == key_old)        // 与原电平比较(消抖处理)
            {  
                key_return = key_press;  
                key_state = key_state_2;        // 状态转换到判键释放态  
            }  
            else  
                key_state = key_state_0;        // 按键已抬起,转换到按键初始态(消抖)  
            break;
        case key_state_2:  
            if (key_press != key_old)
                key_state = key_state_0;        //按键已释放(或转按其它键),转换到按键初始态  
            break;
    }
    key_old = key_press;  
    return key_return;  
}

void light()  

    {    DDRA=0xff;                                    //PA0~7为输出状态
             PORTA=0x01;                                //PA0为输出低电平,而其余为高电平,亦即打亮LED0
    }
void lightt()  
    {    DDRA=0xff;                                    //PA0~7为输出状态
             PORTA=0x02;                                //PA1为输出低电平,而其余为高电平,亦即打亮LED1               
    }
void lights()  
    {    DDRA=0xff;                                    //PA0~7为输出状态
             PORTA=0x04;                                //PA2为输出低电平,而其余为高电平,亦即打亮LED2               
    }
void lightf()  
    {   DDRA=0xff;                                    //PA0~7为输出状态
            PORTA=0x08;                                   //PA3为输出低电平,而其余为高电平,亦即打亮LED3               
    }
void lightm()  
    {   DDRA=0xff;                                    //灭灯
            PORTA=0x00;                               
            PORTA=0x80;               
    }
void light5()  
    {   DDRA=0xff;                                  
            PORTA=0x10;                                          
    }
void light6()  
    {   DDRA=0xff;                                  
            PORTA=0x20;                                          
    }       

//电机程序
void turn()
       {
             while(1)
                 {
               uint i;
               delay(1);
               light();//******************第一台电机转动指示灯
                  for (i=0;i<100;i++)
               { MotorCW();//顺时针转动
                     }
                  delay(10);
                  MotorStop();  //停止转动
                  delay(10);
          for (i=0;i<100;i++)
               { MotorCCW();//逆时针转动
                     }
                  delay(10);
                  MotorStop();//停止转动
                  delay(1);       
                                  lightt();//****************第二台
                  for (i=0;i<100;i++)
              { MotorCW();//顺时针转动
                    }
                  delay(10);
                  MotorStop();  //停止转动
                  delay(10);
          for (i=0;i<100;i++)
              { MotorCCW();//逆时针转动
                   }
                  delay(10);
                  MotorStop();//停止转动
                  delay(1);               
                                  lights();//*******************第三台
                  for (i=0;i<100;i++)
              { MotorCW();//顺时针转动
                  }
                 delay(10);
                 MotorStop();  //停止转动
                 delay(10);
          for (i=0;i<100;i++)
              { MotorCCW();//逆时针转动
                 }
                 delay(10);
                 MotorStop();//停止转动
                 delay(1);       
                                 lightf();//*****************第四台
                  for (i=0;i<100;i++)
             { MotorCW();//顺时针转动
                 }
                 delay(10);
                 MotorStop();  //停止转动
                 delay(10);
          for (i=0;i<100;i++)
             { MotorCCW();//逆时针转动
                 }
                 delay(10);
                 MotorStop();//停止转动
                 delay(1);                                      
                             lightm();       
                                 delay(10);
                                 xianshi();
           }}

//数码管显示
void xianshi()
{
     
       uint i;
            
        for(i=0;i<20;i++)//显示20次,使整体看起来不闪烁
            {
         PORTC=table[num%10];
         delay(10);}
         if(PORTA=0x80)
                                num++;

}       

void main()
{
   unsigned char key_temp;
       
   while(1)
      {
        
        key_temp=   read_key();                  
     switch(key_temp )                  
        {
          case key_k1:
                   turn();xianshi();
                    break;
           case key_k2:MotorStop();light5();break;   
            }
                        delay(10);
      }
}
       
        帮忙看看呢 什么问题

出255入0汤圆

发表于 2013-4-24 11:41:44 | 显示全部楼层
jimmyfan 发表于 2013-4-24 10:49
#include "iom16v.h"
#include "macros.h"
#include                 //包含自定义常量头文件



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-4-24 12:30:54 | 显示全部楼层
天使之翼 发表于 2013-4-24 11:41

很感谢,下午调试调试

出0入0汤圆

发表于 2013-10-23 18:28:54 | 显示全部楼层
非常感谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 00:30

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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