| 
 | 
 
 
 
                                                                                  2017/9/30  22:30 
![]()  
因为国庆忙着回家,没准备好,所以就选择了小黑板作为本帖子的硬件准备,也是参考社区的一篇文章作为参考的。 
小黑板远程控制soc方案。 ,不走任何商业用途!!我这篇优化了下,增加了定时功能,给想学的小伙伴一点干货。 
![]()  
 
第一步:云端增加产品,新增数据点,自动生成soc方案的代码。 
 
第二步:电路图的设计与程序编写。 
 
第三步:配合手机调试。 
 
![]()  
 
一:云端增加产品,新增数据点。 
 
 
       步骤①:选择通讯方式为:wifi ,数据传输方式:定长。 
 
   
 
     步骤②:定义三个数据点: 
             灯的总开关 (lightOpenOff): 布尔值类型  可写 
             定时器的总开关(isTimerOpen):布尔值  可写 
             定时开的时间(timerOpen):数值   0~3660 单位:秒   
 
   
 
 
   步骤③:选择MCU开发,选择硬件平台:esp8266-32M   Product Secret不用我多说了。 
 
   
 
 
二:电路图的设计与程序编写。 
 
 
     电路图: 
          按键S1长按就是进入airlink配网模式了 
          按键S2按下接通时候就是烧录模式了 
          LED是接在GPIO12和VCC之间的。 
 
   
 
 
 
 
 
 
 
 
             程序篇: 
 
步骤一:先搭建8266的开发环境,我这使用的是安信可的集成环境,并且导入工程。如果有不懂的,可以看这篇:http://blog.csdn.net/xh870189248/article/details/77985541 
 
步骤二:我们先修改我们程序的进入 “配网模式”的按键程序,首先我们打开工程的 app --> user --> user_main.c 文件,修改过程如下: 
 
修改第①处: 
 
我们先把按键定义改下,我们这个是只有一个按键,所以key的数量为1,见下面的修改。 
 
修改前: 
 
 
 
- #define GPIO_KEY_NUM                            2                           ///< Defines the total number of key members
 - #define KEY_0_IO_MUX                            PERIPHS_IO_MUX_GPIO0_U      ///< ESP8266 GPIO function
 - #define KEY_0_IO_NUM                            0                           ///< ESP8266 GPIO number
 - #define KEY_0_IO_FUNC                           FUNC_GPIO0                  ///< ESP8266 GPIO name
 - #define KEY_1_IO_MUX                            PERIPHS_IO_MUX_MTMS_U       ///< ESP8266 GPIO function
 - #define KEY_1_IO_NUM                            14                          ///< ESP8266 GPIO number
 - #define KEY_1_IO_FUNC                           FUNC_GPIO14                 ///< ESP8266 GPIO name
 - LOCAL key_typedef_t * singleKey[GPIO_KEY_NUM];                              ///< Defines a single key member array pointer
 - LOCAL keys_typedef_t keys;                                                  ///< Defines the overall key module structure pointer
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
修改后:    (我们在电路图看到是GPIO4触发配网模式,所以该为GPIO4) 
 
- #define GPIO_KEY_NUM                            1                           ///< Defines the total number of key members
 - #define KEY_0_IO_MUX                            PERIPHS_IO_MUX_GPIO4_U      ///< ESP8266 GPIO function
 - #define KEY_0_IO_NUM                            4                          ///< ESP8266 GPIO number
 - #define KEY_0_IO_FUNC                           FUNC_GPIO4                 ///< ESP8266 GPIO name
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
修改第②处: 
 
把以下的代码删除: 
 
- **
 - * Key2 key to short press processing
 - * @param none
 - * @return none
 - */
 - LOCAL void ICACHE_FLASH_ATTR key2ShortPress(void)
 - {</p><p>GIZWITS_LOG("#### key2 short press, soft ap mode \n");
 -   gizwitsSetMode(WIFI_SOFTAP_MODE);
 - }
 - /**
 - * Key2 button long press
 - * @param none
 - * @return none
 - */
 - LOCAL void ICACHE_FLASH_ATTR key2LongPress(void)
 - {
 -     GIZWITS_LOG("#### key2 long press, airlink mode\n");
 -     gizwitsSetMode(WIFI_AIRLINK_MODE);
 - }
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
同时把   ICACHE_FLASH_ATTR 函数里面以下代码去掉:     
 
   singleKey[1] = keyInitOne(KEY_1_IO_NUM, KEY_1_IO_MUX, KEY_1_IO_FUNC,  key2LongPress, key2ShortPress); 
 
最后得到的按键初始化函数 ICACHE_FLASH_ATTR 如下代码: 
 
- /**
 - * Key to initialize
 - * @param none
 - * @return none
 - */
 - LOCAL void ICACHE_FLASH_ATTR keyInit(void)
 - {
 -     singleKey[0] = keyInitOne(KEY_0_IO_NUM, KEY_0_IO_MUX, KEY_0_IO_FUNC,
 -                                 key1LongPress, key1ShortPress);  //key1LongPress方法回调对应上面的,key1shortPress同样也是
 -     keys.singleKey = singleKey;
 -     keyParaInit(&keys);
 - <strong><font color="seagreen">}</font></strong>
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
修改第③处: 
 
    我们把按键短按和长按的方法修改下,让按键短按进入 AirLink配网模式,长按进入softAP配网模式,修改如下: 
 
- /**
 - * Key1 key short press processing
 - * @param none
 - * @return none
 - */
 - LOCAL void ICACHE_FLASH_ATTR key1ShortPress(void)
 - {
 -     gizwitsSetMode(WIFI_SOFTAP_MODE);
 - }
 - /**
 - * Key1 key presses a long press
 - * @param none
 - * @return none
 - */
 - LOCAL void ICACHE_FLASH_ATTR key1LongPress(void)
 - {
 -     gizwitsSetMode(WIFI_AIRLINK_MODE);
 - }
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
修改第④处:  因为我们是只有一个功能,并且只有使用到一个GPIO口,所以我们仅仅初始化一个就好了,我这在user_init()主函数直接加入以下代码: 
-     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); //GPIO12初始化
 -     GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);//GPIO12 低电平输出
  
  
[color=rgb(0, 0, 0) !important]复制代码 
 
修改第五处:我们现在把目标转到 app --->Gizwits_product.c 文件(下同),修改我们8266收到指令后作出动作的代码: 
 
修改前: 
- case EVENT_lightOnOff :
 -             currentDataPoint.valuelightOnOff = dataPointPtr->valuelightOnOff;
 -             GIZWITS_LOG("Evt: EVENT_lightOnOff %d \n", currentDataPoint.valuelightOnOff);
 -             if(0x01 == currentDataPoint.valuelightOnOff)
 -             {
 -                 //user handle
 -             }
 -             else
 -             {
 -                 //user handle
 -             }
 -             break;
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
修改后:  收到0x01(true)开灯,0x00(false)关灯,因为8266的内部GPIO是默认上拉,所以选择高电平输出,反而灯会亮!!博主也是从这篇文章了解到的:http://blog.csdn.net/jackhuang2015/article/details/50839401 
 
- case EVENT_lightOnOff :
 -             currentDataPoint.valuelightOnOff = dataPointPtr->valuelightOnOff;
 -             GIZWITS_LOG("Evt: EVENT_lightOnOff %d \n", currentDataPoint.valuelightOnOff);
 -             if(0x01 == currentDataPoint.valuelightOnOff)
 -             {
 -                      GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1); //开灯
 -             }
 -             else
 -             {
 -                      GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0); //关灯
 -             }
 -             break;
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
修改第⑥处: 
 
    我们在文件新增一个定时器使能的bool类型、一个软件定时器结构体和一个定时时间。 
 
- //布尔值,定时器开关的状态
 - bool isTimer ;
 - //定时时间
 - uint16_t timer_timers;
 - /** 定时器结构体 */
 - static os_timer_t os_timer;
  
  
[color=rgb(0, 0, 0) !important]复制代码 
 
   我们在收到app发来的 isTimerOpen数据点(开关定时器的指令)的方法处理这样做: 
 
- <p>   case EVENT_isTimerOpen :
 -             currentDataPoint.valueisTimerOpen = dataPointPtr->valueisTimerOpen;
 -             if(0x01 == currentDataPoint.valueisTimerOpen)
 -              {
 -                       isTimer=true;
 -              }   else   {
 -               /** 关闭该定时器 */
 -             os_timer_disarm( &os_timer );         </p><p>            /** 定时器使能为false */
 -             isTimer=false;
 -                      }
 -             break;</p>
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
 
  我们在收到app发来的 TimerOpen数据点(定时时间)的方法处理这样做:    注意,每次开启定时器,要先把其关闭掉,再重新初始化使能。 
 
 
- case EVENT_timerOpen:
 -                   currentDataPoint.valuetimerOpen= dataPointPtr->valuetimerOpen;         </p><p> //只有当使能状态为true就可以开启定时器
 -               if(isTimer){
 -                                 /** 关闭该定时器 */
 -                                 os_timer_disarm( &os_timer );
 -                                 // 配置该定时器回调函数,指定的执行方法是: Led_Task_Run (),下面会提供代码
 -                          os_timer_setfn( &os_timer, (ETSTimerFunc *) (<font color="red"> Led_Task_Run</font> ), NULL );
 -                                 /** 开启该定时器 :下发的是秒数,这里的单位是毫秒,要乘1000* ,后面false表示仅仅执行一次**/
 -                                 os_timer_arm( &os_timer, currentDataPoint.valuetimerOpen*1000, false );
 -                                 /**赋值给timer_timers,方便会调用 */
 -                                 timer_timers=currentDataPoint.valuetimerOpen;
 -                           }
 -                break;
  
  
[color=rgb(0, 0, 0) !important]复制代码 
 
  定时任务函数这样做: 
 
- /**
 - * 定时任务函数
 - */
 - void Led_Task_Run(void){
 - //开灯
 - GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);
 - //执行完毕,我们要把定时时间设置0 ,定时使能状态为false
 - timer_timers=0;
 - isTimer=false;
 - }
 
 
  
[color=rgb(0, 0, 0) !important]复制代码 
 
修改⑦:改变上报数据的方法: 
 
- void ICACHE_FLASH_ATTR userHandle(void)
 - {
 -                 //获取GPIO12的高低电平,因为高电平是触发开灯,所以ture就是开灯
 -                 currentDataPoint.valuelightOnOff = GPIO_INPUT_GET(12)  ;
 -                 //是否开启定时器的回调
 -                                currentDataPoint.valueisTimerOpen =isTimer ;
 -                                //定时时间回调,如果用戶設置了定時器关闭,那么我们返回0,否则返回定时时间,注意这个定时时间是固定的。不是倒计时时间。
 -                               if(isTimer){
 -                          currentDataPoint.valuetimerOpen =timer_timers ;
 -                     }else{
 -              currentDataPoint.valuetimerOpen =0;
 -                                        }
 -       system_os_post(USER_TASK_PRIO_2, SIG_UPGRADE_DATA, 0);
 - }
  
  
[color=rgb(0, 0, 0) !important]复制代码 
 
 
     烧录篇: 
 
对于很多新手来说,烧录过程完全是个坑,完全不知道烧录哪几个文件。 
 
①:下面是我从安信可论坛看到的一张图,希望可以帮到大家: 
                                               
②:这里我再强调,blank.bin、esp_init_data_default.bin一定要烧写进去,避免内部初始化出错,这2个文件在工程下bin文件夹可以找到。一般的8266都是32M的。所以,blank.bin的固定烧录地址是:0x3FE000 ,esp_init_data_default.bin的固定烧录地址是:0x3FC000。 
                                                     
③:  再再强调,编译结果有 2 种,第一种不需要 boot.bin 文件,第二种则需要 boot.bin 文件。但是编译结果不管怎么样,我们都是只烧录4个文件。烧录时候:先把gpio0设置为低电平,默认是上拉高电平的。 |  
  
 |   
 
  
  
  
 
 
 |