发新帖我要提问
12
返回列表
打印

PIC16F886支持中断嵌套吗?

[复制链接]
楼主: busdriver
手机看帖
扫描二维码
随时随地手机跟帖
21
busdriver|  楼主 | 2010-11-11 11:24 | 只看该作者 回帖奖励 |倒序浏览
按键消抖程序
1.按键扫描程序
void key_scan(void)
{
        if(step == 0)//in the step of key scanning
        {
                //key scanning
                if(FOUT_ON_OFF != on_off_flag)//if key FOUT_ON_OFF change
                        step = 1;//enter the step of delay
          else if(LED_SWITCH != led_switch_flag)//if key LED_SWITCH change
                        step = 1;//enter the step of delay
                else if(!FOUT_UP)//if key FOUT_UP touch
                        step = 1;//enter the step of delay
                else if(!FOUT_DOWN)
                        step = 1;//enter the step of delay
        }
        else if(step == 1)//in the step of delay
        {
                if(key_timer == 2)//delay timeout
                {
                        step = 0;//reset to the step of key scanning
                       
                        //get key value
                        if(FOUT_ON_OFF != on_off_flag)//if key FOUT_ON_OFF change
                        {
                                of_off_flag = FOUT_ON_OFF;
                                key_change = 1;//set key change flag                               
                        }
                  else if(LED_SWITCH != led_switch_flag)//if key LED_SWITCH change
                        {
                                led_switch_flag = LED_SWITCH;                               
                                key_change = 1;//set key change flag
                        }                         
                  else if(FOUT_UP == 0)//if key FOUT_UP touch
                  {
                                fout_up_flag = 0;                         
                                key_change = 1;//set key change flag
                  }
                        else if(FOUT_DOWN == 0)
                        {
                                fout_down_flag = 0;  
                                key_change = 1;//set key change flag                                       
                        }
                }
        }
}

2.timer 中断延时程序
                if(step == 0)//in the step of key scanning
                {
                        key_timer = 0;//reset key timer
                }
                else if(step == 1)//in the step of delay
                {
                        key_timer++;//key timet +1
                }

帮忙看看这样消抖有问题吗?

最短延时10ms,最长取决于主循环时间。

使用特权

评论回复
22
busdriver|  楼主 | 2010-11-11 11:25 | 只看该作者
说明,此四键不会同时被按下,否则一个step变量处理不过来。谢谢

使用特权

评论回复
23
busdriver|  楼主 | 2010-11-11 14:32 | 只看该作者
本帖最后由 busdriver 于 2010-11-12 16:59 编辑

1.按键扫描程序:
void key_scan(void)
{
if(key_step == 0)//in the step of key scanning
{
  //key scanning
  if(FOUT_ON_OFF != on_off_status)//if key FOUT_ON_OFF change
   key_step = 1;//enter the step of delay
   else if(LED_SWITCH != led_switch_status)//if key LED_SWITCH change
   key_step = 1;//enter the step of delay
  else if(!FOUT_UP)//if key FOUT_UP touch
   key_step = 1;//enter the step of delay
  else if(!FOUT_DOWN)
   key_step = 1;//enter the step of delay
}
else if(key_step == 1)//in the step of delay
{
  if(key_timer == 2)//delay timeout
  {
   key_step = 0;//reset to the step of key scanning
   
   //get key value
   if(FOUT_ON_OFF != on_off_status)//if key FOUT_ON_OFF change
   {
    key_val = KEY_ON_OFF;
    //on_off_swap = 1;//set ON/OFF swap flag
    on_off_status = ~on_off_status;//flip
    key_change = 1;//set key change flag   
   }
    else if(LED_SWITCH != led_switch_status)//if key LED_SWITCH change
   {
    key_val = KEY_LED_SWITCH;
    //led_switch_swap = 1;//set LED_SWITCH flag
    led_switch_status = ~led_switch_status;//flip   
    key_change = 1;//set key change flag
   }     
    else if(FOUT_UP == 0)//if key FOUT_UP touch
    {
    if(!on_off_status)//if ON,or else no actions
    {
     up_down_active = 1;   
     key_val = KEY_UP;
     //fout_up_flag = 0;     
     key_change = 1;//set key change flag   
    }
    }
   else if(FOUT_DOWN == 0)
   {
    if(!on_off_status)//if ON,or else no actions
    {
     up_down_active = 1;
     key_val = KEY_DOWN;
     //fout_down_flag = 0;  
     key_change = 1;//set key change flag      
    }   
   }
  }
}
}
/***********************************************************************
Name:key_action(data)
Function:key action routine
Input:none
Output:none
************************************************************************/
void key_action(void)
{
//unsigned char *set_EN_CLKout
unsigned char i;
//unsigned char SET_CLKout_DIV;
switch(key_val)
{
  case KEY_ON_OFF:
  {
   if(!on_off_status)//ON
   {
    lmk04031_set_word = SET_EN_CLKout;//LMK04031 set word
    lmk04031_set_flag = 1;
     
    led_decode(led,*fout);
    led_display(led);//refresh LEDs     
   }
   else if(on_off_status)//OFF
   {
    lmk04031_set_word = RESET_EN_CLKout;//LMK04031 set word
    lmk04031_set_flag = 1;
   
    for(i=0;i<=4;i++)
    {
     led=10;
    }
    led_display(led);//all off   
    }   
    break;
  }
  case KEY_LED_SWITCH:
  {
   if(led_switch_status)//channel 0
   {
    //set_EN_CLKout = &SET_EN_CLKout0
    SET_CLKout_DIV = SET_CLKout0_DIV;
    CLKout_DIV = &CLKout0_DIV;
    fout = &fout0;
   }
   else if(!led_switch_status)//channel 3
   {
    //set_EN_CLKout = &SET_EN_CLKout3
    SET_CLKout_DIV = SET_CLKout3_DIV;  
    CLKout_DIV = &CLKout3_DIV;
    fout = &fout3;
   }
   break;
  }
  case KEY_UP:
  {
   if(*CLKout_DIV == 32)
    *CLKout_DIV = 1;
   else if((*CLKout_DIV == 12) || (*CLKout_DIV == 16) || (*CLKout_DIV == 20))
    *CLKout_DIV += 4;
   else if(*CLKout_DIV == 24)
    *CLKout_DIV += 6;
   else
    *CLKout_DIV += 2;
   
   lmk04031_set_word = SET_CLKout_DIV;//LMK04031 set word
   lmk04031_set_flag = 1;
   
   //led_decode(led,*fout);
   //led_display(led);//refresh LEDs   
   break;
  }
  case KEY_DOWN:
  {
   if(*CLKout_DIV == 1)
    *CLKout_DIV = 32;
   else if((*CLKout_DIV == 16) || (*CLKout_DIV == 20) || (*CLKout_DIV == 24))
    *CLKout_DIV -= 4;
   else if(*CLKout_DIV == 30)
    *CLKout_DIV -= 6;
   else
    *CLKout_DIV -= 2;
   
   lmk04031_set_word = SET_CLKout_DIV;//LMK04031 set word
   lmk04031_set_flag = 1;  
   
   //led_decode(led,*fout);
   //led_display(led);//refresh LEDs   
   break;
  }   
  default:
   break;
}
}

2.中断程序
if(key_step == 0)//in the step of key scanning
  {
   key_timer = 0;//reset key timer
  }
  else if(key_step == 1)//in the step of delay
  {
   key_timer++;//key timet +1
  }

使用特权

评论回复
24
busdriver|  楼主 | 2010-11-11 14:44 | 只看该作者
Memory Summary:
    Program space        used  1EE1h (  7905) of  2000h words   ( 96.5%)
    Data space           used    E4h (   228) of   170h bytes   ( 62.0%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    Configuration bits   used     0h (     0) of     2h words   (  0.0%)
    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)

code flash快被装满了,有问题吗?

使用特权

评论回复
25
shizaigaole| | 2010-11-11 21:14 | 只看该作者
本帖最后由 shizaigaole 于 2010-11-11 21:26 编辑

一般情况下,如果不考虑多次按键同时按下的情况,
按键扫描子程序设计可以简化一点,
扫描阶段可以不取具体键盘值,
认为延时到的时候的值就是键盘值。

     if(step == 0)//in the step of key scanning
        {
                //key scanning
                if(FOUT_ON_OFF != on_off_flag)//if key FOUT_ON_OFF change
                        step = 1;//enter the step of delay
          else if(LED_SWITCH != led_switch_flag)//if key LED_SWITCH change
                        step = 1;//enter the step of delay
                else if(!FOUT_UP)//if key FOUT_UP touch
                        step = 1;//enter the step of delay
                else if(!FOUT_DOWN)
                        step = 1;//enter the step of delay
        }

如果键值输入口线都在一组IO口中话,

能否改为
if(step == 0)//in the step of key scanning
        {
               if( (PORTA&0xab) !=  0x00)             //类似于此
               step = 1;//enter the step of delay
        }

使用特权

评论回复
26
shizaigaole| | 2010-11-11 21:30 | 只看该作者
你的程序是否还有别的部分,
否则的话就这么一点程序,占用这么大内存不正常。

当然不能使用过期的试用版的Lite 模式的PICC编译器,这样会产生很多垃圾代码。

使用特权

评论回复
27
yewuyi| | 2010-11-12 09:59 | 只看该作者
这个方案完全用不到什么中断嵌套,甚至连16F57那样没有中断向量的MCU都能轻松完成LED动态扫描显示+KEY识别+UART收发的工作。
当然,现在MCU资源都比较丰富了,我们也没必要那么变态的做设计,假设以一个普通16F88X为例,
LZ至少要弄明白以下一些知识点:
1、前后台的程序主框应该如何搞!?
2、按键如何通过查询的方式进行识别!?
3、如何在不长时间独占CPU的情况下完成LED动态扫描!?
4、UART的收发缓冲能起到什么样的作用!?
5、简单的状态处理

使用特权

评论回复
28
busdriver|  楼主 | 2010-11-12 15:29 | 只看该作者
本帖最后由 busdriver 于 2010-11-12 15:46 编辑

1、前后台的程序主框应该如何搞!?
贴出main和中断程序流程图
2、按键如何通过查询的方式进行识别!?
贴出按键扫描和服务程序流程图。
3、如何在不长时间独占CPU的情况下完成LED动态扫描!?
LED用的是静态扫描。
4、UART的收发缓冲能起到什么样的作用!?
只用到接收缓冲,因为只开了接收中断
5、简单的状态处理
是这样做的,参见主程序流程图

firmware flow.pdf

73.82 KB

使用特权

评论回复
29
busdriver|  楼主 | 2010-11-12 15:32 | 只看该作者
本帖最后由 busdriver 于 2010-11-12 15:48 编辑

回shizaigaole:
1.一般情况下,如果不考虑多次按键同时按下的情况,
按键扫描子程序设计可以简化一点,
扫描阶段可以不取具体键盘值,
认为延时到的时候的值就是键盘值。
十分好的建议!但是很遗憾,不在一个口线上面,且其中两个非轻触按键。
2.你的程序是否还有别的部分,
否则的话就这么一点程序,占用这么大内存不正常。

当然不能使用过期的试用版的Lite 模式的PICC编译器,这样会产生很多垃圾代码。
还有别的程序,请参见上面程序流程图,是指Microchip网站下载的最新MPLAB和PICC,应该没过期。

使用特权

评论回复
30
busdriver|  楼主 | 2010-11-12 15:49 | 只看该作者
真理越辩越明,开此一贴,收回颇丰,谢谢大家!

使用特权

评论回复
31
busdriver|  楼主 | 2010-11-12 17:07 | 只看该作者
按键程序更新。见23楼

使用特权

评论回复
32
e掾木| | 2010-11-13 23:24 | 只看该作者
N年前我贴过一个键盘程序,可惜过了三年才有个家伙看出了门道。有兴趣的去www.picpic.cn

使用特权

评论回复
33
busdriver|  楼主 | 2010-11-30 22:50 | 只看该作者
那个家伙是谁?

使用特权

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

本版积分规则