jimmyfan 发表于 2013-4-23 21:22:50

用了状态机按键,但是按下去没反应

#include "iom16v.h"
#include "macros.h"
#include <AVR_PQ1A.h>                //包含自定义常量头文件
#define uchar unsigned char
#define uint unsigned int
unsigned charF_Rotation={0xF1,0xF2,0xF4,0xF8}; //正转表格,换算成二进制 0000 0001,0000 0010,0000 0100,0000 1000
unsigned charB_Rotation={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_mask      0b11110000            // 按键输入屏蔽码
#define key_no                0
#define key_k1                1
#define key_k2                2
#define key_k3                3
#define key_k4                4
#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_press;
      unsigned char key_return = key_no;

      key_press = key_input & key_mask;      // 读按键I/O电平
      switch (key_state)
      {
                case key_state_0:                              // 按键初始态
                        if (key_press != key_mask) key_state = key_state_1;      
                        break;                                          // 键被按下,状态转换到键确认态
                case key_state_1:                              // 按键确认态
                        if (key_press == (key_input & key_mask))
                        {
                              if (key_press == 0b01110000) key_return = key_k1;
                              else if (key_press == 0b10110000) key_return = key_k2;
                                     else if (key_press == 0b11010000) key_return = key_k3;
                                           else if (key_press == 0b11100000) key_return = key_k4;
                              key_state = key_state_2;      // 状态转换到键释放态
                        }
                        else
                              key_state = key_state_0;      // 按键已抬起,转换到按键初始态
                        break;
                case key_state_2:
                        if (key_press == key_mask) key_state = key_state_0;
                        break;                                                //按键已释放,转换到按键初始态
      }
         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;
         delay(10);}
         if(PORTA=0x80)
                                num++;

}       

void main()
{
   
        unsigned char key_value;
   
   key_value = read_key();                   //注意控制10-20ms执行一次.
   if (key_value != key_no)                  //判别键值并做相应的处理
   {
          switch (key_value)
         {
               case key_k1:
                   turn();xianshi();
                  break;
               case key_k2:
                   num=0;light5();
                   break;
               case key_k3:
                   MotorStop();light6();
                   break;
            }
      }
}
       
       

significance201 发表于 2013-4-23 21:23:56

感觉这样也不是很简洁哦

jimmyfan 发表于 2013-4-23 21:42:30

significance201 发表于 2013-4-23 21:23 static/image/common/back.gif
感觉这样也不是很简洁哦

现在不是简洁的问题,而是程序不能执行啊,急死了

significance201 发表于 2013-4-23 21:45:26

你调试一下哦,这个。。。
什么板子做的?

significance201 发表于 2013-4-23 21:47:31

看到了,AVR的,这个只能自己调试一下了,都写这么多代码了,先屏蔽部分,不重要的,然后再加上,我一般这么调试的,不知道是不是好方法?

jimmyfan 发表于 2013-4-23 21:47:33

significance201 发表于 2013-4-23 21:45 static/image/common/back.gif
你调试一下哦,这个。。。
什么板子做的?

自己焊的板子,弄了好多天了,按键互锁没任何进展,有什么好建议

gdjsfy_86 发表于 2013-4-23 21:49:16

jimmyfan 发表于 2013-4-23 21:42 static/image/common/back.gif
现在不是简洁的问题,而是程序不能执行啊,急死了

个人看法:主程序连个WHILE 都没有   ,按键状态机用中断更好一点吧

jimmyfan 发表于 2013-4-23 21:54:00

gdjsfy_86 发表于 2013-4-23 21:49 static/image/common/back.gif
个人看法:主程序连个WHILE 都没有   ,按键状态机用中断更好一点吧

while(1)加了之后直接执行程序,中断不会啊,刚接触AVR一个月,中断怎么用?

jimmyfan 发表于 2013-4-23 21:58:43

gdjsfy_86 发表于 2013-4-23 21:49 static/image/common/back.gif
个人看法:主程序连个WHILE 都没有   ,按键状态机用中断更好一点吧

这是我弄得另一种按键,按下去能运行,但是在键1按下后按下键2不能运行,怎么改,不甚感激
#include "iom16v.h"
#include "macros.h"
#include <AVR_PQ1A.h>                //包含自定义常量头文件
#define uchar unsigned char
#define uint unsigned int
unsigned charF_Rotation={0xF1,0xF2,0xF4,0xF8}; //正转表格,换算成二进制 0000 0001,0000 0010,0000 0100,0000 1000
unsigned charB_Rotation={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;//输出对应的相 可以自行换成反转表格
          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;
}
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()
       {
             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;
         delay(10);}
         if(PORTA=0x80)
                                num++;

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

gdjsfy_86 发表于 2013-4-23 21:59:53

本帖最后由 gdjsfy_86 于 2013-4-23 22:00 编辑

jimmyfan 发表于 2013-4-23 21:54 static/image/common/back.gif
while(1)加了之后直接执行程序,中断不会啊,刚接触AVR一个月,中断怎么用? ...

你这样写 状态机只执行了一次 ,怎么可能判断出按键呢   不会用中断的话可以这样写 :
while(1)
{
       readkey();
       switch()
       {

       }
       delay_10ms;
}
这样写的话,CPU利用不高   
会用中断的话 可以这样写:
while(1)
{
    if(flag_10MS==1)//在10ms定时中断中置位此标志
    {
          flag_10MS=0;
          readkey();
          switch()
          {}
    }
}


jimmyfan 发表于 2013-4-23 22:02:31

gdjsfy_86 发表于 2013-4-23 21:59 static/image/common/back.gif
你这样写 状态机只执行了一次 ,怎么可能判断出按键呢   不会用中断的话可以这样写 :
while(1)
{


恩,我先试试

jimmyfan 发表于 2013-4-23 22:06:56

gdjsfy_86 发表于 2013-4-23 21:59 static/image/common/back.gif
你这样写 状态机只执行了一次 ,怎么可能判断出按键呢   不会用中断的话可以这样写 :
while(1)
{


void main()
{
   
       
   while(1)
      {
      unsigned char key_temp;
      key_temp=   read_key();                  
   switch(key_temp )                  
      {
          case key_k1:
                   turn();xianshi();
                  break;
         case key_k2:MotorStop();light5();break;   
            }
                        delay(10);
      }
}
是这样吗?

gdjsfy_86 发表于 2013-4-23 22:09:29

jimmyfan 发表于 2013-4-23 22:06 static/image/common/back.gif
void main()
{
   


变量定义放在WHILE外面

jimmyfan 发表于 2013-4-23 22:13:02

gdjsfy_86 发表于 2013-4-23 22:09 static/image/common/back.gif
变量定义放在WHILE外面



是这样吧,还是按键没反应

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);
      }
}
页: [1]
查看完整版本: 用了状态机按键,但是按下去没反应