ESP8266 GPIO接口(按键中断,软件定时LED)

GPIO接口

SDK使用ESP8266_NONOS_SDK V3.0
此文记录在使用GPIO口时,功能复用以及IO中断的问题。

GPIO复用

接口 位于 /ESP8266_NONOS_SDK/include/eagle_soc.h和gpio.h。
管脚功能选择宏定义:PIN_FUNC_SELECT(PIN_NAME,FUNC);对于不同的引脚,PIN_NAME不同,IO口复用的功能FUNC也不同。由于我在配置GPIO14时,不小心错写成FUNC_GPIO4,IO口电平死活不会反转。。。

以8266的MTMS为例,说明GPIO功能的选择。
功能选择寄存器PERIPHS_IO_MUX_MTMS_U(不同的GPIO,该寄存器不同)
配置的时候,请参考引脚配置表,如下图
在这里插入图片描述
需要注意的是,如果需要配置为FUNCTION3,应该往寄存器对应的位中写2,如果需要配置为FUNCTION2,应该往寄存器对应的位中写1,以此类推。

    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);//led
    GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 1);

在这里插入图片描述

GPIO中断

GPIO中断相关宏:
ETS_GPIO_INTR_ENABLE() //开 GPIO 中断
ETS_GPIO_INTR_DISABLE() //关 GPIO 中断
ETS_GPIO_INTR_ATTACH(func, arg) //注册 GPIO 中断处理函数

GPIO中断相关函数:gpio_pin_intr_state_set
在这里插入图片描述
0是失能; 1是上升沿触发; 2是下降沿; 3是边沿;4是低电平;5是高电平

中断加延时

参考:https://www.jianshu.com/p/ec424a87ded0
简单说下这种处理方式,在user_init()函数中加入按键初始化,注册中断处理函数以及设置为下降沿触发方式。然后在中断处理函数里面判断IO口状态,再delay延时后再去判断IO口状态,来最终判断是否按键按下。实际使用发现去抖效果并不好,会多次触发。而且个人也不喜欢这个延时方式。
于是在网上搜索发现sdk里面自带了按键的API,下面主要介绍这个以及遇到的问题。

中断加软件定时器

参考:https://blog.youkuaiyun.com/qq_15647227/article/details/52218376
相关API不再介绍,参考链接即可,里面说的很详细了。使用时只需要将key.c和key.h放入你工程目录app下面的相应位置即可。key.c里面改为#include “key.h”。
说下不一样的,我是一个按键既有短按功能,也有长按功能。按照sdk的流程是有点问题的,长按后松手也会触发短按程序。
先贴初始化代码:

void usr_key_init(void)//按键初始化
{
	switch_signle = key_init_single(GPIO_KEY_ID,
									GPIO_KEY_NAME,
									GPIO_KEY_FUNC,
									&usr_longkey_process,
									&usr_shortkey_process);
	switch_param.key_num = 1;
	switch_param.single_key = &switch_signle;
	key_init(&switch_param);
}

按键处理函数:

static void usr_shortkey_process()
{
    os_timer_disarm(&led_time);//定时器设置
    os_timer_setfn(&led_time, (os_timer_func_t *)led_callback, NULL);
    os_timer_arm(&led_time, 500, 1);//0.5s
    os_printf("shortkey press!!!\r\n");
}

static void usr_longkey_process()
{
    os_timer_disarm(&led_time);//定时器设置
    os_timer_setfn(&led_time, (os_timer_func_t *)led_callback, NULL);
    os_timer_arm(&led_time, 2000, 1);//2s
    os_printf("longkey press!!!\r\n");
}

针对长按触发后松手会触发短按的现象,我对key.c相关函数做了修改。
首先我在5s定时器回调函数中置位key_level=2;

LOCAL void ICACHE_FLASH_ATTR
key_5s_cb(struct single_key_param *single_key)
{
    os_timer_disarm(&single_key->key_5s);

    // low, then restart
    if (0 == GPIO_INPUT_GET(GPIO_ID_PIN(single_key->gpio_id))) {
    	single_key->key_level = 2;
        if (single_key->long_press) {
            single_key->long_press();
        }
    }
}

在key_intr_handler()函数中加入长按松手后检测判断。

else if (keys->single_key[i]->key_level == 2){
            	keys->single_key[i]->key_level = 1;
            	gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_NEGEDGE);
            }

这样就实现了一个按键的短按和长按功能。

软件定时器

相对来说,软定时器没遇到什么问题。大家可以参考:https://blog.youkuaiyun.com/xh870189248/article/details/78155357
只要注意在初始化前先关闭该定时器,同一个定时器不能同时使用。还有就是设置好回调函数。我的回调函数如下:

void ICACHE_FLASH_ATTR
led_callback(void) // test
{
//	os_printf("What!\r\n");
	if (led_status == true)
	{
		GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 0);
		led_status = false;
	}
	else
	{
		GPIO_OUTPUT_SET(GPIO_ID_PIN(14), 1);
		led_status = true;
	}
}

以上便是我使用gpio遇到的问题了,欢迎不妥之处给予指正。

<think>好的,用户想了解如何使用STM32通过ESP8266上传LED状态。我需要结合之前提供的引用内容来回答。首先,引用[2]提到开发板有4个LEDESP8266模块,型号是ESP-12F,STM32是F103C8T6。引用[3]给出了项目地址,可能包含相关代码。引用[1]提到烧录程序后通过串口调试工具确认ESP8266连接WiFi并发送数据。 首先,应该明确硬件连接部分。ESP8266通常通过串口与STM32通信,比如USART2。用户需要将ESP8266的TX、RX连接到STM32对应的引脚,并确保供电稳定。然后,配置STM32的GPIO来控制LED,比如GPIOA的Pin0到Pin3,设置为输出模式。 接下来是ESP8266的配置。需要发送AT指令让模块连接WiFi,并建立TCP连接。步骤可能包括设置模式为STA,连接到路由器的SSID和密码,然后连接到服务器IP和端口。这些AT指令需要从STM32通过串口发送给ESP8266,并处理返回的响应。 在代码部分,可能需要初始化USART和GPIO,然后发送AT指令。例如,AT+CWMODE=1设置模块为STA模式,AT+CWJAP="SSID","password"连接WiFi,AT+CIPSTART建立TCP连接。然后,STM32读取LED的状态,拼接成HTTP请求或自定义协议的数据,通过AT+CIPSEND发送。 另外,引用[1]提到观察串口输出确认数据正常,所以在代码中需要确保调试信息通过串口输出,方便用户检查问题。例如,使用printf函数通过USART1发送调试信息到PC端的串口工具。 用户可能需要示例代码的结构,比如主循环中读取按键LED状态,然后触发数据上传。需要处理ESP8266的响应,比如判断是否返回"OK"或"ERROR",以进行错误处理或重试。 还需要考虑数据格式,如何将LED状态封装成服务器能识别的格式。比如使用GET请求,URL中包含LED的状态参数,或者POST JSON数据。这取决于服务器端的接口设计。 最后,参考项目地址中的代码可能提供更具体的实现,比如如何组织代码模块,处理AT指令的发送和接收,以及状态机的实现,确保非阻塞式处理,避免长时间等待影响系统响应。 可能的问题包括:AT指令超时处理,网络断开重连机制,LED状态变化的检测方式(轮询或中断),以及如何优化数据传输以减少流量。需要确保示例代码简洁,并注释清晰,方便用户理解。 总结步骤:硬件连接->配置ESP8266->STM32控制LED并读取状态->封装数据并通过ESP8266发送->处理服务器响应。同时,提供代码框架和关键函数,引用项目地址供用户进一步参考。</think>### STM32通过ESP8266上传LED状态实现方法 #### 一、硬件连接与配置 1. **ESP8266接线** - 使用USART2连接ESP8266模块(参考引用[2]) - 接线示例: ``` STM32 USART2_TX -> ESP8266_RX STM32 USART2_RX -> ESP8266_TX ESP8266_VCC -> 3.3V ESP8266_GND -> GND ``` 2. **LED控制引脚配置** - 假设LED连接在GPIOA的Pin0-Pin3(参考引用[2]) ```c GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); ``` #### 二、ESP8266网络配置流程 通过AT指令完成以下操作(波特率建议115200): 1. **基础配置** ```AT+CWMODE=1```(设置为STA模式) ```AT+CIPMUX=0```(单连接模式) 2. **连接WiFi** ```AT+CWJAP="your_SSID","your_password"``` 3. **建立TCP连接** ```AT+CIPSTART="TCP","your_server_ip",your_port``` #### 三、关键代码实现 ```c // USART2发送字符串函数 void ESP8266_SendCmd(char *cmd) { while(*cmd != '\0') { USART_SendData(USART2, *cmd++); while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); } } // 上传LED状态函数 void Upload_LED_Status(void) { char http_cmd[128]; uint8_t led_status = GPIO_ReadOutputData(GPIOA) & 0x0F; // 读取PA0-PA3 sprintf(http_cmd, "AT+CIPSEND=%d\r\n", strlen(led_status_json)); ESP8266_SendCmd(http_cmd); Delay_ms(100); sprintf(led_status_json, "{\"LED\":\"%04b\"}", led_status); // 二进制格式状态 ESP8266_SendCmd(led_status_json); } ``` #### 四、调试验证 1. 使用USART1输出调试信息(参考引用[1]) ```c printf("ESP8266 Response: %s\r\n", uart1_buffer); ``` 2. 通过串口调试工具观察: - WiFi连接成功提示:```WIFI CONNECTED``` - 数据发送成功响应:```SEND OK``` #### 五、完整实现流程 1. 初始化系统时钟和GPIO 2. 配置USART2与ESP8266通信 3. 发送AT指令建立网络连接 4. 主循环中定时调用`Upload_LED_Status()` 5. 异常处理:检测```ERROR```响应并重试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值