打印
[AVR单片机]

求助,端口复用问题!!!

[复制链接]
4391|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
areshan|  楼主 | 2010-10-19 10:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
hot大叔,AVR的端口能否输入输出复用,我手上一个产品用的是AVR8,想加两个按键,可是都用完了,现在想把两个按键和LED灯共用。。。。LED灯是输出管脚,按键是输入管脚。我是在中断里检测按键,初始化程序是把那两个复用的管脚设为输出,在中断检测按键时,在设置成输入。我试过,要是有按键被检测到,那么其他的数码管就不能点亮了。。。。。。。附上部分程序:
void io_init(void)
{
DDRC|=(1<<PC0)|(1<<PC1)|(1<<PC3);//把cs,sdi,sclk管脚连接的io口设为输出
DDRC&=~(1<<PC2);//把SDO管脚连接的IO设为输入
PORTC|=(1<<PC2);//打开PC2的上拉电阻
DDRD|=(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);//数码管片选
DDRB=0XFF;//数码管
DDRD|=(1<<PD0)|(1<<PD1);//LED
DDRC|=(1<<PC4)|(1<<PC5); //LED
DDRD&=~(1<<PD2);//按键设为输入
PORTD|=(1<<PD2);//按键开上拉
PORTB=0XFF;
PORTC=0XFF;
PORTD=0XFF;
}

void led_light(uchar led)
{
if(led==1)
{
   PORTC&=~(1<<PC5);//点亮右1
   PORTC|=(1<<PC4);//熄灭右2
   PORTD|=(1<<PD1);//熄灭右3
   PORTD|=(1<<PD0);//熄灭右4
   }
else if(led==2)
  {
   PORTC|=(1<<PC5);
   PORTC&=~(1<<PC4);
   PORTD|=(1<<PD1);
   PORTD|=(1<<PD0);
   }
else if(led==3)
  {
   PORTC=(1<<PC5);
   PORTC|=(1<<PC4);
   PORTD&=~(1<<PD1);
   PORTD|=(1<<PD0);
   }
else if(led==4)  
  {
   PORTC|=(1<<PC5);
   PORTC|=(1<<PC4);
   PORTD|=(1<<PD1);
   PORTD&=~(1<<PD0);
   }
else
{
   PORTC|=(1<<PC5);
   PORTC|=(1<<PC4);
   PORTD|=(1<<PD1);
   PORTD|=(1<<PD0);
   }
}

/******中断是50ms*****/
#pragma interrupt_handler clock2:4
void clock2(void)
{
DDRC&=~((1<<PC4)|(1<<PC5)); //设置为输入管脚检查按键,复用的两个按键
NOP();
NOP();
NOP();
if(key1_status==KEY_OFF)//判断按键1的状态,KEY_OFF=1,KEY_ON=0
     {
      if((!(PIND&(1<<PD2))))//如果按键被按下
        key1_status=KEY_ON;
   else key1_status=KEY_OFF;
           }
else
     {
   if((!(PIND&(1<<PD2))))//如果按键被再次按下
         {
     key_count++;
    //key_check++;
     }
    key1_status=KEY_OFF;
    }
if(key2_status==KEY_OFF)//判断按键1的状态
     {
      if((!(PINC&(1<<PC4))))//如果按键被按下
        key2_status=KEY_ON;
   else key2_status=KEY_OFF;
           }
else
     {
   if(!(PINC&(1<<PC4)))//如果按键被再次按下
         { //按键被按下
     //key_count++;
    key_check++;
     }
    key1_status=KEY_OFF;
    }  
NOP();
NOP();
NOP();
if(key3_status==KEY_OFF)//判断按键1的状态
     {
      if((!(PINC&(1<<PC5))))//如果按键被按下
        key2_status=KEY_ON;
   else key2_status=KEY_OFF;
           }
else
     {
   if((!(PINC&(1<<PC5))))//如果按键被再次按下
         {//按键被按下
     //key_count++;
    key_check++;
     }
    key1_status=KEY_OFF;
    }
*/
io_init();//管脚再次初始化,以前直接是DDRC|=(1<<PC4)|(1<<PC5)
if(key_count==5) key_count=1;
//if(key_check==10) key_check=0;
led_light(key_count);
NOP();
}
大叔帮忙看看,我都快不行了。。。。。输入和输出到底该怎么复用呢????

相关帖子

沙发
areshan|  楼主 | 2010-10-19 10:25 | 只看该作者
我的想法是在中断里面改变IO管脚的方向,在判断 ,这样不会把LED灯的变化误认为是按键的变化了,可是这样其他的2个LED等却不亮了。。。。。。。。让我很迷惑,我在显示LED灯的函数里都是有“|,&”的符号根本没有改变其它管脚的状态,而且更没有改变其它管脚的DDR寄存器!!!

使用特权

评论回复
板凳
zhaoyu2005| | 2010-10-19 17:47 | 只看该作者
如果能改板子,用2片595级联驱动4个数码管和4个灯,只需3根线,剩下的口可以接按键

如果想按照你上面的想法改,可以这样试试:
使用灯的驱动口作为按键的输入,在灯灭时切换为输入,检测是否有按键按下,有的话记录,灯该亮时仍旧将灯点亮,灭时再检测,连续检测几次,确认按键是否有效,有效就执行按键程序,无效继续检测
灯需要动态显示

使用特权

评论回复
地板
NE5532| | 2010-10-19 19:39 | 只看该作者
把电路图发上来瞧瞧呢。程序是小事,关键是方案做对了没。

使用特权

评论回复
5
zyp898989| | 2010-10-20 16:56 | 只看该作者
可以的,网上有按键指示灯(数码管)一起控制的例程,就是扫描方式工作

使用特权

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

本版积分规则

127

主题

728

帖子

0

粉丝