[Cortex-M0技术交流] 菜鸟学习M0第九帖——Button

[复制链接]
 楼主| lixiaoxu2meng 发表于 2011-9-24 10:59 | 显示全部楼层 |阅读模式
自从上个月选美到现在 已有一个月左右了  一直没有什么时间  只得抽空编写几个例程
所以一直没有什么时间上传  今天我把电脑里的几个例程一起传上来  传之前我专门 测试了一下 以保证都好用 避免给参考的网友带来麻烦
下面上代码 本例程参考STM32开发板的按键例程 采用FIFO的方式 不多说了 直接上代码
mian()函数
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /* */
  3. /* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
  4. /* */
  5. /*---------------------------------------------------------------------------------------------------------*/
  6. #include "includes.h" //包含所需的头文件
  7. /*************************************************************************************
  8. ** Function name: main
  9. ** Descriptions: Key1键按下LED1点亮,Key1键长按 LED2点亮 ,Key1键释放 LED1熄灭
  10. Key2键按下LED3点亮,Key2键长按 LED4点亮 ,Key2键释放 LED3熄灭
  11. ** input parameters: 无
  12. ** output parameters: 无
  13. ** Returned value: 无
  14. *************************************************************************************/
  15. int main (void)
  16. {
  17. Set_System(); //封装一些初始化模块
  18. while(1)
  19. {
  20. KeyCode = GetKey();
  21. switch(KeyCode)
  22. {
  23. case KEY1_DOWN_USER:
  24. {
  25. DrvGPIO_ClrBit(E_GPA,2); //LED1 点亮
  26. }
  27. break;
  28. case KEY1_UP_USER:
  29. {
  30. DrvGPIO_SetBit(E_GPA,2); //LED2 熄灭
  31. }
  32. break;
  33. case KEY1_HOLD_USER:
  34. {
  35. DrvGPIO_ClrBit(E_GPA,3); //LED2 点亮
  36. }
  37. break;
  38. case KEY2_DOWN_USER:
  39. {
  40. DrvGPIO_ClrBit(E_GPA,4); //LED3 点亮
  41. }
  42. break;
  43. case KEY2_UP_USER:
  44. {
  45. DrvGPIO_SetBit(E_GPA,4); //LED3 熄灭
  46. }
  47. break;
  48. case KEY2_HOLD_USER:
  49. {
  50. DrvGPIO_ClrBit(E_GPA,5); //LED4 点亮
  51. }
  52. break;
  53. default:break;
  54. }
  55. }
  56. }


hw_config函数
  1. #include "includes.h" //包含所需的头文件
  2. /*************************************************************************************
  3. ** Function name: Set_System
  4. ** Descriptions: 封装一些初始化模块
  5. ** input parameters: count
  6. ** output parameters: 无
  7. ** Returned value: 无
  8. *************************************************************************************/
  9. void Set_System(void)
  10. {
  11. InitButtonVar(); //按键初始化

  12. RCC_Configuration(); //配置系统时钟

  13. GPIO_Configuration(); //配置GPIO

  14. TIMER_Configuration(); //配置TIMER
  15. }
  16. /*************************************************************************************
  17. ** Function name: RCC_Configuration
  18. ** Descriptions: 系统时钟源设置
  19. ** input parameters: none
  20. ** output parameters: none
  21. ** Returned value: none
  22. *************************************************************************************/
  23. void RCC_Configuration(void)
  24. {
  25. UNLOCKREG(); // 对写保护位操作时 需要一次向0x50000 0100写入 0x59,0x16,0x88,
  26. DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);//与其 SYSCLK->PWRCON.XTL12M_EN = 1; 等同
  27. // PWRCON寄存器(这些寄存器在上电复位到用户解锁定之前是锁定的)除了 BIT[6]位其他位都受写保护
  28. // 解除这些需要向 0x50000 0100写入 0x59,0x16,0x88,
  29. // 令PWRCON寄存器的BITP[0]为1(即设定12M外部晶振)
  30. delay_ms(100); //while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);//等待外部12MHZ晶振就绪
  31. LOCKREG(); // 向“0x5000_0100”写入任何值,就可以重锁保护寄存器
  32. }
  33. /*************************************************************************************
  34. ** Function name: GPIO_Configuration
  35. ** Descriptions: GPIO配置
  36. ** input parameters: none
  37. ** output parameters: none
  38. ** Returned value: none
  39. *************************************************************************************/
  40. void GPIO_Configuration()
  41. {
  42. DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT ); //led端口设置为输出
  43. DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT );
  44. DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT );
  45. DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT );

  46. DrvGPIO_Open( E_GPB, 14, E_IO_INPUT ); //按键端口设置为输入
  47. DrvGPIO_Open( E_GPB, 15, E_IO_INPUT );
  48. }
  49. /*************************************************************************************
  50. ** Function name: TIMER_Configuration
  51. ** Descriptions: TIMER配置
  52. ** input parameters: none
  53. ** output parameters: none
  54. ** Returned value: none
  55. *************************************************************************************/
  56. void TIMER_Configuration()
  57. {
  58. DrvTIMER_Init(); //初始化定时器

  59. DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0); //使用外设时注意必须设置该外设的时钟 设置TMR0的时钟源为外部12MHZ

  60. DrvTIMER_Open(E_TMR0,1000,E_PERIODIC_MODE); //设定定时器timer0的tick周期,并且启动定时器:定时器通道 TMR0 每秒1000次 周期模式

  61. DrvTIMER_SetTimerEvent(E_TMR0,10,(TIMER_CALLBACK) Timer0_Callback,0); //安装一个10ms定时处理事件到 timer0通道

  62. DrvTIMER_EnableInt(E_TMR0); //使能定时器中断 //TIMER0->TCSR.IE = 1

  63. DrvTIMER_Start(E_TMR0); //定时器timer0开始计数 //TIMER0->TCSR.CEN = 1;
  64. }
  65. /*************************************************************************************
  66. ** Function name: Timer0_Callback
  67. ** Descriptions: 定时处理事件 用来做按键扫描
  68. ** input parameters: none
  69. ** output parameters: none
  70. ** Returned value: none
  71. *************************************************************************************/
  72. void Timer0_Callback (void)
  73. {
  74. KeyPro(); //按键扫描 该函数在 button.c 中实现
  75. }

  76. /*************************************************************************************
  77. ** Function name: delay_ms
  78. ** Descriptions: 1ms(晶振为12MHZ)延时子程序
  79. ** input parameters: count
  80. ** output parameters: 无
  81. ** Returned value: 无
  82. *************************************************************************************/
  83. void delay_ms(uint32_t count)
  84. {
  85. uint32_t i,j;
  86. for(i=count;i>0;i--)
  87. for(j=2395;j>0;j--);
  88. }

hw_config头文件
  1. #ifndef __HW_CONFIG_H__
  2. #define __HW_CONFIG_H__
  3. void Set_System(void);
  4. void RCC_Configuration(void);
  5. void GPIO_Configuration(void);
  6. void TIMER_Configuration(void);
  7. void Timer0_Callback (void);
  8. void delay_ms(uint32_t count);
  9. #endif

button函数

  1. /* Includes ------------------------------------------------------------------*/
  2. #include "includes.h"
  3. #include <stdio.h>
  4. static BUTTON_T s_Btn1User; /* Key1USER 键 */
  5. static BUTTON_T s_Btn2User; /* Key2USER 键 */

  6. static KEY_FIFO_T s_Key; /* 按键FIFO变量,结构体 */

  7. /*
  8. M0助学板 按键口线分配:
  9. KEY_User1键 : PB14 (低电平表示按下)
  10. KEY_User2键 : PB15 (低电平表示按下)
  11. 定义2个函数,判断按键是否按下,返回值1 表示按下,0表示未按下
  12. */
  13. static u8 IsKey1DownUser(void) {if (DrvGPIO_GetBit(E_GPB,15)== Bit_SET) return 0; return 1;}
  14. static u8 IsKey2DownUser(void) {if (DrvGPIO_GetBit(E_GPB,14) == Bit_SET) return 0; return 1;}


  15. /*******************************************************************************
  16. 函数名: InitButtonVar
  17. 输 入:
  18. 输 出:
  19. 功能说明:初始化所有的按键变量,这个函数需要在TIMER0中断启动前调用1次
  20. *******************************************************************************/
  21. void InitButtonVar(void)
  22. {
  23. /* 对按键FIFO读写指针清零 */
  24. s_Key.Read = 0;
  25. s_Key.Write = 0;

  26. /* 初始化Key1USER按键变量 */
  27. s_Btn1User.IsKeyDownFunc = IsKey1DownUser; /* 判断按键按下的函数 */
  28. s_Btn1User.FilterTime = BUTTON_FILTER_TIME; /* 按键滤波时间 */
  29. s_Btn1User.LongTime = BUTTON_LONG_TIME; /* 长按时间, 0表示不检测 */
  30. s_Btn1User.Count = s_Btn1User.FilterTime / 2; /* 计数器设置为滤波时间的一半 */
  31. s_Btn1User.State = 0; /* 按键缺省状态,0为未按下 */
  32. s_Btn1User.KeyCodeDown = KEY1_DOWN_USER; /* 按键按下的键值代码 */
  33. s_Btn1User.KeyCodeUp = KEY1_UP_USER; /* 按键弹起的键值代码 */
  34. s_Btn1User.KeyCodeLong = KEY1_HOLD_USER; /* 按键被持续按下的键值代码 */

  35. /* 初始化Key2USER按键变量 */
  36. s_Btn2User.IsKeyDownFunc = IsKey2DownUser; /* 判断按键按下的函数 */
  37. s_Btn2User.FilterTime = BUTTON_FILTER_TIME; /* 按键滤波时间 */
  38. s_Btn2User.LongTime = BUTTON_LONG_TIME; /* 长按时间, 0表示不检测 */
  39. s_Btn2User.Count = s_Btn2User.FilterTime / 2; /* 计数器设置为滤波时间的一半 */
  40. s_Btn2User.State = 0; /* 按键缺省状态,0为未按下 */
  41. s_Btn2User.KeyCodeDown = KEY2_DOWN_USER; /* 按键按下的键值代码 */
  42. s_Btn2User.KeyCodeUp = KEY2_UP_USER; /* 按键弹起的键值代码 */
  43. s_Btn2User.KeyCodeLong = KEY2_HOLD_USER; /* 按键被持续按下的键值代码 */

  44. }

  45. /*******************************************************************************
  46. 函数名: PutKey
  47. 输 入: 键值
  48. 输 出:
  49. 功能说明:将1个键值压入按键FIFO缓冲区
  50. *******************************************************************************/
  51. void PutKey(u8 _KeyCode)
  52. {
  53. s_Key.Buf[s_Key.Write] = _KeyCode;

  54. if (++s_Key.Write >= KEY_FIFO_SIZE)
  55. {
  56. s_Key.Write = 0;
  57. }
  58. }

  59. /*******************************************************************************
  60. 函数名: GetKey
  61. 输 入:
  62. 输 出: 返回键值, KEY_NONE ( = 0) 表示无键按下
  63. 功能说明:从按键FIFO取1个键值
  64. *******************************************************************************/
  65. u8 GetKey(void)
  66. {
  67. u8 ret;

  68. if (s_Key.Read == s_Key.Write)
  69. {
  70. return KEY_NONE;
  71. }
  72. else
  73. {
  74. ret = s_Key.Buf[s_Key.Read];
  75. if (++s_Key.Read >= KEY_FIFO_SIZE)
  76. {
  77. s_Key.Read = 0;
  78. }
  79. return ret;
  80. }
  81. }

  82. /*******************************************************************************
  83. 函数名:DetectButton
  84. 输 入: 按键结构变量指针
  85. 输 出:
  86. 功能说明:检测指定的按键
  87. *******************************************************************************/
  88. static void DetectButton(BUTTON_T *_pBtn)
  89. {
  90. if (_pBtn->IsKeyDownFunc())
  91. {
  92. if (_pBtn->Count < _pBtn->FilterTime)
  93. {
  94. _pBtn->Count = _pBtn->FilterTime;
  95. }
  96. else if(_pBtn->Count < 2 * _pBtn->FilterTime)
  97. {
  98. _pBtn->Count++;
  99. }
  100. else
  101. {
  102. if (_pBtn->State == 0)
  103. {
  104. _pBtn->State = 1;

  105. /* 发送按钮按下的消息 */
  106. if (_pBtn->KeyCodeDown > 0)
  107. {
  108. /* 键值放入按键FIFO */
  109. PutKey(_pBtn->KeyCodeDown);
  110. }
  111. }

  112. if (_pBtn->LongTime > 0)
  113. {
  114. if (_pBtn->LongCount < _pBtn->LongTime)
  115. {
  116. /* 发送按钮持续按下的消息 */
  117. if (++_pBtn->LongCount == _pBtn->LongTime)
  118. {
  119. /* 键值放入按键FIFO */
  120. PutKey(_pBtn->KeyCodeLong);
  121. }
  122. }
  123. }
  124. }
  125. }
  126. else
  127. {
  128. if(_pBtn->Count > _pBtn->FilterTime)
  129. {
  130. _pBtn->Count = _pBtn->FilterTime;
  131. }
  132. else if(_pBtn->Count != 0)
  133. {
  134. _pBtn->Count--;
  135. }
  136. else
  137. {
  138. if (_pBtn->State == 1)
  139. {
  140. _pBtn->State = 0;

  141. /* 发送按钮弹起的消息 */
  142. if (_pBtn->KeyCodeUp > 0)
  143. {
  144. /* 键值放入按键FIFO */
  145. PutKey(_pBtn->KeyCodeUp);
  146. }
  147. }
  148. }

  149. _pBtn->LongCount = 0;
  150. }
  151. }




  152. /*******************************************************************************
  153. 函数名:KeyPro
  154. 输 入:
  155. 输 出:
  156. 功能说明:检测所有的按键,这个函数要被TIMER0的中断服务程序调用
  157. *******************************************************************************/
  158. void KeyPro(void)
  159. {
  160. DetectButton(&s_Btn1User); /* Key1USER 键 */
  161. DetectButton(&s_Btn2User); /* Key2USER 键 */
  162. }

button头文件
  1. /* Define to prevent recursive inclusion -------------------------------------*/
  2. #ifndef __BUTTON_H
  3. #define __BUTTON_H
  4. #define u8 unsigned char
  5. #define u16 unsigned int
  6. /* Bit_SET and Bit_RESET enumeration -----------------------------------------*/
  7. typedef enum
  8. { Bit_RESET = 0,
  9. Bit_SET
  10. }BitAction;
  11. /* 按键滤波时间50ms, 单位10ms
  12. 只有连续检测到50ms状态不变才认为有效,包括弹起和按下两种事件
  13. */
  14. #define BUTTON_FILTER_TIME 5
  15. #define BUTTON_LONG_TIME 100 /* 持续1秒,认为长按事件 */

  16. /*
  17. 每个按键对应1个全局的结构体变量。
  18. 其成员变量是实现滤波和多种按键状态所必须的
  19. */
  20. typedef struct
  21. {
  22. /* 下面是一个函数指针,指向判断按键手否按下的函数 */
  23. u8 (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */
  24. u8 Count; /* 滤波器计数器 */
  25. u8 FilterTime; /* 滤波时间(最大255,表示2550ms) */
  26. u16 LongCount; /* 长按计数器 */
  27. u16 LongTime; /* 按键按下持续时间, 0表示不检测长按 */
  28. u8 State; /* 按键当前状态(按下还是弹起) */
  29. u8 KeyCodeUp; /* 按键弹起的键值代码, 0表示不检测按键弹起 */
  30. u8 KeyCodeDown; /* 按键按下的键值代码, 0表示不检测按键按下 */
  31. u8 KeyCodeLong; /* 按键长按的键值代码, 0表示不检测长按 */
  32. }BUTTON_T;

  33. /* 定义键值代码 */
  34. typedef enum
  35. {
  36. KEY_NONE = 0, /* 0 表示按键事件 */

  37. KEY1_DOWN_USER, /* KEY_User1键按下 */
  38. KEY1_UP_USER, /* KEY_User1键弹起 */
  39. KEY1_HOLD_USER, /* KEY_User1键长按 */

  40. KEY2_DOWN_USER, /* KEY_User2键按下 */
  41. KEY2_UP_USER, /* KEY_User2键弹起 */
  42. KEY2_HOLD_USER, /* KEY_User2键长按 */

  43. }KEY_ENUM;

  44. /*按键FIFO用到变量 */
  45. #define KEY_FIFO_SIZE 20
  46. typedef struct
  47. {
  48. u8 Buf[KEY_FIFO_SIZE]; /* 键值缓冲区 */
  49. u8 Read; /* 缓冲区读指针 */
  50. u8 Write; /* 缓冲区写指针 */
  51. }KEY_FIFO_T;

  52. void InitButtonVar(void);
  53. void PutKey(u8 _KeyCode);
  54. u8 GetKey(void);
  55. void KeyPro(void);
  56. #endif



已经过测试 OK
工程

本帖子中包含更多资源

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

×
mbydyjj 发表于 2011-9-30 09:40 | 显示全部楼层
学习一下 也要分数

您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

1679

帖子

2

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