文档中心

MCU 快速开始

更新时间:2020-10-13 02:44:20下载pdf

在完成涂鸦三明治开发板开发环境搭建之后,本文介绍如何使用涂鸦三明治开发板创建产品工程,以及如何在开发完成后验证、运行和维护。

准备工作

  1. 请确保您已经安装了 Arduino IDE。
  2. 请确保您已经准备了以下硬件物料。
    • 支持数据传输的 Micro-USB线
    • 涂鸦三明治 Wi-Fi 通信板(E3S)
      MCU 快速开始
    • ST Nucleo 开发板
      MCU 快速开始

创建工程

您需要创建工程来实现产品的两个功能:

  • 涂鸦三明治主控板与涂鸦三明治 Wi-Fi 通信板(E3S)之间基础的通信功能
  • 根据自身需求编写实际产品具体 DP 点对应的功能逻辑

第一步:获取 MCU SDK

为了实现涂鸦三明治套件中的主控板与涂鸦三明治 Wi-Fi 通信板(E3S)之间的通信,您需要预先通过涂鸦 IoT 工作台根据产品生成 MCU SDK 开发包。下面以实现产品插座为例,获取插座产品 MCU SDK 开发包步骤如下:

  1. 登录 IoT 工作台

  2. 参考 选品类创建产品 创建一个插座产品,例如创建一款 自定义开发方案 的 Wi-Fi 协议插座。
    MCU 快速开始

  3. 功能定义 处,根据功能需求选取对应的 DP 点。

  4. App 面板 处,选择并体验一款 App 面板。

  5. 硬件开发 页面底部,单击 MCU SDK 列的 下载

    MCU 快速开始

  6. 打开下载的开发包压缩文件,目录如下所示。

    MCU 快速开始

    其中包含有说明文档、MCU SDK 文件夹、涂鸦云串口调试助手和助手所需的调试文件。

    在当前阶段,您仅需要使用其中的 MCU SDK 文件夹中的内容:

    MCU 快速开始

    文件夹内文件对应说明如下:

    执行文件 头文件 说明
    mcu_api.c mcu_api.h 内含Wi-Fi相关函数,您可以按需调用
    protocol.c protocol.h 协议文件,内含数据处理函数,您需要根据项目需求修改这两个文件
    system.c system.h 串口通讯协议的具体实现
    / wifi.h Wi-Fi 相关宏定义

第二步:移植 MCU SDK

  1. 在 Arduino IDE 工程中,单击 菜单栏 > 文件 > 新建,新建一个工程项目。

    MCU 快速开始

    工程中,您需要注意以下函数:

    • setup9():用于初始化,只执行一次
    • loop():循环执行函数
  2. 找到 MCU 开发包中以下所有 .c.h 文件,将这些文件复制到刚刚新建的工程路径下的 同一级目录,并将 .c 件后缀改为 .cpp,将 MCU SDK 包中的文件添加进当前 Arduino 的项目之中。

    完成后如下图所示:

    MCU 快速开始

  3. 重新打开 .ino 文件,即可在 IDE 中发现添加的 MCU SDK 文件。

    MCU 快速开始

  4. 单击左上角对勾,进行代码编译验证。

第三步:移植代码和报错排查

MCU SDK 刚导入工程,未进行任何移植操作前,编译会有报错的情况出现,这是正常现象。接下来,您需要依次对代码进行移植修改,直到编译后没有错误。

  • 报错一:

    • 报错信息:请将MCU串口发送函数填入该函数,并删除该行。

      MCU 快速开始

    • 报错原因:在 SDK 中,每个 #error 出现的位置都是 SDK 移植时,您必须改动代码的位置,#error 可以提醒您遗漏程序编写的关键部分。

    • 解决方法: 为了方便验证通过,您可以 暂时#error 前添加 // ,使其处于注释状态,跳过提醒。

      注意:后续完成代码开发时,您需要回到出现 #error 提示的位置,并按照 #error 的指引填写相应功能实现需要的内容。

  • 报错二:

    • 报错信息:Invalid conversion from ‘const char’ to unsigned char [-fpermissive]

      MCU 快速开始

    • 报错原因:编译环境存在不同导致编译不通过。

    • 解决方法:您可以在system.cpp文件中,找到位置并添加强制类型转换,替换后的函数参考如下所示:

      static void product_info_update(void)
      {
        unsigned char length = 0;
        length = set_wifi_uart_buffer(length,(unsigned char *)"{\"p\":\"", my_strlen((unsigned char *)"{\"p\":\""));
        length = set_wifi_uart_buffer(length,(unsigned char *)PRODUCT_KEY,my_strlen((unsigned char *)PRODUCT_KEY));
        length = set_wifi_uart_buffer(length,(unsigned char *) "\",\"v\":\"", my_strlen((unsigned char *)"\",\"v\":\""));
        length = set_wifi_uart_buffer(length,(unsigned char *)MCU_VER,my_strlen((unsigned char *)MCU_VER));
        length = set_wifi_uart_buffer(length,(unsigned char *)"\",\"m\":", my_strlen((unsigned char *)"\",\"m\":"));
        length = set_wifi_uart_buffer(length,(unsigned char *)CONFIG_MODE, my_strlen((unsigned char *)CONFIG_MODE));
        length = set_wifi_uart_buffer(length,(unsigned char *) "}", my_strlen((unsigned char *)"}"));
        
        wifi_uart_write_frame(PRODUCT_INFO_CMD, length);
      }
      
  • 报错三:

    • 报错信息:为开发板Nucleo-64编译时出错。

      MCU 快速开始

    • 报错原因:程序常量问题。

    • 修改方法:去掉 protocol.cppsystem.cpp 文件中截图处的 const

      MCU 快速开始
      MCU 快速开始

  • 报错四

    • 报错信息:如下图所示。

      MCU 快速开始

    • 报错原因: 与官方库存在重复定义。

    • 解决方法: 删除 wifi.h 中重复定义的部分,删除内容见上图红框所示。

报错解决后编译通过,您需要实现三明治开发板与 Wi-Fi 模组通信之间的串口收发函数。详细移植细节,请参考 STM32 的 MCU SDK 移植

第四部:运行示例代码

本示例可以作为您实现基本串口和按键功能的参考,其中串口收发功能实现是调用了 Arduino 串口的 API。关于 Arduino API 使用说明,您可在 Arduino 官网查询。

  1. 运行以下主程序代码示例。

    #include "wifi.h"
    #include <SoftwareSerial.h>
    
    SoftwareSerial mySerial(0, 1); // RX, TX
    #define _SS_MAX_RX_BUFF 300
    #define relay 10
    int time_cnt = 0, cnt = 0, init_flag = 0;
    
    void setup() {
    
      pinMode(relay, OUTPUT);   // 继电器I/O初始化
      digitalWrite(relay, LOW);
    
      pinMode(PC13, INPUT);     // 重置Wi-Fi按键初始化
      pinMode(8, OUTPUT);       // Wi-Fi状态指示灯初始化
    
      mySerial.begin(9600);     // 软件串口初始化
      mySerial.println("myserial init successful!");
      Serial.begin(115200);     // PA3 RX   PA2 TX
      Serial.println("serial init successful!");
    
      wifi_protocol_init();
    }
    
    void loop() {
      if (init_flag == 0) {
        time_cnt++;
        if (time_cnt % 6000 == 0) {
          time_cnt = 0;
          cnt ++;
        }
        wifi_stat_led(&cnt);   // Wi-Fi状态处理
      }
      wifi_uart_service();
      myserialEvent();      // 串口接收处理
      key_scan();           // 重置配网按键检测
    
    }
    
    void myserialEvent() {
      if (mySerial.available()) {
        unsigned char ch = (unsigned char)mySerial.read();
        uart_receive_input(ch);
      }
    }
    
    void key_scan(void)
    {
      static char ap_ez_change = 0;
      unsigned char buttonState  = HIGH;
      buttonState = digitalRead(PC13);
      if (buttonState == LOW) {
        delay(3000);
        buttonState = digitalRead(PC13);
          printf("----%d",buttonState);
        if (buttonState == LOW) {
          printf("123\r\n");
          init_flag = 0;
          switch (ap_ez_change) {
            case 0 :
              mcu_set_wifi_mode(SMART_CONFIG);
              break;
            case 1 :
              mcu_set_wifi_mode(AP_CONFIG);
              break;
            default:
              break;
          }
          ap_ez_change = !ap_ez_change;
        }
    
      }
    }
    
    void wifi_stat_led(int *cnt)
    {
    #define wifi_stat_led 8
      switch (mcu_get_wifi_work_state())
      {
        case SMART_CONFIG_STATE:  //0x00
          init_flag = 0;
          if (*cnt == 2) {
            *cnt = 0;
          }
          if (*cnt % 2 == 0)  //LED快闪
          {
            digitalWrite(wifi_stat_led, LOW);
          }
          else
          {
            digitalWrite(wifi_stat_led, HIGH);
          }
          break;
        case AP_STATE:  //0x01
          init_flag = 0;
          if (*cnt >= 30) {
            *cnt = 0;
          }
          if (*cnt  == 0)      // LED 慢闪
          {
            digitalWrite(wifi_stat_led, LOW);
          }
          else if (*cnt == 15)
          {
            digitalWrite(wifi_stat_led, HIGH);
          }
          break;
    
        case WIFI_NOT_CONNECTED:  // 0x02
          digitalWrite(wifi_stat_led, HIGH); // LED 熄灭
          break;
        case WIFI_CONNECTED:  // 0x03
          break;
        case WIFI_CONN_CLOUD:  // 0x04
          if ( 0 == init_flag )
          {
            digitalWrite(wifi_stat_led, LOW);// LED 常亮
            init_flag = 1;                  // Wi-Fi 连接上后该灯可控
            *cnt = 0;
          }
    
          break;
    
        default:
          digitalWrite(wifi_stat_led, HIGH);
          break;
      }
    }
    
  2. 找到串口发送函数实现的下图标记部分。

    MCU 快速开始

    修改为以下片段:

    void uart_transmit_output(unsigned char value)
    {
    //  #error "请将MCU串口发送函数填入该函数,并删除该行"
    extern SoftwareSerial mySerial;
      mySerial.write(value);                                
    }
    
  3. 导入 Arduino 相应库函数头文件。

  4. 找到 protocol.cpp 文件里的下图标记部分。

    MCU 快速开始

    修改为以下片段:

    #include "wifi.h"
    #include <SoftwareSerial.h>
    #include "Arduino.h"
    #ifdef WEATHER_ENABLE
    
  5. 找到 wifi.h 文件里的下图标记部分。

    MCU 快速开始

    修改为以下片段:

    #include "protocol.h"
    #include "system.h"
    #include "mcu_api.h"
    #include "Arduino.h"
    

第五步:开发产品功能

实现基本的串口收发功能以后,就需要您根据需求,实现产品的具体功能。

在上述示例中,您在涂鸦 IoT 工作台创建产品时,功能实现选项中选择了开关功能,选择的功能在下载的 SDK 包中生成了对应 DP 功能函数,具体的实现函数在 protocol.cpp 如下位置。

MCU 快速开始

下载与调试

当您编写好产品的应用程序后,可通过以下步骤将代码下载到涂鸦三明治开发板中。

  1. 将三明治开发板与电脑相连,选择对应的端口。

  2. 单击 上传

    通过以上步骤将程序下载到您的开发板中,下载成功出现以下页面:

    MCU 快速开始

  3. 初始化硬件串口语句 Serial.begin(115200);

  4. 涂鸦三明治开发板库中已将 printf() 函数重定向到了串口,因此您可以直接使用 printf() 函数完成数据收发。

在 App 上配网

将程序下载到后开发板重新上电,此时 Wi-Fi 模组默认处于 EZ 配网模式,使用涂鸦智能 App 进行配网。

您可以根据模组上配网指示灯的不同状态,判断当前模组的配网状态:

配网指示灯 配网状态
快闪 EZ 配网状态,等待配网
慢闪 AP 配网状态,等待配网
熄灭 Wi-Fi 已配置且连上路由器
常亮 已连上路由器且连接到云端
  1. 打开涂鸦智能 App,点击图示添加设备按钮。

    MCU 快速开始

  2. 选择对应品类,添加设备。

    MCU 快速开始

    MCU 快速开始

    MCU 快速开始

  3. 配网中,等待配网完成。

    MCU 快速开始

  4. 设备配网成功,您可通过App进行相应控制。

    MCU 快速开始

相关文档

点击获取服务和帮助