打印
[AVR单片机]

AVR单片机键盘实验

[复制链接]
1746|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
unsigned int KeyBoard()
{
   unsigned int j;
   DDRD=0x0f;
   PORTD=0x0f;
   
   DDRD=0xF0;
   j=PIND;
   j&=0x0F;
   return j;   
}
以上程序可以正常运行。

下面这个就不能正常运行了,为什么呢?DDRD设置为输入,然后读取PIND,不就能得到外部引脚的电平吗?为什么得不到呢?
unsigned int KeyBoard()
{
   unsigned int j;
   //DDRD=0x0f;
   //PORTD=0x0f;   
   DDRD=0xF0;   
   j=PIND;
   j&=0x0F;
   return j;   
}

相关帖子

沙发
ningling_21| | 2014-5-3 08:40 | 只看该作者
下面这个就不能正常运行了

是怎么个不正常?

使用特权

评论回复
板凳
qingtianjushi|  楼主 | 2014-5-3 11:09 | 只看该作者
本帖最后由 qingtianjushi 于 2014-5-3 11:11 编辑
ningling_21 发表于 2014-5-3 08:40
下面这个就不能正常运行了

是怎么个不正常?

下面是原理图,接了四个独立按键,按键接地。按键按下的时候PINDx应该是低电平吧。
程序:
if(j==0X0E)                                    
  LedDisplay(1);
                        
if(j==0X0d)
  LedDisplay(2);
                  
if(j==0X0b)
  LedDisplay(3);

if(j==0X07)
  LedDisplay(4);

这段程序就不能正常运行


使用特权

评论回复
地板
ningling_21| | 2014-5-3 11:37 | 只看该作者
本帖最后由 ningling_21 于 2014-5-3 11:40 编辑
qingtianjushi 发表于 2014-5-3 11:09
下面是原理图,接了四个独立按键,按键接地。按键按下的时候PINDx应该是低电平吧。
程序:
if(j==0X0E)    ...

改一下试试

if(j==0X0E)                                    
  LedDisplay(1);
                        
else if(j==0X0d)
  LedDisplay(2);
                  
else if(j==0X0b)
  LedDisplay(3);

else if(j==0X07)
  LedDisplay(4);


j 是个局部变量,返回就无效了。

使用特权

评论回复
5
qingtianjushi|  楼主 | 2014-5-3 12:02 | 只看该作者
ningling_21 发表于 2014-5-3 11:37
改一下试试

if(j==0X0E)                                    

与全局变量还是局部变量没有关系,对于函数的返回值,我记得是这样:比如j=0x01 ,这个0x01应该是在常量区的,返回的时候返回的是常量的地址,所以不存在返回值无效的情况。我记得的不是很清楚了。但函数返回一个值,是可行的,这个我确定。

对于IF选择上也没有关系,没有记得if () if ()  和if () else if()有太大的区别。

我刚才又把程序改了一下:
   DDRD=0x0f;
   PORTD=0x0f;
   delay(1);
   key=PIND;
   key&=0x0F;
   return key;  

这样都可以读到正常的PIND值,为什么DDRD=0x0f ,PORTD=0x0f .都是输出了,不是输入了,都可以正常读到。问你另外一个问题:对于这个按键,AVR Mega16内部的上拉电阻有什么用处?

使用特权

评论回复
6
ningling_21| | 2014-5-3 12:36 | 只看该作者
qingtianjushi 发表于 2014-5-3 12:02
与全局变量还是局部变量没有关系,对于函数的返回值,我记得是这样:比如j=0x01 ,这个0x01应该是在常量区 ...

上拉电阻 使IO口在输入状态保持高电平...

使用特权

评论回复
7
qingtianjushi|  楼主 | 2014-5-3 16:55 | 只看该作者
ningling_21 发表于 2014-5-3 12:36
上拉电阻 使IO口在输入状态保持高电平...

问题差不多解决了, 是因为干扰的问题。把程序改为下面这样就OK了
while(1)
  {
  DDRD=0xf0;
  PORTD=0x0f;
   delay(1);
   key=PIND&0x01;
   key2=PIND&0x02;
   key3=PIND&0x04;
   key4=PIND&0x08;

    if(key==0)   
           LedDisplay(1);          
    else if(key2==0)   
           LedDisplay(2);
    else if(key3==0)   
           LedDisplay(3);
    else if(key4==0)   
           LedDisplay(4);
        else
           LedDisplay(0);          
  }

以前的程序是一次判断四位,比如if(key==0x0E),这样判断不好,因为其余的IO口,即使在按键没有按下的情况下,也有可能是低电平,即使使用了内部上拉电阻。所以说DDRD=0x00,PORTD=0xff,是可行的,因为这样就把PORTD都钳制在高电平了。

所以把程序改为每次判断一位,这样就好多了,不会因为其余的端口干扰,而影响判断。

在这次的程序中,我就用到了上拉电阻,明白了上拉电阻的用法,如果不开启上拉电阻,就会出现干扰,按键有时候会失灵

使用特权

评论回复
8
zhprotel| | 2014-5-3 17:25 | 只看该作者
前者为什么正常工作是因为
DDRD=0xF0;
PORTD=0X0F,已开起了D0~D3的内部上拉。
此时读引脚为高电平,按下按键则为低电平。
读按键还需要做防抖。另外用uint j浪费了一个字节。
有些朋友喜欢外加上拉,提高抗干扰能力。其实没有必要,别人设计芯片的时候就验证过了。

使用特权

评论回复
9
qingtianjushi|  楼主 | 2014-5-3 20:57 | 只看该作者
zhprotel 发表于 2014-5-3 17:25
前者为什么正常工作是因为
DDRD=0xF0;
PORTD=0X0F,已开起了D0~D3的内部上拉。

DDRD=0x0F;
PORTD=0x0F;

然后读取PIND的值,四个独立键全部接地的,这个时候按键的时候,不也能读取低电平吗?我试验了,是可行的。与

DDRD=0xF0;
PORTD=0x0F;

有什么区别?

使用特权

评论回复
10
zhprotel| | 2014-5-4 23:08 | 只看该作者
qingtianjushi 发表于 2014-5-3 20:57
DDRD=0x0F;
PORTD=0x0F;

哎呀,DDRD=0X0F与DDRD=0XF0你自己看有什么区别,
另外增强干扰就不在罗嗦了。不加一样的读。你就玩玩就行。

使用特权

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

本版积分规则

6

主题

13

帖子

0

粉丝