第一次按下开灯,第二次按下关灯,通过状态机机制实现该功能

一、user_app.c

void* state_off(LightSwitcher* self,Event e)
{
	if(e == BUTTON_PRESSED)
	{


		return state_on;
	}

	return state_off;
}

void* state_on(LightSwitcher* self,Event e)
{
	if(e==BUTTON_PRESSED)
	{

		return state_off;
	}
	return state_on;
}

void feed(LightSwitcher* self,Event e)
{
	self->current_state = self->current_state(self,e);
}

void init_light_switcher(LightSwitcher* self)
{
	self->current_state = state_off;
}
LightSwitcher switcher;
u8 button_event =0;
//**gy_button**//
void gy_button_1ms_timer(/*u32 count*/void)
{
	static u8 gy_button_count = 0;//延时消抖计数
	if(gy_button_press == gy_button_read())//如果按键按下
	{
		if(gy_button_count == GY_BUTTON_PRESS_COUNT_MAX)
		{
#if(GY_DEV_TYPE == GY_DEV_1005 || GY_DEV_TYPE == GY_DEV_1006 || GY_DEV_TYPE == GY_DEV_1007)
			gy_factory_reset_ready();
#else
			/*factory_reset();
			show_factory_reset();
			start_reboot();*/
#endif
			//LOG_USER_MSG_INFO(0,0,"button_press",0);
			button_event=1;
			if(button_event)
			{
				button_event=0;
				feed(&switcher,BUTTON_PRESSED);
				//LOG_USER_MSG_INFO(0,0,"button_press",0);
				//feed();
			}
		}
		gy_button_count++;
	}
	else if(gy_button_release == gy_button_read())//如果按键抬起
	{
		if(gy_button_count)
		{
			//LOG_USER_MSG_INFO(0,0,"gy_button_count",0);
			gy_button_count = 0;
		}
	}
}

二、user_app.h

typedef enum{
	BUTTON_PRESSED,
	BUTTON_RELEASE,
}Event;

typedef struct LightSwitcher LightSwitcher;

typedef void* (*State)(LightSwitcher*,Event);
struct LightSwitcher{
	State current_state;
};
void* state_on(LightSwitcher* self,Event e);
void* state_off(LightSwitcher* self,Event e);
void init_light_switcher(LightSwitcher* self);
void feed(LightSwitcher* self,Event e);

三、通用代码

在泰凌微8258环境下,结合提供的状态机代码实现按键控制LED开关的步骤如下:

1. 硬件配置及头文件引入

#include "proj/mcu/config.h"
#include "vendor/common/gpio.h"
#include "vendor/common/uart.h"

#define LED_PIN GPIO_PD5 // 假设LED连接在PD5
#define BUTTON_PIN GPIO_PD6 // 假设按键连接在PD6
#define DEBOUNCE_DELAY_MS 50 // 去抖动延时

typedef enum {
    BUTTON_PRESSED,
    BUTTON_RELEASED
} Event;

typedef struct LightSwitcher {
    void* (*current_state)(struct LightSwitcher*, Event);
} LightSwitcher;

volatile bool button_event = false;
volatile u32 button_press_time = 0;

2. GPIO及中断初始化

void gpio_init() {
    // LED配置为输出,初始熄灭
    gpio_set_output(LED_PIN);
    gpio_write(LED_PIN, 0);
    
    // 按键配置为输入,启用内部上拉
    gpio_set_input(BUTTON_PIN);
    gpio_enable_pullup(BUTTON_PIN);
    
    // 配置下降沿中断(按键按下时拉低电平)
    gpio_set_interrupt(BUTTON_PIN, POL_FALLING);
}

// 中断服务函数(在SDK的irq_handler.c中添加)
void button_isr(void) {
    static u32 last_time = 0;
    u32 now = clock_time();
    
    if ((now - last_time) > DEBOUNCE_DELAY_MS * 1000) { // clock_time单位是微秒
        button_event = true;
        last_time = now;
    }
}

3. 修改状态机控制LED

void* state_off(LightSwitcher* self, Event e) {
    if (e == BUTTON_PRESSED) {
        gpio_write(LED_PIN, 1); // 点亮LED
        return state_on;
    }
    return state_off;
}

void* state_on(LightSwitcher* self, Event e) {
    if (e == BUTTON_PRESSED) {
        gpio_write(LED_PIN, 0); // 熄灭LED
        return state_off;
    }
    return state_on;
}

void feed(LightSwitcher* self, Event e) {
    if (self->current_state) {
        self->current_state = self->current_state(self, e);
    }
}

void init_light_switcher(LightSwitcher* self) {
    self->current_state = state_off;
}

4. 主函数整合逻辑

int main() {
    LightSwitcher switcher;
    cpu_wakeup_init();
    gpio_init();
    init_light_switcher(&switcher);
    
    while(1) {
        if (button_event) {
            button_event = false;
            feed(&switcher, BUTTON_PRESSED);
        }
        sleep_us(1000); // 低功耗处理
    }
    return 0;
}

关键点说明:

  1. GPIO配置

    • LED引脚设为输出模式并初始置低

    • 按键引脚启用内部上拉,配置下降沿中断

  2. 去抖动处理

    • 在中断中记录时间戳,通过时间差过滤抖动

    • 使用clock_time()获取系统时间(单位微秒)

  3. 状态机改进

    • 在状态转换时直接操作GPIO电平

    • BUTTON_PRESSED事件触发状态切换

  4. 低功耗优化

    • 主循环中使用sleep_us()降低功耗

    • 实际开发中可结合TLSR芯片的休眠模式

注意事项:

  1. 根据实际硬件连接修改LED_PIN和BUTTON_PIN定义

  2. 确保SDK中已启用GPIO中断功能

  3. 若使用硬件消抖,可适当减小软件去抖时间

  4. 生产代码建议添加看门狗处理

该方案实现了:

  • 按键按下→LED状态翻转

  • 硬件消抖+软件二次验证

  • 低功耗待机设计

  • 清晰的状态机维护逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值