foxpro2005 发表于 2012-10-31 21:41:30

关于傻孩子书中 “中断唤醒的键盘扫描” (P109)只能唤...

傻孩子大侠书中【实例七】中断唤醒的键盘扫描,P109页,说到“这个实例还有一个遗留的问题需要大家注意:如果去掉中断服务函数中“PCMSK1&=(~((1<<PCINT11)|(1<<PCINT10)|(1<<PCINT9)));”一句,键盘将只能被唤醒1次。据说DA895在这个问题上找了半天,在这里我们不打算详细分析,把这个问题留给读者思考。”

pragma interrupt_handler pcint1_isr: iv_PCINT1
void pcint1_isr(void)                                    //引脚电平变化中断PCINT1中断服务函数
{
    SMCR&=0xFE;                                          //禁止休眠功能,以免误触发
    //PCMSK1&=(~((1<<PCINT11)|(1<<PCINT10)|(1<<PCINT9)));//禁止引脚电平变化中断,以免影响键盘扫描程序的运行 (把这一行注释掉)
    PCICR&=(~(1<<PCIE1));
}

void main (void)
{
    unsigned char KeyValue=NoKey;
    unsigned int SleepTimer=0;

    DDRC=0xF1;                  //将键盘的"行"设置为输出,键盘的"列"设置为输入并开启了输入端的内部上拉电阻
    DDRB=0xFF;
    DDRD=0xFF;
    PORTC=0xFF;
    PORTB=0xFF;
    PORTD=0xFF;

    SEI();                     //允许全局中断

    LedDisPort=DisTab;      //上电后初始化显示"0"

    while(1)
    {
      KeyValue=Key_Scan_Ant_Dither();
      if (KeyValue!=NoKey)                                          //当有按键按下时,显示该键的键值
            {
                LedDisPort=DisTab;
                SleepTimer=0;                                           //并清0休眠计时器
            }
      else                                                            //当没有按键按下时,计算连续未操作的时间
            {
                SleepTimer++;                                           //休眠计时器自加以实现计时
                if (SleepTimer >= 1500)                                  //当连续3秒钟(近似值)没有按任何按键时,将进入休眠状态
                {
                  SleepTimer=0;                                       //清0休眠计时器,以便唤醒后继续计时
                  PORTC=0b11001111;                                 //将键盘的行(PC5,PC4)设置为输出"0"状态
                  PORTD=0x00;                                       //关闭数码管显示驱动以节省电能
                  PCMSK1|=((1<<PCINT11)|(1<<PCINT10)|(1<<PCINT9));    //使能PCINT9..11
                  PCICR|=(1<<PCIE1);                                  //使能第一组引脚电平变化中断
                  SMCR=0x05;                                          //设置掉电状态并使能休眠功能
                  asm("SLEEP");                                       //休眠单片机,进入掉电状态
                  PORTC=0xFF;                                                                                        //休眠唤醒后将PC端口重置回初始化状态
                }
            }                                        //End Of Else
    }                                                        //End Of While
}

键盘只能唤醒一次?我感觉有点疑问:
1. 在第一次中断唤醒后,虽然PCMSK1中的电平变化中断没有被屏蔽掉,但是在 PCICR&=(~(1<<PCIE1)) 后, PCIE1(PCINT8-14端口的总开关)是掉的,故即使唤醒后的,键盘操作(PC1,PC2,PC3输入)或端口(PORT PC4,PC5输出变化)引起的电平也不会使得再次进入电平变化中断服务程序。

除非把 PCICR&=(~(1<<PCIE1));也去掉,每次按键或PORTC的电平变化都将引起中断,从而影响程序的正常运行而已。

2.我在Protues中仿真试过,后续唤醒仍然是有效的。(并不是只能唤醒一次)

foxpro2005 发表于 2012-10-31 22:07:24

现在都没有人讨论AVR啦 ?

Gorgon_Meducer 发表于 2012-11-1 10:27:12

不要相信protues

foxpro2005 发表于 2012-11-1 10:30:32

本帖最后由 foxpro2005 于 2012-11-1 10:36 编辑

谢谢傻孩子大侠 即时回复。
但我想后续应该也还是可以唤醒的啊。因为PCICR&=(~(1<<PCIE1)),PCIE1是屏蔽掉的。
我还是没有想通,只能唤醒一次,后续无法再唤醒。
页: [1]
查看完整版本: 关于傻孩子书中 “中断唤醒的键盘扫描” (P109)只能唤...