庆科社区
直播中

gjianw217

11年用户 689经验值
擅长:嵌入式技术 控制/MCU RF/无线
私信 关注

【MiCOKit试用体验】庆科MiCOKit外设篇(2)Key按键

本帖最后由 gjianw217 于 2015-10-17 23:56 编辑

本帖主要内容:本帖子主要使用庆科提供的MiCOKit开发环境,来测试板上的2个Key的响应,并简单了解MiCOKit的封装。
一、测试环境:
庆科开发套件EMW3165底板和扩展板
庆科SDK_MiCOKit_v2.3.0.2
USB串口线
JLink仿真
串口调试助手

二、硬件分析:
在EMW3165套件上,一共配置了4个按键,如下图所示,其中底板2个,扩展板2个,如图中所示,当按键按下时,对应引脚接地,为低电平,否则为高电平。
3.png
另外通过查看原理图和开发板,各个按键分别对应EMW3165无线控制模块的引脚,如下图所示:
4.png
三、软件分析:
1 软件分层
在庆科提供的SDK_MiCOKit_v2.3.0.2开发包中,进行了三层的软件封装,即:用户层(外设层),平台层,驱动层。
(1)用户层(外设层),定义在 SDK_MiCOKit_v2.3.0.2/Platform/Drivers/MiCOKit_EX/目录下,主要通过调用平台层的封装函数,定义了各扩展板上外设的操作,用户只要调用它们,而无需知道各外设的原理,即可对其进行操作。
(2)平台层 定义在SDK_MiCOKit_v2.3.0.2/Platform/Peripherals/目录下,以platform_xxx.h命名,主要通过调用驱动层的封装函数,定义了MiCO系统需要调用的接口,方便将MiCO移植到不同的芯片平台上。
(3)驱动层 定义在SDK_MiCOKit_v2.3.0.2/Platform/Peripherals/Libraries/STM32F4xx_StdPeriph_Driver/目录下,以stm32f4xx_xx.c命名,主要移植了有关芯片提供商提供的对芯片操作的接口函数。
2 软件定义
在 SDK_MiCOKit_v2.3.0.2PlatformDriversMiCOKit_EXTkey目录下的key.c文件中,定义了4+4+2个函数,实现对按键初始化以及单击和长按事件的响应函数,在分析具体函数前,需要弄明白两个关键字:static和weak
下面是摘自维基百科的一段话:

A weak symbol denotes a specially annotatedsymbol during linking of Executable and Linkable Format (ELF) object files. Bydefault, without any annotation, a symbol in an object file is strong. Duringlinking, a strong symbol can override a weak symbol of the same name. Incontrast, two strong symbols that share a name yield a link error duringlink-time. When linking a binary executable, a weakly declared symbol does notneed a definition. In comparison, (by default) a declared strong symbol withouta definition triggers an undefined symbol link error.
Astaticvariable is a variable that ha***een allocated statically in computer programming,—whose lifetime or"extent" extends across the entire run of the program. This is incontrast to the more ephemeral automatic variables (local variables aregenerally automatic), whose storage is allocated and deallocated on the callstack; and in contrast to objects whose storage is dynamically allocated in heapmemory.

在key.c文件中,
首先是2个初始化函数:
在初始化函数中,首先将按键对应的引脚初始为上拉输入模式,然后为其初始化一个定时器,如果在规定的时间内按下按键,则响应定时中断任务,最后将其初始化为下降边沿中断,如果按键被按下,则响应相应的事件。
  1. void user_key1_init(void)
  2. {
  3.    MicoGpioInitialize( (mico_gpio_t)USER_KEY1, INPUT_PULL_UP );
  4.    mico_init_timer(&_user_key1_timer, user_key1_long_press_timeout, _user_key1_timeout_handler, NULL);
  5.    MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY1, IRQ_TRIGGER_FALLING_EDGE, _user_key1_irq_handler, NULL );
  6. }

  7. void user_key2_init(void)
  8. {
  9.    MicoGpioInitialize( (mico_gpio_t)USER_KEY2, INPUT_PULL_UP );
  10.    mico_init_timer(&_user_key2_timer, user_key2_long_press_timeout, _user_key2_timeout_handler, NULL);
  11.    MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY2, IRQ_TRIGGER_FALLING_EDGE, _user_key2_irq_handler, NULL );
  12. }
其次,其定义了4个静态本地函数,通过逻辑判断,实现相应按键响应长按事件还是单击事件
  1. static void _user_key1_irq_handler( void* arg )
  2. {
  3.   (void)(arg);
  4.   int interval = -1;
  5.   
  6.   if ( MicoGpioInputGet( (mico_gpio_t)USER_KEY1 ) == 0 ) {
  7.     _default_key1_start_time = mico_get_time()+1;
  8.     mico_start_timer(&_user_key1_timer);
  9.     MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY1, IRQ_TRIGGER_RISING_EDGE, _user_key1_irq_handler, NULL );
  10.   }
  11.   else {
  12.     interval = mico_get_time() + 1 - _default_key1_start_time;
  13.     if ( (_default_key1_start_time != 0) && interval > 50 && interval < user_key1_long_press_timeout){
  14.       /* button clicked once */
  15.       user_key1_clicked_callback();
  16.       MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY1, IRQ_TRIGGER_FALLING_EDGE, _user_key1_irq_handler, NULL );
  17.     }
  18.     mico_stop_timer(&_user_key1_timer);
  19.     _default_key1_start_time = 0;
  20.   }
  21. }

  22. static void _user_key1_timeout_handler( void* arg )
  23. {
  24.   (void)(arg);
  25.   _default_key1_start_time = 0;
  26.   MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY1, IRQ_TRIGGER_FALLING_EDGE, _user_key1_irq_handler, NULL );
  27.   if( MicoGpioInputGet( (mico_gpio_t)USER_KEY1 ) == 0){
  28.     user_key1_long_pressed_callback();
  29.   }
  30.   mico_stop_timer(&_user_key1_timer);
  31. }

  32. static void _user_key2_irq_handler( void* arg )
  33. {
  34.   (void)(arg);
  35.   int interval = -1;
  36.   
  37.   if ( MicoGpioInputGet( (mico_gpio_t)USER_KEY2 ) == 0 ) {
  38.     //keys_log("_user_key2_irq_handler1");
  39.     _default_key2_start_time = mico_get_time()+1;
  40.     mico_start_timer(&_user_key2_timer);
  41.     MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY2, IRQ_TRIGGER_RISING_EDGE, _user_key2_irq_handler, NULL );
  42.   }
  43.   else {
  44.     //keys_log("_user_key2_irq_handler2");
  45.     interval = mico_get_time() + 1 - _default_key2_start_time;
  46.     if ( (_default_key2_start_time != 0) && interval > 50 && interval < user_key2_long_press_timeout){
  47.       /* button clicked once */
  48.       user_key2_clicked_callback();
  49.       MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY2, IRQ_TRIGGER_FALLING_EDGE, _user_key2_irq_handler, NULL );
  50.     }
  51.     mico_stop_timer(&_user_key2_timer);
  52.     _default_key2_start_time = 0;
  53.   }
  54. }

  55. static void _user_key2_timeout_handler( void* arg )
  56. {
  57.   (void)(arg);
  58.   _default_key2_start_time = 0;
  59.   MicoGpioEnableIRQ( (mico_gpio_t)USER_KEY2, IRQ_TRIGGER_FALLING_EDGE, _user_key2_irq_handler, NULL );
  60.   if( MicoGpioInputGet( (mico_gpio_t)USER_KEY2 ) == 0){
  61.     user_key2_long_pressed_callback();
  62.   }
  63.   mico_stop_timer(&_user_key2_timer);
  64. }
最后,定义了4个用户接口函数,即2个按键的长按事件和单击事件的接口,由于是用weak来修改该函数(接口),故用户可重写该4个函数,实现自己的功能,默认什么也不做。
  1. WEAK void user_key1_clicked_callback(void)
  2. {
  3.   return;
  4. }

  5. // Key1 long pressed callback
  6. WEAK void user_key1_long_pressed_callback(void)
  7. {
  8.   return;
  9. }

  10. // Key2 clicked callback:  next test module in test mode
  11. WEAK void user_key2_clicked_callback(void)
  12. {
  13.   return;
  14. }

  15. // Key2 long pressed callback(use for enter MFG MODE when reset)
  16. WEAK void user_key2_long_pressed_callback(void)
  17. {
  18.   return;
  19. }
四、测试程序:
1 指定头文件
由于在IAR开发环境中,SDK_MiCOKit_v2.3.0.2已经指定了头文件目录 ,如下图所示,
5.png
故在测试文件中,指定头文件的方法如下:
  1. #include "key/keys.h"
2 编写测试程序
  1. #define sensor_log(M, ...) custom_log("Sensor", M, ##__VA_ARGS__) //在helloworld文件中,重新定义串口测试函数
  2. void user_key1_clicked_callback(void)//点击key1,SYS_LED反转三次
  3. {
  4.   MicoGpioOutputTrigger( MICO_SYS_LED );
  5.   mico_thread_sleep(1);
  6.   MicoGpioOutputTrigger( MICO_SYS_LED );
  7.   mico_thread_sleep(1);
  8.   MicoGpioOutputTrigger( MICO_SYS_LED );
  9.   mico_thread_sleep(1);
  10. sensor_log("key1_clicked_callback");
  11. }

  12. // Key1 long pressed callback
  13. void user_key1_long_pressed_callback(void)//长按key1,SYS_LED反转一次
  14. {
  15.   MicoGpioOutputTrigger( MICO_SYS_LED );
  16.   mico_thread_sleep(1);
  17. sensor_log("key1_long_pressed_callback");
  18.   return;
  19. }

  20. // Key2 clicked callback
  21. void user_key2_clicked_callback(void)//点击key2,RF_LED反转三次
  22. {
  23.   MicoGpioOutputTrigger( MICO_RF_LED );
  24.   mico_thread_sleep(1);
  25.   MicoGpioOutputTrigger( MICO_RF_LED );
  26.   mico_thread_sleep(1);
  27.   MicoGpioOutputTrigger( MICO_RF_LED );
  28.   mico_thread_sleep(1);
  29. sensor_log("key2_clicked_callback");
  30.   return;
  31. }

  32. // Key2 long pressed callback
  33. void user_key2_long_pressed_callback(void)//长按key2,RF_LED反转一次
  34. {
  35.   MicoGpioOutputTrigger( MICO_RF_LED );
  36.   mico_thread_sleep(1);
  37. sensor_log("key2_long_pressed_callback");
  38.   return;
  39. }

  40. void TestKey(void)//由application_start函数调用
  41. {
  42.   //Led已经Bootloader中初始化,故无需要再初始化
  43.   user_key1_init();
  44.   user_key2_init();
  45.   while(1);
  46. }
3由于在micoket_ext_mfg.c文件中,定义了user_key1_clicked_callback和user_key2_clicked_callback,故需要注释掉这两个函数,才能正常编译过去。
五、测试结果:
开板板效果:
串口效果:
测试不正常:
刚开始可以正常响应几次,但多次后,出错死机的现像,其中的一次测试结果如:
21.png



回帖(2)

Murphy

2015-12-15 16:40:27
您好,我运行这个程序的时候遇到了这各问题,按键速度稍快一点就会有异常,如图: 111.PNG
E:111.png
举报

gjianw217

2016-1-15 16:45:10
我不清楚你的“这个程序”是那个程序?,上面的程序是经常自己修改过的。不过从你的提示看,应该是内存出了问题。
另外在micoket_ext_mfg.c文件中,已经定义了user_key1_clicked_callback和user_key2_clicked_callback它们的回调函数,如果想自己实现别的功能,需要注释后重新定义。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分