打印
[AVR单片机]

请大神帮帮忙,如何储存按键值?

[复制链接]
1733|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
行者大洁|  楼主 | 2014-12-21 18:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚学AVR,做一个按键判断好多天了,大脑越来越乱,求大神们给小弟指点迷津。
我现在在写这么一个程序,我有四个按键,按下A、B、C,每按一次加一次把按键值储存起来,
按下D,则开始运行主程序,再按下D则跳出主程序。对中断表示无法理解怎么用,找资料折腾出了按键判断和键值返回,后面就不知道怎么才能把按键值可以存起来,怎样才能按下KEY4就能随意进出主程序,还请大神给帮帮忙啊,万分感谢。做广告培训班的就别留言了,苦逼小屌丝没钱只能自学。我的代码如下
#include <iom8v.h>
#include <macros.h>
#define  uchar unsigned char
#define  uint unsigned int
#pragma data:code
uchar u,p,m;
flash  table[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff};
void delay(uint ms)
{          
          uint k,j;
          for(k=0;k<ms;k++)
          {
          for(j=0;j<11;j++);
          }
}
uchar key_scan()
{
          uchar key;
          delay(5);
          if(key_press())
          {
          key=PINC;
          key&=0x0f;
          switch(key)
           {
                   case 0X0e:
                key=3;
                break;
                case 0x0d:
                key=4;
               
                break;
                case 0x0b:
                key=2;
                break;
                case 0x07:
                key=1;
                break;
                default:        
                key=5;
               
           }
        while(key_press());
        delay(10);
         }
         else
         {
                  key=5;
               
         }
         return key;
         }

uchar key_press()
{
     uchar i;
     DDRC|=0X0F;
     PORTC|=0X0F;
     DDRC&=0XF0;
         i=PINC;
         i&=0X0F;
     if(i==0X0F)
       return 0;
     else
       return 1;
}
//uchar key_store()       
//{
//     if(key==4)
//         if(key_press())
//       u++;
         
         
//}
void show(uint h)
{
         PORTD=0xff;
         PORTC&=0xe0;
         PORTD=table[h];
         delay(1);
         PORTC|=0x10;
         PORTC&=0xd0;
         PORTD=table[h];
         delay(1);
         PORTC|=0x20;
}
void main()
{
         DDRD=0Xff;
         PORTD=0x7e;
         DDRC=0xf0;
         PORTC=0xff;
         //u=key_store;
         key_press();
         m=key_scan();
         while(m==4)
         {
         m=key_scan();
         if(m==4)
         {
         PORTD=0x7d;
         delay(5000);
         }
         PORTD=0x7e;
         delay(5000);
         }
         
}

相关帖子

沙发
wangch_sh| | 2014-12-22 08:58 | 只看该作者
你存键值干嘛?键值还用存吗?

使用特权

评论回复
板凳
airwill| | 2014-12-22 19:28 | 只看该作者
看来真是个新人, 我觉得在自己写程序之前, 有必要先看看人家的程序. 学习一下人家的思路, 网上应该不乏例程和开发板资料, 去搜一点学习学习, 再说你的按键处理, 其实是个状态机问题, 有按键后就进行状态变换罢了. 那么就只要做判断, 晚了, 这个按键也就没有作用了, 丢弃了. 保存它干吗呢

使用特权

评论回复
地板
行者大洁|  楼主 | 2014-12-22 23:37 | 只看该作者
wangch_sh 发表于 2014-12-22 08:58
你存键值干嘛?键值还用存吗?

有用啊,按键比如加到100,就存到EEPOM,等下次开机就默认为那个键值啦。

使用特权

评论回复
5
行者大洁|  楼主 | 2014-12-22 23:41 | 只看该作者
airwill 发表于 2014-12-22 19:28
看来真是个新人, 我觉得在自己写程序之前, 有必要先看看人家的程序. 学习一下人家的思路, 网上应该不乏例程 ...

斑竹,我这个程序有个缺点就是按键不能实时扫描,听说可以放中断几ms去扫一次,能不能解释下怎么才能具体通过中断实现这个几ms扫描一次按键啊。我觉的吧我是要多看看,但是每次看了没用,忘的快,也不知道所云,索性边实战边学习,不然没法进步啊~

使用特权

评论回复
6
wangch_sh| | 2014-12-23 08:10 | 只看该作者
AVR内部带不带EEPROM,不带的话,外挂EEPROM。

使用特权

评论回复
7
qin552011373| | 2014-12-23 09:39 | 只看该作者
简直是乱来,你扫描按键的思路是什么?

默认按键返回值5.永远进不了主循环。

使用特权

评论回复
8
airwill| | 2014-12-23 18:31 | 只看该作者
中断扫描, 可以使用定时器的中断, 在中断服务里循环扫描检测按键, 那就要个变量供中断告知主循环按键是否有效和键值. 一般一个全局变量可以完成.
怎么才能具体通过中断实现这个几ms扫描一次按键啊。把定时溢出时间设置成你要扫描的周期的就是了.

使用特权

评论回复
9
行者大洁|  楼主 | 2014-12-23 20:48 | 只看该作者
wangch_sh 发表于 2014-12-23 08:10
AVR内部带不带EEPROM,不带的话,外挂EEPROM。

AVR有自带哦  至于外挂  好像都木有听说过

使用特权

评论回复
10
行者大洁|  楼主 | 2014-12-23 20:53 | 只看该作者
qin552011373 发表于 2014-12-23 09:39
简直是乱来,你扫描按键的思路是什么?

默认按键返回值5.永远进不了主循环。 ...

起初没有考虑到按键再循环扫描时,原来的按键就不存在了。。
现在想想真是太糊涂了,我验证了下确实一直都是KEY==5。。。

使用特权

评论回复
11
行者大洁|  楼主 | 2014-12-23 20:56 | 只看该作者
airwill 发表于 2014-12-23 18:31
中断扫描, 可以使用定时器的中断, 在中断服务里循环扫描检测按键, 那就要个变量供中断告知主循环按键是否有 ...

明白了一点,怎么设置寄存器和定时中断还得好好看看,设定时间的话,我AVR的芯片是不是要先写熔丝位把晶振设置为内部的,才能精确计时啊,我现在没有写熔丝位,程序貌似也能执行哦,我都没外接晶振

使用特权

评论回复
12
airwill| | 2014-12-23 21:19 | 只看该作者
通常, 不设定, 默认是内部振荡器, 所以没有晶体也可以工作, 但内部振荡器的频率精度差一点.

使用特权

评论回复
13
行者大洁|  楼主 | 2014-12-23 21:35 | 只看该作者
airwill 发表于 2014-12-23 21:19
通常, 不设定, 默认是内部振荡器, 所以没有晶体也可以工作, 但内部振荡器的频率精度差一点.  ...

好吧,终于理清点思路了,也感谢为我这等小白详细解答,我继续研究研究了~

使用特权

评论回复
14
行者大洁|  楼主 | 2014-12-25 23:47 | 只看该作者
airwill 发表于 2014-12-23 21:19
通常, 不设定, 默认是内部振荡器, 所以没有晶体也可以工作, 但内部振荡器的频率精度差一点.  ...

斑竹,麻烦再帮我看个问题,我在练习中断,死活都进不去,搞三天了,救救我吧,代码如下,能帮我看下到底哪里有问题吗?万分感谢
//#include <eeprom.h>
#include <iom8v.h>
#include <macros.h>
#define  uchar unsigned char
#define  uint unsigned int
uchar p=40;
#pragma data:code
#pragma interrupt_handler miao:iv_TIMER1_OVF
uchar u,m;
flash  table[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff};
void delay(uint ms)
{          
          uint k,j;
          for(k=0;k<ms;k++)
          {
          for(j=0;j<11;j++);
          }
}
uchar key_scan()
{
          uchar key;
          delay(5);
          if(key_press())
          {
          key=PINC;
          key&=0x0f;
          switch(key)
           {
                   case 0X0e:
                key=3;
                break;
                case 0x0d:
                key=4;
                u=~u;
               
                break;
                case 0x0b:
                key=2;
                break;
                case 0x07:
                key=1;
                break;
                default:        
                key=5;
               
           }
        while(key_press());
        delay(10);
         }
         else
         {
                  key=5;
               
         }
         return key;
         }

uchar key_press()
{
     uchar i;
     DDRC|=0X0F;
     PORTC|=0X0F;
     DDRC&=0XF0;
         i=PINC;
         i&=0X0F;
     if(i==0X0F)
       return 0;
     else
       return 1;
}
void show(uchar j)
{
    PORTC&=~BIT(4);
    PORTD=table[j/10];//蔳e 位
    PORTC|=BIT(4);
        delay(100);
   PORTC&=~BIT(5);
   PORTD=table[j%10];//shi位
   PORTC|=BIT(5);
   delay(100);
}

void miao()
{
    // if(p==60)
        // {
         p=0;
        // }
     p++;
         PORTD=0X7e;
        delay(100);
       
    TCNT1H=0X40;
    TCNT1L=0Xe0;
       
}       
   

//void show(uint h)
//{
//         PORTD=0xff;
        // PORTC&=0xe0;
        // PORTD=table[h];
        // delay(1);
        // PORTC|=0x10;
        // PORTC&=0xd0;
        // PORTD=table[h];
        // delay(1);
        // PORTC|=0x20;
//}
void main()
{   
     CLI();
         DDRD=0Xff;
         PORTD=0x8e;
         DDRC=0xf0;
         PORTC=0xff;
         u=0xff;
         TCCR1B=0X40;
         TCNT1H=0X85;
     TCNT1L=0XED;
     TIMSK=0x04;
     SREG=0x80;
         SEI();
       
         while(1)
         {;
         //key_press();
         //key_scan();
        // if(u==0)
        // {
        // show(p);
        // delay(5);
        // }
        // else
        // {
        // PORTD=0X8e;
        // }
         }
         
}

使用特权

评论回复
15
airwill| | 2014-12-26 00:46 | 只看该作者
哦, 要睡觉了, 才看到有消息.
你的 MCU 是 MEGA8 吧, 从手册看
TCCR1B=0X40;
不是关闭了定时器的时钟了, 哪里还能进入中断?

使用特权

评论回复
16
行者大洁|  楼主 | 2014-12-26 21:26 | 只看该作者
airwill 发表于 2014-12-26 00:46
哦, 要睡觉了, 才看到有消息.
你的 MCU 是 MEGA8 吧, 从手册看
TCCR1B=0X40;

太感谢了,我高低位弄错了,谢谢啊,斑竹大神!太开新了,一下子解决了我好几天的困惑。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

13

帖子

0

粉丝