C语言的封装与嵌入式开发的完美结合① 封装C语言接口在esp8266上对 smartConfig 二

2019-07-13 09:00发布

一、前言;

     敲写C语言这么久,看见乐鑫的代码很多都是有回调函数,这个和面向对象编程有很多相似的地方,这种回调函数在面向对象语言比如Java中称之为接口;很多小伙伴不理解这个是怎么做到的,其实这个也是非常简单的,下面我将由浅到深给大家剖析整个过程。

玩了这么久的乐鑫的wi-fi芯片,昨晚看到官方微信公告已经把esp32和亚马逊平台完美对接了!恭喜!我下面也要好好学习esp32了!

二、[ 抛砖 ]:我们从一个简单的例子做起;


: 实现的目的:输入2个数字,随时等待我想要结果时候,我就取出来,而且要求是通过回调方法拿到!

二 : 实现的好处:随心所欲想要结果,而且可以在回调方法中做其他的操作!也符合代码整洁之道,如果底层逻辑够复杂的话,可以减少一个主文件的代码之绒!大大地提高了开发效率!

这里写图片描述
实现的过程如下:
  • 首先编写头文件,声明一个回调函数,作为介质传递:
#ifndef CACULATE_H_INCLUDED #define CACULATE_H_INCLUDED //初始化需要相加的2个数传值 void Caculate_Add(int a ,int b); //调用返回2个数相加的数值,并且在回调函数中回调 void Caculate_Get_Result(); //声明一个回调函数类型,形参是 int typedef void (*Caculate_CallBack)(int pdata); //注册回调函数 void registerCaculateCallBack(Caculate_CallBack callBack); #endif // CACULATE_H_INCLUDED
  • 编写驱动文件,so easy
#include #include #include "Caculate.h" int result = 0 ; //回调函数声明,注意不用初始化赋值 Caculate_CallBack mCallBack ; //2个数的逻辑处理函数 void Caculate_Add(int a ,int b){ result =a + b; } void registerCaculateCallBack(Caculate_CallBack tempCallBack){ //从主文件中赋值此给驱动文件的回调函数 mCallBack = tempCallBack; } //开始调用 void Caculate_Get_Result(){ //来时回调 mCallBack(result); }
  • 看看我们的主文件吧:
#include #include #include "Caculate.h" //回调函数 void funCaculateCallBack(int pResult){ //do your things printf("funCaculateCallBack: %d ",pResult); } int main(){ //注册回调函数 registerCaculateCallBack(funCaculateCallBack); //2个数添加操作 Caculate_Add(5,9); //触发回调 Caculate_Get_Result(); return 0; }
  • 看看结果?是不是完美调用了吖?
这里写图片描述

三、[ 引玉 ]:对官方的smartConfig二次封装;


  • 熟悉esp8266 的同学们都知道,其的smartConfig是没有连接失败的回调的,需要自己去判断是否成功配网!那么现在我们上面的原理,来完善下这个不足地方!
    • 第一步:编写一个头文件;
    • 这里我们定义一个结构体,方便我们核对校验码!
#ifndef MSMARTCONFIG_H_INCLUDED #define MSMARTCONFIG_H_INCLUDED typedef enum { xSmartConfig_Status_Succeed = 0, //连接成功 xSmartConfig_Status_Failed = 1, //连接失败 xSmartConfig_Status_Get_Pas = 3, //成功得到手机发来的网关的帐号和密码信息 xSmartConfig_Status_Connectting_GateWay = 4, //正在连接网关 xSmartConfig_Status_Connectting_Early = 5, //未开始连接 } xSmartConfig_Status_Code; typedef void (*xSmartConfig_CallBack)(xSmartConfig_Status_Code statusCode); //开始一键配网 void xSmartConfig_Start(); //注册回调函数 void register_xSmartConfigCallBack(xSmartConfig_CallBack callBack); #endif
  • 第二步:看看我们的驱动文件怎么实现?
    首先我们这个先拿到回调函数,和上面一样,等待触发事件了,我们就调用此回调函数即可,这个就可以在主文件实现同步啦!
    ①:需要注意的是,配网失败的处理,我这个用一个定时器不断地获取ip,如果超过60s,还是没有获取到ip,那么我们就回调说配网失败啦! 下面计时的35,实际计算就是60s左右的!
    ②:配网失败,记得要关闭定时器哦!
int flag = 0; os_timer_t mTimerXSmartConfig; xSmartConfig_CallBack statusCodeDriver; struct station_config *sta_conf; void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata) { switch (status) { case SC_STATUS_FIND_CHANNEL: statusCodeDriver(xSmartConfig_Status_Get_Pas); break; case SC_STATUS_GETTING_SSID_PSWD: statusCodeDriver(xSmartConfig_Status_Get_Pas); break; case SC_STATUS_LINK: os_strcpy(&sta_conf, &pdata); wifi_station_set_config(sta_conf); wifi_station_disconnect(); wifi_station_connect(); statusCodeDriver(xSmartConfig_Status_Connectting_GateWay); break; case SC_STATUS_LINK_OVER: if (pdata != NULL) { statusCodeDriver(xSmartConfig_Status_Succeed); flag = 40; } smartconfig_stop(); break; } } //注册回调函数 void register_xSmartConfigCallBack(xSmartConfig_CallBack tempCallBack) { statusCodeDriver = tempCallBack; } //定時器回调函数 void Check_WifiState() { flag++; if (flag > 35) { struct ip_info ipConfig; wifi_get_ip_info(STATION_IF, &ipConfig); u8 getState = wifi_station_get_connect_status(); if (!(getState == STATION_GOT_IP && ipConfig.ip.addr != 0)) { statusCodeDriver(xSmartConfig_Status_Failed); } os_timer_disarm(&mTimerXSmartConfig); //启动定时器前先取消定时器定时 } } //开始一键配网 void xSmartConfig_Start() { statusCodeDriver(xSmartConfig_Status_Connectting_Early); smartconfig_set_type(SC_TYPE_ESPTOUCH); wifi_set_opmode(STATION_MODE); smartconfig_start(smartconfig_done); os_timer_disarm(&mTimerXSmartConfig); //启动定时器前先取消定时器定时 os_timer_setfn(&mTimerXSmartConfig, (os_timer_func_t *) Check_WifiState, NULL); //设置定时器回调函数 os_timer_arm(&mTimerXSmartConfig, 2000, 1); //启动定时器 }

四、效果图;

这里写图片描述