123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- //==================================================================
- //
- // Filename: key.c
- // Description: key process.
- //
- //------------------------------------------------------------------
- //
- // version: v2.0
- // data: 10:08am, 07.Mar.2013, written by Sirius
- // Description: Change the way to process for CAN & line.
- //
- //------------------------------------------------------------------
- //==================================================================
- /*------------------------------------------------------------------------------
- * I N C L U D E
- *------------------------------------------------------------------------------*/
- #include "stm32f0xx.h"
- #include "general.h"
- #include "main.h"
- #include "mapp_msg.h"
- #include "mapp_arm.h"
- #include "mapp_key.h"
- #include "mapp_gpio.h"
- #include "mapp_pwr.h"
- /*------------------------------------------------------------------------------
- * D E F I N E
- *------------------------------------------------------------------------------*/
- /*--- sampling couter ---*/
- #define SCAN_ACK_COUNT (2) //2
- #define KEY_COUNT (7)
- /*--- Key status timer ---*/
- #define K_TIMER_LONG_PRESS (OS_TIMER_1_2S) /* Continious timer since key pressed */
- #define K_TIMER_RPT_INTERVAL (OS_TIMER_200MS) /* Interval timer between twice long press */
- /*------------------------------------------------------------------------------
- * S T R U C T
- *------------------------------------------------------------------------------*/
- /*----------------------
- ** Key struct
- -----------------------*/
- /*------------------------------------------------------------------------------
- * S T A T I C - V A R I A B L E S
- *------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- * G L O B A L
- *------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- * P R O T O T Y P E
- *------------------------------------------------------------------------------*/
- static void s_KeyDealwithTask(void);
- static VU16 s_keytime[KEY_COUNT] = {0};
- /*----------------------------------------------------------------------
- // Function name : ADC_Init
- // Input parameter :
- // Output parameter :
- // Use Function :
- // Reserve date : 10:25am, 07.Sep.2013, written by zwj
- ----------------------------------------------------------------------*/
- void AdcCfgInit(void)
- {
- }
- /*----------------------------------------------------------------------
- // Function name : KeyVarInit
- // Input parameter :
- // Output parameter :
- // Use Function : Init key module variables.
- // Reserve date : 11:37am, 07.Mar.2013, written by Sirius
- ----------------------------------------------------------------------*/
- void KeyVarInit(void)
- {
- }
- unsigned char key2_5laycnt = 0;
- /**
- * @brief 按键扫描与处理任务函数
- *
- * 该函数负责定期扫描所有按键状态,进行防抖处理,并在状态变化时
- * 通过消息队列发送按键事件。同时维护gtArm.KeyState变量以记录所有按键的当前状态。
- * 优化版:一次性读取所有GPIO状态,避免引脚读取之间的时间差异。
- */
- void KeyTask(void)
- {
- // 静态变量用于记录按键状态的历史信息
- static U08 last_KeyVal[KEY_COUNT] = {0}; // 记录每个按键的上一个状态
- static U08 trascnt1[KEY_COUNT] = {0}; // 按下状态计数器(用于防抖)
- static U08 trascnt2[KEY_COUNT] = {0}; // 释放状态计数器(用于防抖)
- U08 index = 0; // 循环索引
- U08 u8KeyVal[KEY_COUNT] = {0}; // 当前按键采样值
-
- // 一次性读取所有GPIO端口状态
- uint16_t portA_status = GPIOA->IDR; // 读取GPIOA输入数据寄存器
- uint16_t portB_status = GPIOB->IDR; // 读取GPIOB输入数据寄存器
-
- // 从端口状态中提取各按键状态 - 使用位操作代替单独的GPIO_ReadInputDataBit调用
- u8KeyVal[0] = !((portB_status & GPIO_Pin_5) != 0); // 呼叫按键 (PB5)
- u8KeyVal[1] = !gtArm.PA4_Value; // 手柄检测 (PA4) - 特殊处理
- u8KeyVal[2] = ((portA_status & GPIO_Pin_7) != 0); // 紧急按钮 (PA7)
- u8KeyVal[3] = !((portA_status & GPIO_Pin_15) != 0); // 增援按键 (PA15)
- u8KeyVal[4] = !((portB_status & GPIO_Pin_3) != 0); // 护理按键 (PB3)
- u8KeyVal[5] = !((portA_status & GPIO_Pin_5) != 0); // 换药按键 (PA5)
- u8KeyVal[6] = !((portB_status & GPIO_Pin_4) != 0); // 取消按键 (PB4)
-
- // 拔针功能特殊处理(手柄和换药按键同时按下)
- if ((u8KeyVal[1] == 1) && (u8KeyVal[5] == 1)) { // 长按拔针,延时退出
- key2_5laycnt = 50; // 设置延时计数
- } else {
- if (key2_5laycnt == 50) { // 拔针按键刚释放
- // 发送拔针释放消息
- OSQPost(AmiMsgQueue, ARM_MSG_KEY, TO_WORD(0x0f, KEY_RELEASED));
- }
- if (key2_5laycnt) {
- key2_5laycnt--; // 递减延时计数
- u8KeyVal[1] = 0; // 强制清除手柄按键状态
- u8KeyVal[5] = 0; // 强制清除换药按键状态
- last_KeyVal[1] = 0; // 更新历史状态
- last_KeyVal[5] = 0; // 更新历史状态
- return; // 在延时期间跳过正常按键处理
- }
- }
- // 增加互斥逻辑,防止PB5和PB4同时触发
- // 如果两个按键同时被检测为按下,优先处理PB5(呼叫键)
- if (u8KeyVal[0] == 1 && u8KeyVal[6] == 1) {
- u8KeyVal[6] = 0; // 忽略PB4按键
- }
- // 遍历所有按键进行状态检测和处理
- for (index = 0; index < KEY_COUNT; index++) {
- if (u8KeyVal[index] == 0) { // 按键未按下
- gtArm.KeyState &= ~(1 << index); // 清除对应按键状态位
- trascnt1[index] = 0; // 重置按下计数器
- trascnt2[index]++; // 增加释放计数器
- s_keytime[index] = 0; // 重置长按计时
-
- // 按键释放防抖处理
- if (trascnt2[index] > SCAN_ACK_COUNT) { // 防抖时间
- trascnt2[index] = 0;
- // 只有状态确实发生变化时才处理
- if (last_KeyVal[index] != u8KeyVal[index]) {
- // 区分普通释放和长按后释放
- if (last_KeyVal[index] == KEY_CONTINUE) {
- // 长按后释放消息
- OSQPost(AmiMsgQueue, ARM_MSG_KEY, TO_WORD(index+5, KEY_CONTINUE));
- } else {
- // 普通释放消息
- OSQPost(AmiMsgQueue, ARM_MSG_KEY, TO_WORD(index+5, KEY_RELEASED));
- }
- // 更新按键历史状态
- last_KeyVal[index] = u8KeyVal[index];
- }
- }
- } else { // 按键按下
- gtArm.KeyState |= (1 << index); // 设置对应按键状态位
- trascnt1[index]++; // 增加按下计数器
- trascnt2[index] = 0; // 重置释放计数器
- s_keytime[index]++; // 增加长按计时
- // 按键按下防抖处理
- if (trascnt1[index] > SCAN_ACK_COUNT) { // 防抖
- trascnt1[index] = 0;
- // 长按检测(超过1.5秒)
- if (s_keytime[index] > OS_TIMER_1S5) {
- // 首次达到长按时间时触发长按
- if (last_KeyVal[index] != KEY_CONTINUE) {
- last_KeyVal[index] = KEY_CONTINUE;
- // 这里原本有长按消息发送代码(已注释)
- }
- } else if (last_KeyVal[index] != u8KeyVal[index]) {
- // 普通按下消息(状态变化)
- OSQPost(AmiMsgQueue, ARM_MSG_KEY, TO_WORD(index+5, KEY_PRESSED));
- // 更新按键历史状态
- last_KeyVal[index] = u8KeyVal[index];
- }
- }
- }
- }
- }
- /*=============================== END OF FILE ===============================*/
|