记录一个真实项目的开发历程(5)--BUTTON for debug

button部分直接上代码, 先满足调试功能, 可以看到里面还有一些尚未完成的部分.

整体的思路是外部中断函数中触发按键, 然后启动一个定时器进行按键扫描, 状态机输出按键事件, 再利用任务通知直接恢复按键任务的阻塞状态进行按键事件的分发处理. 如果没有按键按下整个按键任务是堵塞状态, 主要是为了方便主控休眠而没有采用osDelay的方法.

按键事件的handler包括了按键初始化, 按键事件注册, 按键事件状态机扫描, 分层设计.欢迎留言

/* Include file --------------------------------------------------------------*/
#include <stdio.h>
#include "cmsis_os.h"
#include "limits.h"

#include "tim.h"
#include "iwdg.h"
#include "rtc.h"

#include "low_power_mgr.h"
#include "database.h"
#include "dbg_printf.h"
#include "btn.h"
#include "exflash.h"
#include "fp.h"

#if (BUTTONS_NUMBER > 0)
/* Private typedef -----------------------------------------------------------*/
typedef struct BUTTON_MGR {
	uint16_t            gpio_pin;
	GPIO_TypeDef       *gpio_port;
	uint32_t            ticks;
	bsp_button_action_t action;
	bsp_button_event_t  event;
} button_mgr_t;
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint16_t m_button_auth_masks = 0; /**<  */
static button_mgr_t m_events_list[BUTTONS_NUMBER] = {
#ifdef BUTTON_0
	{EXTI00_HOME_SYS_WKUP_Pin, EXTI00_HOME_SYS_WKUP_GPIO_Port},
#endif
#ifdef BUTTON_1
	{EXTI08_BUTTON0_Pin, GPIOD},
#endif
#ifdef BUTTON_2
	{EXTI09_BUTTON1_Pin, GPIOD},
#endif
#ifdef BUTTON_3
	{EXTI10_BUTTON2_Pin, GPIOD},
#endif
#ifdef BUTTON_4
	{EXTI11_BUTTON3_Pin, GPIOD},
#endif
#ifdef BUTTON_5
	{EXTI12_BUTTON4_Pin, GPIOD},
#endif
#ifdef BUTTON_6
	{EXTI13_BUTTON5_Pin, GPIOD},
#endif
#ifdef BUTTON_7
	{EXTI06_FP_SYS_WKUP_Pin, EXTI06_FP_SYS_WKUP_GPIO_Port},
#endif
};

extern osThreadId myTaskButtonHandle;
extern osThreadId myTaskRunStateHandle;

/* Private function prototypes -----------------------------------------------*/
static void bsp_button_init(void);
static bool bsp_button_startup_configure(void);
static bool bsp_event_button_action_assign(bsp_button_id_t button, bsp_button_action_t action, bsp_event_t event);
static uint8_t button_trigger_push(uint16_t gpio_pin);
static bsp_event_t button_state_machine(bool *bsp_button_is_press, uint16_t period_ticks);
static void app_button_event_process(bsp_event_t event);
static bool button_auth_cancel(uint16_t button_mask);

/* Private functions ---------------------------------------------------------*/
static void bsp_button_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();
	GPIO_InitStruct.Pin = EXTI08_BUTTON0_Pin | EXTI09_BUTTON1_Pin | EXTI10_BUTTON2_Pin | \
						  EXTI11_BUTTON3_Pin | EXTI12_BUTTON4_Pin | EXTI13_BUTTON5_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
	GPIO_InitStruct.Pull = GPIO_PULLDOWN;
	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
	GPIO_InitStruct.Pin = EXTI00_HOME_SYS_WKUP_Pin;
	HAL_GPIO_Init(EXTI00_HOME_SYS_WKUP_GPIO_Port, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = EXTI06_FP_SYS_WKUP_Pin;
	HAL_GPIO_Init(EXTI06_FP_SYS_WKUP_GPIO_Port, &GPIO_InitStruct);
	HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0);
	HAL_NVIC_SetPriority(EXTI9_5_IRQn, 5, 0);
	HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
	HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0);
	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

void timer16_init(void)
{
    htim16.Instance = TIM16;
	htim16.Init.Prescaler = 800 - 1;
	htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim16.Init.Period = 1000 - 1;
	htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
	htim16.Init.RepetitionCounter = 0;
	htim16.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	if (HAL_TIM_Base_Init(&htim16) != HAL_OK) {
		Error_Handler();
	}
}

void app_button_init(void)
{
	bsp_button_init();
    timer16_init();
	for (uint16_t num = 0; num < BUTTONS_NUMBER; num++) {
		bsp_event_button_action_assign(num, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_DEFAULT);
		m_events_list[num].event.push = BSP_EVENT_NOTHING;
		m_events_list[num].event.push_long = BSP_EVENT_NOTHING;
		m_events_list[num].event.push_long_3s = BSP_EVENT_NOTHING;
		m_events_list[num].event.release = BSP_EVENT_NOTHING;
	}
	bsp_button_startup_configure();
}

void button_wkup_enable(void)
{
	HAL_PWR_DisableWakeUpPin(EXTI00_HOME_SYS_WKUP_Pin);
	HAL_PWR_EnableWakeUpPin(EXTI00_HOME_SYS_WKUP_Pin);
//	HAL_PWR_DisableWakeUpPin(EXTI08_BUTTON0_Pin | EXTI09_BUTTON1_Pin | EXTI10_BUTTON2_Pin | \
//							 EXTI11_BUTTON3_Pin | EXTI12_BUTTON4_Pin | EXTI13_BUTTON5_Pin);
//	HAL_PWR_EnableWakeUpPin(EXTI08_BUTTON0_Pin | EXTI09_BUTTON1_Pin | EXTI10_BUTTON2_Pin | \
							EXTI11_BUTTON3_Pin | EXTI12_BUTTON4_Pin | EXTI13_BUTTON5_Pin);
	/* add your code... */
	/* add your code... */
	HAL_PWREx_EnableInternalWakeUpLine();
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF1 | PWR_FLAG_WUF2 | PWR_FLAG_WUF3 | PWR_FLAG_WUF4 | PWR_FLAG_WUF5);
}

void button_wkup_disable(void)
{
    HAL_PWREx_DisableInternalWakeUpLine();
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF1 | PWR_FLAG_WUF2 | PWR_FLAG_WUF3 | PWR_FLAG_WUF4 | PWR_FLAG_WUF5);
}

void StartTaskButton(void const *argument)
{
#if 0
	const TickType_t xFrequency = BUTTON_TICKS_DEBOUNCE;
	for(;;) {
		bsp_event_t button_event = button_state_machine(NULL, 0);
		if (BSP_EVENT_NOTHING != button_event) {
			app_button_event_process(button_event);
		}
		osDelay(xFrequency);
	}
#else
	for (;;) {
        osEvent signal = osSignalWait(0xFF, osWaitForever);  /**<  */
        if (signal.status == osEventSignal) {
            bsp_event_t event = (bsp_event_t)signal.value.signals;
            app_button_event_process(event);
        }
	}
#endif
}

static void app_button_event_process(bsp_event_t event)
{
	switch (event) {
	case BSP_EVENT_KEY_0:
		dbg_printf("button_0.\r\n");
		break;
	case BSP_EVENT_KEY_1:
		dbg_printf("button_1.\r\n");
        osSignalSet(myTaskRunStateHandle, 1);
		break;
	case BSP_EVENT_KEY_2:
		dbg_printf("button_2.\r\n");
		break;
	case BSP_EVENT_KEY_3:
		dbg_printf("button_3.\r\n");
//        exflash_chip_erase();
		break;
	case BSP_EVENT_KEY_4:
		dbg_printf("button_4.\r\n");
		db_message_send(DB_READ, NULL);
		break;
	case BSP_EVENT_KEY_5:
		dbg_printf("button_5.\r\n");
		db_message_send(DB_WRITE, NULL);
		break;
	case BSP_EVENT_KEY_6:
		dbg_printf("button_6.\r\n");
//		db_message_send(DB_UPDATE, NULL);
		break;
	case BSP_EVENT_MODE_SELECT:
        fp_sensor_wkup();
		dbg_printf("mode select.\r\n");
		db_message_send(DB_FORMAT, NULL);
		break;
	case BSP_EVENT_SLEEP:
		dbg_printf("go to sleep.\r\n");
		while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {}
		break;
    case BSP_EVENT_WAKEUP:
        dbg_printf("fp sensor touched.\r\n");
        fp_sensor_wkup();
        break;
	default:
		dbg_printf("unknow button event.\r\n");
		break;
	}
}

static bool bsp_event_button_action_assign(bsp_button_id_t button, bsp_button_action_t action, bsp_event_t event)
{
	bool retval = true;
	if (button < BUTTONS_NUMBER) {
		if (event == BSP_EVENT_DEFAULT) {
			event = BSP_EVENT_NOTHING;
		}
		switch (action) {
		case BSP_BUTTON_ACTION_PUSH:
			m_events_list[button].event.push = event;
			break;
		case BSP_BUTTON_ACTION_RELEASE:
			m_events_list[button].event.release = event;
			break;
		case BSP_BUTTON_ACTION_PUSH_LONG:
			m_events_list[button].event.push_long = event;
			break;
		case BSP_BUTTON_ACTION_PUSH_LONG_3S:
			m_events_list[button].event.push_long_3s = event;
			break;
		default:
			retval = false;
			break;
		}
	} else {
		retval = false;
	}
	return retval;
}

static bool bsp_button_startup_configure(void)
{
	bool retval = false;
	retval = bsp_event_button_action_assign(BSP_BUTTON_HOME, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_MODE_SELECT);
	retval = bsp_event_button_action_assign(BSP_BUTTON_HOME, BSP_BUTTON_ACTION_PUSH_LONG_3S, BSP_EVENT_SLEEP);
	retval = bsp_event_button_action_assign(BSP_BUTTON_1, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_KEY_1);
	retval = bsp_event_button_action_assign(BSP_BUTTON_2, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_KEY_2);
	retval = bsp_event_button_action_assign(BSP_BUTTON_3, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_KEY_3);
	retval = bsp_event_button_action_assign(BSP_BUTTON_4, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_KEY_4);
	retval = bsp_event_button_action_assign(BSP_BUTTON_5, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_KEY_5);
	retval = bsp_event_button_action_assign(BSP_BUTTON_6, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_KEY_6);
    retval = bsp_event_button_action_assign(BSP_BUTTON_FP, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_WAKEUP);
	return retval;
}

static bsp_event_t button_state_machine(bool *bsp_button_is_press, uint16_t period_ticks)
{
    bool button_is_press = false;
	bsp_event_t event = BSP_EVENT_NOTHING;
	for(uint16_t button = 0; button < BUTTONS_NUMBER; button++) {
		if (m_button_auth_masks & (1 << button)) {
			uint8_t pin_state = HAL_GPIO_ReadPin(m_events_list[button].gpio_port, m_events_list[button].gpio_pin);
			if (pin_state == GPIO_PIN_SET) {
                button_is_press = true;
				m_events_list[button].ticks += period_ticks;
				if (m_events_list[button].action == BSP_BUTTON_ACTION_RELEASE) {
					m_events_list[button].action = BSP_BUTTON_ACTION_PUSH;
				}
			} else {
				m_events_list[button].action = BSP_BUTTON_ACTION_RELEASE;
			}
			switch (m_events_list[button].action) {
			case BSP_BUTTON_ACTION_PUSH:
				if (m_events_list[button].ticks == BUTTON_TICKS_DEBOUNCE) {
					event = m_events_list[button].event.push;
				} else if (m_events_list[button].ticks >= BUTTON_TICKS_PUSH_LONG) {
					m_events_list[button].action = BSP_BUTTON_ACTION_PUSH_LONG;
					if (m_events_list[button].event.push_long != BSP_EVENT_NOTHING) {
						event = m_events_list[button].event.push_long;
					}
				}
				break;
			case BSP_BUTTON_ACTION_RELEASE:
				m_events_list[button].ticks = 0;
				button_auth_cancel(1 << button);
				m_events_list[button].action = BSP_BUTTON_ACTION_RELEASE;
				if (m_events_list[button].event.release != BSP_EVENT_NOTHING) {
					event = m_events_list[button].event.release;
				}
				break;
			case BSP_BUTTON_ACTION_PUSH_LONG:
				if (m_events_list[button].ticks >= BUTTON_TICKS_PUSH_LONG_3S) {
					m_events_list[button].action = BSP_BUTTON_ACTION_PUSH_LONG_3S;
					if (m_events_list[button].event.push_long_3s != BSP_EVENT_NOTHING) {
						event = m_events_list[button].event.push_long_3s;
					}
				}
				break;
			case BSP_BUTTON_ACTION_PUSH_LONG_3S:
				break;
			default:
				break;
			}
		}
	}
    *bsp_button_is_press = button_is_press;
	return event;
}

/* Public function definiton ------------------------------------------------ */
void button_event_timer_handler(void)
{
    bool button_is_press = false;
	uint32_t notify_value = 0;
    bsp_event_t event = button_state_machine(&button_is_press, 10);
    if (button_is_press) {
        if (event != BSP_EVENT_NOTHING) {
            notify_value = (uint32_t)event;
            int32_t v = osSignalSet(myTaskButtonHandle, notify_value);
        }
    } else {
        HAL_TIM_Base_Stop_IT(&htim16);
    }
}

static uint8_t button_trigger_push(uint16_t gpio_pin)
{
	uint8_t retval = 0xff;
	switch (gpio_pin) {
	case EXTI00_HOME_SYS_WKUP_Pin:
		retval = BUTTON_0;
		break;
	case EXTI08_BUTTON0_Pin:
		retval = BUTTON_1;
		break;
	case EXTI09_BUTTON1_Pin:
		retval = BUTTON_2;
		break;
	case EXTI10_BUTTON2_Pin:
		retval = BUTTON_3;
		break;
	case EXTI11_BUTTON3_Pin:
		retval = BUTTON_4;
		break;
	case EXTI12_BUTTON4_Pin:
		retval = BUTTON_5;
		break;
	case EXTI13_BUTTON5_Pin:
		retval = BUTTON_6;
		break;
    case EXTI06_FP_SYS_WKUP_Pin:
		retval = BUTTON_7;
		break;
	default:
		break;
	}
	return retval;
}

static bool button_try_get_auth(uint16_t button_mask)
{
	if (button_mask & BSP_BUTTON_MASKS_PWD) {                       /**<  */
		if ((m_button_auth_masks & BSP_BUTTON_MASKS_PWD) == 0) {    /**<  */
			m_button_auth_masks |= button_mask;
		} else {                                                    /**<  */
			return false;
		}
	} else if (button_mask & BSP_BUTTON_MASKS_FUNCTION) {           /**<  */
        if (1) {
            
        }
		m_button_auth_masks |= button_mask;                         /**<  */
	}
	return true;
}

static bool button_auth_cancel(uint16_t button_mask)
{
	m_button_auth_masks &= ~button_mask;
	return true;
}

bool button_exti_irq_handler(uint16_t gpio_pin, uint32_t *notify_value)
{
	uint8_t button = button_trigger_push(gpio_pin);
	if (button < BUTTONS_NUMBER) {      /* 尝试授权 */
		return button_try_get_auth(1 << button);
	}
	return false;
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    BaseType_t xHigherPriorityTaskWoken;
	uint32_t notify_value = 0;
	uint32_t retval = 0;
	retval = taskENTER_CRITICAL_FROM_ISR();
	if (button_exti_irq_handler(GPIO_Pin, &notify_value)) {
        HAL_TIM_Base_Start_IT(&htim16);
	}
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	taskEXIT_CRITICAL_FROM_ISR(retval);
}
#endif

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值