代码分析
-
初始化分区
-
初始化串口(串口1 串口2都为57600) 初始化串口(串口1 串口2都为57600)
-
打印sdk版本
-
按键初始化(简短的单按钮初始化 长按 短按 按键驱动程序初始化 IO口初始化)
4.1 按键回调函数(长按函数 短按函数 内含提示灯)
4.2 长按函数为空
4.3短按函数为
4.3.1 WiFi准备(设置模式,ssid password 加密模式 信标间隔时槽 通道号(即通频带) 最大连接数 隐藏ssid 保存到flash)
4.3.2 TCP准备端口8266(分配空间 设置类型为TCP协议 本地端口 注册连接成功回调函数(server_listen)和重新连接回调函数(server_recon))创建 TCP server,建立侦听 设置超时断开时间
4.3.2 .1注册连接成功回调函数(server_listen)入口 用户tcp类型地址
4.3.2 .1.1 回调函数 接收(用cJSON解析接收的包 判断包是否为空 创建对象 给对象传递数据 打印对象 1. 如果为空 创建对象 提示json错误 2.不为空 创建对象 继承WiFi ssid password state(为0(成功连接到指定的WiFi 检测是否有IP,有代表连接成功) 为1表示连接AP) 打印信息)AP和WiFi区别是IP地址
4.3.2 .1.2发送(设置为station模式 发送信息) 断开
4.3.2 .2重新连接回调函数(server_recon) 返回错误代码和类型 -
设置ESP8266 station 上电是否自动连接已记录的AP(路由),默认为自动连接
-
设置为无睡眠模式
-
定时器回调函数 检查WIFI状态,用IO口的灯变化显示出WiFi状态打印sdk版本 按键初始化定时器回调函数 检查WIFI状态,用IO口的灯变化显示出WiFi状态
代码
user_main.c
#include "driver/uart.h" //串口0需要的头文件
#include "osapi.h" //串口1需要的头文件
#include "user_interface.h" //WIFI连接需要的头文件
#include "espconn.h"//TCP连接需要的头文件
#include "mem.h" //系统操作需要的头文件
#include "gpio.h" //端口控制需要的头文件
#include "cJSON.h"
#include "hal_key.h"
struct espconn user_tcp_espconn;
os_timer_t checkTimer_wifistate;
//按键定义
#define GPIO_KEY_NUM 1
#define KEY_0_IO_MUX PERIPHS_IO_MUX_MTMS_U
#define KEY_0_IO_NUM 14
#define KEY_0_IO_FUNC FUNC_GPIO14
LOCAL key_typedef_t * singleKey[GPIO_KEY_NUM];
LOCAL keys_typedef_t keys;
bool isConnected = false;
void Check_WifiState(void)//检查WIFI状态
{
uint8 status = wifi_station_get_connect_status();//查询ESP8266 WIFI station 接口连接AP的状态
if (status == STATION_GOT_IP)//检测是否连接AP并且返回信息
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(15), 0); //设置IO口输出电平
GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);
wifi_set_opmode(0x01); //WIFI模式为station
}
else
{
GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0); //GPIO15 低电平输出
GPIO_OUTPUT_SET(GPIO_ID_PIN(15), 1); //GPIO15 低电平输出
}
}
void wifiStationConnect(char *ssid, char *psw)//WiFi重新连接
{
os_printf(" wifiStationConnect name:%s \n", ssid);
os_printf(" wifiStationConnect psw :%s \n", psw);
struct station_config stationConf;
os_strcpy(stationConf.ssid, ssid); //路由器的用户名
os_strcpy(stationConf.password, psw); //路由器的密码
wifi_station_set_config(&stationConf); //设置WiFi station接口配置,并保存到 flash
wifi_station_connect(); //连接路由器
}
void ICACHE_FLASH_ATTR server_recv(void *arg, char *pdata, unsigned short len) //注册 TCP 连接成功建立后的回调函数接收
{
//判断是否为json数据
cJSON *root = cJSON_Parse(pdata);//解析数据 返回一个解析成功的值 调用cJSON.c库
if (!root)
{
os_printf("Error before: [%s]\n", cJSON_GetErrorPtr());/*用于分析失败的分析。这将返回指向分析错误的指针。你可能需要找几个字符来解释它。当cjson_parse()返回0时定义。当cjson_parse()成功时为0。*/
cJSON * Result = cJSON_CreateObject();/*这些调用创建适当类型的CJSON项。 创造对象分配空间 大小为6 范围为0到6 */
cJSON_AddNumberToObject(Result, "status", 3);//添加数字到对象 对象 名字 数字
cJSON_AddStringToObject(Result, "msg", "json error!");//添加字符串到对象 对象 名字 字符串
char *succeedData = cJSON_Print(Result);//将CJSON项/实体/结构呈现为文本。
char data[1024];
os_sprintf(data, "%s", succeedData); //打印Result
espconn_send((struct espconn *) arg, data, strlen(data));//通过WIFI发送数据
return;
}
else
{
char *ssid, *psw;
int state;
//解析字段
cJSON *ssid_json = cJSON_GetObjectItem(root, "ssid");
cJSON *psw_json = cJSON_GetObjectItem(root, "psw");
cJSON *state_json = cJSON_GetObjectItem(root, "state");
state = state_json->valueint;
//对state 进行剖析
switch (state)
{ //当前wifi的连接情况查询
case 0://成功连接到指定的WiFi
if (STATION_GOT_IP == wifi_station_get_connect_status())
{
cJSON * Result = cJSON_CreateObject();
cJSON_AddNumberToObject(Result, "status", 0);
cJSON_AddStringToObject(Result, "msg", "connect succeed!");
char *succeedData = cJSON_Print(Result);
char data[1024];
os_sprintf(data, "%s", succeedData);
espconn_send((struct espconn *) arg, data, strlen(data));
isConnected = true;
}
else
{
//未连接到指定的WiFi
cJSON * Result = cJSON_CreateObject();
cJSON_AddNumberToObject(Result, "status", 1);
cJSON_AddStringToObject(Result, "msg", "connect fail!");
char *succeedData = cJSON_Print(Result);
char data[1024];
os_sprintf(data, "%s", succeedData);
espconn_send((struct espconn *) arg, data, strlen(data));
}
break;
//1表示连接AP
case 1:
if (ssid_json && psw_json)
{
ssid = ssid_json->valuestring;
psw = psw_json->valuestring;
wifiStationConnect(ssid, psw);//WiFi重新连接
}
else {
os_printf(" width null! \n");
}
cJSON_Delete(root);//释放内存
cJSON * Result = cJSON_CreateObject();//构造json
cJSON_AddNumberToObject(Result, "status", 2);
cJSON_AddStringToObject(Result, "msg", "AP connectting!");
char *succeedData = cJSON_Print(Result);
char data[1024];
os_sprintf(data, "%s", succeedData);
espconn_send((struct espconn *) arg, data, strlen(data));
break;
}
}
}
void ICACHE_FLASH_ATTR server_sent(void *arg) //注册 TCP 连接成功建立后的回调函数发送
{
os_printf("send data succeed!\r");
if (isConnected)
{
wifi_set_opmode(0x01); //设置为STATION模式
}
}
void ICACHE_FLASH_ATTR server_discon(void *arg) //注册 TCP 连接成功建立后的回调函数断开
{
os_printf("conect diable! \r");
}
void ICACHE_FLASH_ATTR server_listen(void *arg) //注册 TCP 连接成功建立后的回调函数
{
struct espconn *pespconn = arg;
espconn_regist_recvcb(pespconn, server_recv); //接收
espconn_regist_sentcb(pespconn, server_sent); //发送
espconn_regist_disconcb(pespconn, server_discon); //断开
}
void ICACHE_FLASH_ATTR server_recon(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
{
os_printf("连接错误,错误代码为:%d\r\n", err); //%d,用来输出十进制整数
}
void Inter213_InitTCP(uint32_t Local_port)
{
user_tcp_espconn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); //分配空间
user_tcp_espconn.type = ESPCONN_TCP; //设置类型为TCP协议
user_tcp_espconn.proto.tcp->local_port = Local_port; //本地端口
//注册连接成功回调函数和重新连接回调函数
espconn_regist_connectcb(&user_tcp_espconn, server_listen); //注册 TCP 连接成功建立后的回调函数
espconn_regist_reconcb(&user_tcp_espconn, server_recon); //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
espconn_accept(&user_tcp_espconn); //创建 TCP server,建立侦听
espconn_regist_time(&user_tcp_espconn, 180, 0); //设置超时断开时间 单位:秒,最大值:7200 秒
//如果超时时间设置为 0,ESP8266 TCP server 将始终不会断开已经不与它通信的 TCP client,不建议这样使用。
}
void WIFI_Init()
{
struct softap_config apConfig;
wifi_set_opmode(0x03); //设置为station+soft-AP模式,保存到 flash
apConfig.ssid_len = 10; //设置ssid长度
os_strcpy(apConfig.ssid, "xaiofang"); //设置ssid名字
os_strcpy(apConfig.password, "12345678"); //设置密码
apConfig.authmode = 3; //设置加密模式
apConfig.beacon_interval = 100; //信标间隔时槽100 ~ 60000 ms
apConfig.channel = 1; //通道号1 ~ 13
apConfig.max_connection = 4; //最大连接数
apConfig.ssid_hidden = 0; //隐藏SSID
wifi_softap_set_config(&apConfig); //设置 WiFi soft-AP 接口配置,并保存到 flash
}
void wifiConnectCb(uint8_t status)
{
}
LOCAL void ICACHE_FLASH_ATTR keyLongPress(void)//长按按键
{
}
LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) //短按按键
{
os_printf(" key short...\r\n");
WIFI_Init(); //WIFI 准备
Inter213_InitTCP(8266); //本地端口
}
//按键初始化
LOCAL void ICACHE_FLASH_ATTR keyInit(void)
{
singleKey[0] = keyInitOne(KEY_0_IO_NUM, KEY_0_IO_MUX, KEY_0_IO_FUNC,
keyLongPress, keyShortPress);//简短的单按钮初始化 长按 短按
keys.singleKey = singleKey;
keyParaInit(&keys);//简短按钮驱动程序初始化
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); //GPIO12初始化(管脚功能选择)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); //GPIO15初始化(管脚功能选择)
}
void user_init()
{
uart_init(57600, 57600); //设置串口0和串口1的波特率
os_printf("-----SDK version:%s------\n", system_get_sdk_version());//打印版本号
keyInit(); //按键准备
wifi_station_set_auto_connect(1);//设置ESP8266 station 上电是否自动连接已记录的AP(路由),默认为自动连接1 0为不自动
wifi_set_sleep_type(NONE_SLEEP_T); //set none sleep mode,默认为睡眠模式(modem-sleep参数为sleep_type)
os_timer_disarm(&checkTimer_wifistate); //取消定时器定时
os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,
NULL); //设置定时器回调函数 检查WIFI状态
os_timer_arm(&checkTimer_wifistate, 1000, true); //启动定时器,单位:毫秒
}
void user_rf_pre_init()
{
}
keyInitOne(uint8 gpio_id, uint32 gpio_name, uint8 gpio_func, gokit_key_function long_press, gokit_key_function short_press)
/**
*@简短的单按钮初始化
*在这个函数中要完成单键初始化,这里需要结合ESP8266 GPIO寄存器描述文档来设置参数
*@param[in]gpio_id ESP8266 GPIO号码
*@param[in]gpio_name ESP8266 GPIO名称
*@param[in]gpio_func ESP8266 GPIO函数
*@param[in]long_press Long按回调函数地址
*@param[in]._press Short press状态回调函数地址
*@return单按钮结构指针
*/
/**
* @brief button driver initialization
* In the function to complete all the keys GPIO initialization, and open a timer to start the key state monitoring
* @param [in] keys Key Function Global structure pointer
* @return none
* /**
*@简短按钮驱动程序初始化
*在函数中完成所有密钥GPIO初始化,并打开定时器开始密钥状态监控。
*@param[in]keys键函数全局结构指针
*@无返回
*/
*/
void ICACHE_FLASH_ATTR keyParaInit(keys_typedef_t * keys)
{
uint8 tem_i = 0;
if(NULL == keys)
{
return ;
}
//init key timer 准备按键定时器
keys->key_timer_ms = KEY_TIMER_MS;
os_timer_disarm(&keys->key_timer);
os_timer_setfn(&keys->key_timer, (os_timer_func_t *)gokitKeyHandle, keys); //定时器回调函数
keys->keyTotolNum = keyTotolNum;
//Limit on the number keys (Allowable number: 0~12) 数字键的限制(0-12)
if(KEY_MAX_NUMBER < keys->keyTotolNum)
{
keys->keyTotolNum = KEY_MAX_NUMBER;
}
//GPIO configured as a high level input mode GPIO,配置为高级输入模式
for(tem_i = 0; tem_i < keys->keyTotolNum; tem_i++)
{
PIN_FUNC_SELECT(keys->singleKey[tem_i]->gpio_name, keys->singleKey[tem_i]->gpio_func); //管脚功能选择
GPIO_OUTPUT_SET(GPIO_ID_PIN(keys->singleKey[tem_i]->gpio_id), 1); //设置GPIO属性
PIN_PULLUP_EN(keys->singleKey[tem_i]->gpio_name); //管脚使能上拉
GPIO_DIS_OUTPUT(GPIO_ID_PIN(keys->singleKey[tem_i]->gpio_id));
os_printf("gpio_name %d \r\n", keys->singleKey[tem_i]->gpio_id);
}
//key timer start 按键定时器启动
os_timer_arm(&keys->key_timer, keys->key_timer_ms, 1);
}
安卓APK:网络调试助手