[菜农助学交流] 【第四批】入门笔记第一帖_trigkey(by zxcscm)

[复制链接]
 楼主| zxcscm 发表于 2012-1-4 16:00 | 显示全部楼层 |阅读模式
gp, IO, GPIO, pi, ST
先不多说,直接上代码,功能说明啥的都在程序注释里
说明:
/*********************************************************************
* 文件名称:        tirgkey.c
* 功能说明:        触发器键盘识别驱动程序,可区分短按与长按
* 版本日期: 2011年12月28日
* 修改记录:
* 声    明:1、该部分程序参照二姨网友XIANSir的程序,具体请见:https://bbs.21ic.com/icview-229561-2-1.html
                  2、在保持原功能不变的情况下,区分短按与长按,不再买一赠一
***********************************************************************/
KeyScan()
  1. /
  2. /**************************************************************************
  3. * 函数名称:        KeyScan()
  4. * 功能说明: 扫描按键,并给出按键值,存储在KeyCode中
  5. * 输    入: 无
  6. * 输    出: 无
  7. * 注意事项: 1、按键处理与按键的硬件连接息息相关,本函数当前能够正确处理的按键硬件连接为:
  8. *                        KEY_1<->GPB.15        KEY_2<->GPB.14
  9. *                        
  10. ****************************************************************************/

  11. void KeyScan(void)
  12. {
  13.       uint32_t stat  = 0x00; //按键的状态值
  14.     static uint32_t trig  = 0;    //按键触发,按键的下降沿将trig置1,以表示有按键被按下;在下一个检测周期(下一次本函数被调用)tirg会被本函数自动清零
  15.     static uint32_t press = 0;    //保存stat的状态,表示按键持续按下
  16.     static uint32_t count = 0;    //记录press值持续时间,以检测长按键
  17.     static uint32_t save  = 0;    //记录按键按下时的按键值,只有短按键抬起时才用到,长按后抬起也被清除

  18.     stat = (DrvGPIO_GetPortBits(E_GPB) & 0xC000) ^ 0xC000; //按键的状态值,实际是GPB15和GPB14引脚电平逻辑的按位取反值
  19.         
  20.     if((trig != 0x00) && (stat == press)) //trig置位表示发生了一次按键动作,
  21.     {                                  //stat == press这个判断可以起到“消抖”作用
  22.         save=stat;                        //有按键按下, 暂时保存按键值
  23.     }        
  24.         
  25.       trig  = stat&(stat^press);//实际的核心代码,stat^press保证只有在按键变化时(有键被按下或释放),trig才有机会为1;而stat&部分则保证只有按键被按下才会置位tirg,而按键被释放则不会置位tirg
  26.       press = stat;             //保存stat的状态,stat与press协同工作构建了一个“软件触发器”

  27.     if((press==0)&&(save!=0))    //按键按下且抬起了,判断为短按
  28.     {
  29.              switch(save)             //判断是哪一个按键被按下了
  30.         {
  31.                      case 0x4000:
  32.                               KeyCode = KEY_1;
  33.                               break;
  34.                       case 0x8000:
  35.                               KeyCode = KEY_2;
  36.                               break;
  37.                       default:            //多个按键同时被按下的情况当前代码不支持,但如果有需要加入复合键的支持非常容易
  38.                     KeyCode = NOKEY;
  39.                               break;
  40.              }
  41.             save=0;                //判断完按键值,清除按键值
  42.     }
  43.       if(press != 0x00)
  44.      {
  45.             count++;
  46.             if(count == 100)     //按键被持续按住长达10ms*100=1s,表示有按键被长按
  47.         {
  48.                   save=0;          //清空短按值,防止长按后抬起执行短按功能
  49.             count = 50;      //将计数器置为50,目的是长按后每隔(100-50)*10ms,连续执行长按实现类似连加的功能。若想仅执行一次长按可将count置大于100的数,如KEY2
  50.                   switch(stat)     //判断是哪一个按键被长按了
  51.             {
  52.                          case 0x4000:
  53.                                    KeyCode = KEY_1L;
  54.                                    break;
  55.                          case 0x8000:
  56.                                   KeyCode = KEY_2L;
  57.                                   count=101;   //将count置大于100的值,屏蔽长按KEY2时连续的执行KEY2功能,
  58.                       break;
  59.                        default:
  60.                                 KeyCode = NOKEY;        //多个按键同时被按下的情况当前代码不支持,但如果有需要加入复合键的支持非常容易
  61.                 break;
  62.                   }
  63.           }
  64.           if(count>200)
  65.                 count=101;
  66.     }
  67.     else
  68.     {
  69.           count=0;
  70.     }               
  71. }
main()

  1. /***********************************************************************
  2. * 函数名称: main()
  3. * 功能说明: 根据按键值点亮相应LED。
  4.             短按K1:LED1亮/灭;长按K1:LED2亮/灭,若持续按下K1则LED2闪烁;
  5.             短按K2:LED3亮/灭;长按K2:LED4亮/灭,若持续按下K2则LED4不再变化,直到抬起后再次长按。
  6. * 输    入: 无
  7. * 输    出: 无
  8. ************************************************************************/


  9. int main(void)
  10. {
  11.     UNLOCKREG();
  12.     SYSCLK->PWRCON.XTL12M_EN = 1;// SYSCLK =>12Mhz
  13.     LOCKREG();
  14.    
  15.     DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT );//设置GPA.2~GPA.5为输出模式
  16.    DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT );
  17.     DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT );
  18.     DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT );
  19.    
  20.     DrvGPIO_ClrBit( E_GPA,2);            //做测试LED用
  21.    DrvGPIO_SetBit( E_GPA,4);
  22.    
  23.     KeyInit();  //初始化按键相关的端口和定时器。
  24.                 //PS:开始调试时忘加该函数,导致反复的调试按键都没反应。几天后才通过断点调试发现定时器T0都没有运行。切记切记~~~

  25.     while(1)
  26.     {
  27.         if(KeyCode!= NOKEY)
  28.         {
  29.             switch (KeyCode)
  30.             {
  31.             case KEY_1:                     //短按KEY1,LED1状态取反
  32.                 if(DrvGPIO_GetBit(E_GPA,2))
  33.                        {
  34.                             DrvGPIO_ClrBit(E_GPA,2);
  35.                        }
  36.                        else
  37.                            DrvGPIO_SetBit(E_GPA,2);
  38.                        KeyCode=0;
  39.                        break;
  40.             case KEY_1L:                   //长按KEY1,LED2状态取反,若一直按着不放,LED2会闪烁
  41.                if(DrvGPIO_GetBit(E_GPA,3))
  42.                       {
  43.                               DrvGPIO_ClrBit(E_GPA,3);
  44.                        }
  45.                        else
  46.                              DrvGPIO_SetBit(E_GPA,3);
  47.                        KeyCode=0;
  48.                        break;
  49.             case KEY_2:                    //短按KEY2,LED3状态取反
  50.                 if(DrvGPIO_GetBit(E_GPA,4))
  51.                        {
  52.                                DrvGPIO_ClrBit(E_GPA,4);
  53.                         }
  54.                         else
  55.                                DrvGPIO_SetBit(E_GPA,4);
  56.                         KeyCode=0;
  57.                         break;
  58.             case KEY_2L:                   //长按KEY2,LED4状态取反,若一直按着不放,就不会再执行了,具体原因见KeyScan()
  59.             {
  60.                        if(DrvGPIO_GetBit(E_GPA,5))
  61.                       {
  62.                              DrvGPIO_ClrBit(E_GPA,5);
  63.                        }
  64.                        else
  65.                              DrvGPIO_SetBit(E_GPA,5);
  66.                        KeyCode=0;
  67.                        break;
  68.              }
  69.             default:break;
  70.             }
  71.         }
  72.     }
  73. }
工程文件包:

作为第四批的园地M0幸运者,由于各种原因现在才开始真正意义上的第一帖笔记,真的很惭愧,对不起自己当初的热情,更对不起菜农大叔的辛苦。俺从园地的第一届助学活动就开始关注,目睹了菜农大叔的各种辛苦,大叔的真诚、热心以及助学活动的信心大家有目共睹,心知肚明的,但是总是有各种怀疑和议论声,我就不明白为什么不能多些理解和支持呢。大叔如此热情的进行这个义务的助学活动,不管是精神上、物质上还是时间上都付出那么多,为的是什么?“挽救失足青年”仅此而已,我们作为学子能做的就是把握机会,好好学习,认真记笔记,我想就是对菜农最大的支持了。

无论如何,从现在开始俺将真正的学习M0,学习嵌入式,争取从51菜鸟转成M0菜农,能在园地里耕作,收获属于自己的果实。

声明一点,俺的基础薄,所以笔记不会有多少含金量的,但俺会一直向各位网友学习,一步一个脚印的学扎实了,同时欢迎各位来拍砖!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| zxcscm 发表于 2012-1-4 16:01 | 显示全部楼层

灌水,吐糟

本帖最后由 zxcscm 于 2012-1-4 16:03 编辑

二楼纯属吐糟,说下俺中断学习原因之一,可直接绕过


俺是第四批最后一个拿到助学板的,刚开始时对着菜地里的例程很快学会了keil工程建立和断点调试以及ICP程序下载,当板上的LED开始亮起来时,甚是高兴。兴奋之余,想探索开发板其他的功能。
首先是ISP下载:在公司里对着例程将ISP固件下载到板子上,连上串口线,开始用新塘的ISP下载,尝试若干次没连上,换用大叔的HotISP,也不行,单独用usb给板子供电也不行,开始纳闷了,难道是ISP固件下载的不对?然后就重新用ICP下载最新固件(注意此时我没有拔掉板子上的USB电源,即NU_Link和板子都连接了USB),结果出现了更让人郁闷的结果:ICP连接不上NU_Link,提示要重新擦除FLASH,按照提示操作一通,还好,ICP连上了也下载了程序,ISP依然没有连接上。无奈,重新用keil调试下载程序。问题来了,keil连接不上U_Link了,所有的配置都没动,怎么就会出现这种问题呢,马上用ICP试试,又出现提示:quedin
确定后,ICP也连接不上了!!!
第一反应,完了板子坏了:因为我将板子一直放在主机箱上面,我就怀疑会不会是机箱漏电或静电什么的把开发板给电坏了。
不甘心,真希望是我某个设置的问题,尝试了下脱机下载,一切正常,ICP能连接NU_Link并下载程序,可是无论如何就是下载不到开发板上,当天晚上回家在自己的电脑上出现同样的问题,ICP要擦除FLASH 最终但也连接不上。然后就找菜农大叔,寻求帮助,菜农大叔很热心,让我一步一步的重新配置,用一晚上的时间,尝试了各种方法都没成功,结论是:NU_Link连接正常,没问题,问题就出现在开发板上。这更让我确信:开发板坏了!

郁闷至极:新拿的开发板还没开始用呢就这样坏了,多心疼。心想着只好再想办法买一个了,之后工作上的事让我也无暇再顾及M0助学板,这一放就1个多月过去了,每每看到园地MM们陆续上传的笔记和桌子上躺着的M0 助学板,心里就说不出的滋味,想学可又没有板子用,那么好的一个开发板怎么就坏了呢……

直到偶然间看到这个帖子https://bbs.21ic.com/icview-229808-1-1.html,他在9楼的问题和我的完全一样,向他请教解决方法,确认后,赶紧按照他的方法,将NU_LINK上的102电阻换成100欧,连接ICP,哈哈,顺利的连接上了!!!不再有提示擦除FLASH ,换用keil一切正常,改用HotISP的usbisp也很顺利,心里甭提多高兴了!!!在这里真的要谢谢Swallow_0322 若没有他这个帖子我不知会郁闷到什么时候呢。

所以这次的教训就是:不能用两根USB线同时给NU—Link和开发板供电,否则有损坏NU—Link的可能,一定要切记!
还有另外一个方法就是更改NU—Link上电源处的0Ω电阻,换成二极管,防止电流倒灌。
lovebaby8848 发表于 2012-1-4 21:11 | 显示全部楼层
准备把线藏起来一根 不要让两根线见面
 楼主| zxcscm 发表于 2012-1-5 10:34 | 显示全部楼层
3# lovebaby8848

对的,当时就是因为看到有两根线就直接都给用上了
仙人球W 发表于 2014-11-18 11:59 | 显示全部楼层
路过
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

628

帖子

1

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