[AVR单片机] AVR单片机键盘实验

[复制链接]
2190|9
 楼主| qingtianjushi 发表于 2014-5-2 22:51 | 显示全部楼层 |阅读模式
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 是个局部变量,返回就无效了。

 楼主| 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内部的上拉电阻有什么用处?
ningling_21 发表于 2014-5-3 12:36 | 显示全部楼层
qingtianjushi 发表于 2014-5-3 12:02
与全局变量还是局部变量没有关系,对于函数的返回值,我记得是这样:比如j=0x01 ,这个0x01应该是在常量区 ...

上拉电阻 使IO口在输入状态保持高电平...
 楼主| 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都钳制在高电平了。

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

在这次的程序中,我就用到了上拉电阻,明白了上拉电阻的用法,如果不开启上拉电阻,就会出现干扰,按键有时候会失灵
zhprotel 发表于 2014-5-3 17:25 | 显示全部楼层
前者为什么正常工作是因为
DDRD=0xF0;
PORTD=0X0F,已开起了D0~D3的内部上拉。
此时读引脚为高电平,按下按键则为低电平。
读按键还需要做防抖。另外用uint j浪费了一个字节。
有些朋友喜欢外加上拉,提高抗干扰能力。其实没有必要,别人设计芯片的时候就验证过了。
 楼主| 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;

有什么区别?
zhprotel 发表于 2014-5-4 23:08 | 显示全部楼层
qingtianjushi 发表于 2014-5-3 20:57
DDRD=0x0F;
PORTD=0x0F;

哎呀,DDRD=0X0F与DDRD=0XF0你自己看有什么区别,
另外增强干扰就不在罗嗦了。不加一样的读。你就玩玩就行。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

13

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部