ESP32C3 BLE5.0 吞吐速率的分析与测试

这篇具有很好参考价值的文章主要介绍了ESP32C3 BLE5.0 吞吐速率的分析与测试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ESP32C3 BLE5.0 吞吐速率的分析与测试

前言: 本篇文章主要探讨下影响 BLE 传输速率的因素,分析和计算 BLE 1M PHY、BLE 2M PHY 的最大传输速率以及使用 ESP32-C3 验证两种 PHY 的传输速率

1、影响 BLE 传输速率的因素

当前蓝牙核心规范的版本是v5.3, 从 BLE5.0 版本时, BLE已经可以支持多种物理层:LE 1M UNCODED PHY、LE 2M UNCODED PHY 以及 LE CODED PHY, 其中1M UNCODED PHY 也是 BLE4.2 版本所使用的物理层,比特传输速率为 1M bit/s, LE 2M UNCODED PHY 的比特传输速率为 2M bit/s, 而 LE CODED PHY 着重于长距离通讯,比特传输速率反而更低,分别是 125 K bit/s 和 500 K bit/s.

如果我使用 LE 2M UNCODED PHY 的物理层,那传输速率是否可以达到2M bit/s? 当然不可能,影响因素也并不复杂,主要有以下几点

  • 从 ATT 层往下的层层打包

    一般来说,我们并不主动去操控蓝牙链路层(LL 层)直接发送数据,而是从 ATT 层 、L2CAP 层、LL 层层层封装打包,对端拿到数据是再层层解包, 也是说通过 BLE 传输的数据并不是都是有效数据,还有 “协议数据”
    esp32 蓝牙 速度,Bluetooth,物联网,iot

    上图可以看到各个协议层的 HEADER , LE 1M UNCODED PHY时,Preamble是 1个字节, LE 2M UNCODED PHY时,Preamble是 2个字节

    在BLE 4.0 和 4.1 中,最大 ATT Payload 为 20 字节,在BLE 4.2 和 5.0 中,一种称为数据长度扩展 (DLE) 的新功能允许 ATT 有效负载最多容纳 244 字节的数据,一般 DLE 是可以配置的,从单包数据利用率来看,DLE 调至最大更好,很多蓝牙芯片默认设置就是 DLE 最大

  • 帧间空间 (T_IFS)

    同一数据信道上, 两个空中包的之间的距离是 150 us, 从上一包的包尾到下一包的包头, 这个是一个固定的时间消耗

  • 连接事件和连接间隔

    在两个 BLE 设备建立连接后,需要在一个个连接事件中进行相互收发包, 每个连接事件中双方要完成一次收发包,如果没有数据发, 也需要发送一个空包给对端。一个连接事件中双方可以有多个数据包的交互,取决于数据包的长度及连接间隔大小; 连接间隔是两个相邻连接事件起始之间的时间距离,可通过应用层配置
    esp32 蓝牙 速度,Bluetooth,物联网,iot

综上来看,影响 BLE 传输速率的因素主要是应用层发包方式和连接间隔的调整,举个例子,应用层使用 write command 的方式发包要比使用 write request 的方式快很多,因为后者对端还要回复 write response 包; 连接间隔的调整指的在一个连接事件中尽可能提升数据包的填充率,例如一个连接事件中能发送 14 个 负载为 150 的数据,如果调整下 DLE负载数据为 145, 连接事件可以发送 15 个包,这样就整体提升了发送数据的速率, 或者微小的提升连接间隔,一个连接事件中能发送 15 个 负载为 150 的数据

这里有个问题是连接间隔是不是越大越好?或者越小越好?这个和设备厂商或者协议栈有关系,一个连接事件的最大包的个数有限制, 你调整到连接间隔为 1s, 一般就超过这个限制了, 那速率也会很慢,实际最好是连接间隔越小并且能使当前连接事件中包含更多的数据包

2、BLE 传输速率的计算和分析

以乐鑫的吞吐量示例为例, 单向 client 发送 write command 数据,数据长度 490, 使用 LE 1M UNCODED PHY, 默认的连接间隔是 40ms (可以通过抓包或者建立连接后调用 esp_ble_get_current_conn_params 获得),ATT 层 3 个字节 header, L2CAP 层 4 个 字节 header, DLE 默认是最大的,所以链路层会分两包进行发送,平均每个 LL 层数据包长度及占用时间如下:

LL层数据包长度 = Preamble + Access Address + LL Header + Data + CRC = 1+4+2+(497/2)+3=259 byte
LL层数据包占用时间 = (259*8) bits / 1 Mbps = 2072 us

slave 设备收到包后要回复一个空包,空包长度及占用时间如下:

空包长度 = Preamble + Access Address + LL Header + CRC = 1+4+2+3=10 byte
空包占用时间 =  =  80 bits / 1 Mbps = 80 us

一次收发包过程所占用的时间:

一次收发包过程占用时间 = LL层数据包占用时间 + IFS + 空包占用时间 + IFS = 80 + 2*150 + 2072 =  2452 us

40ms 的连接间隔可以有 (40 * 1000)/2452 = 16 个收发包过程, 应用层传输速率

应用层传输速率 =  (1000/40) * (16/2 *490)*8 = 784000 bit/s

使用两块 ESP32-C3 对跑测试,实际速率是

I (112501) GATTS_DEMO: GATTC write Bit rate = 91805 Byte/s, = 734440 bit/s, time = 101s
I (114501) GATTS_DEMO: GATTC write Bit rate = 91807 Byte/s, = 734456 bit/s, time = 103s
I (116501) GATTS_DEMO: GATTC write Bit rate = 91808 Byte/s, = 734464 bit/s, time = 105s
I (118501) GATTS_DEMO: GATTC write Bit rate = 91777 Byte/s, = 734216 bit/s, time = 107s
I (120501) GATTS_DEMO: GATTC write Bit rate = 91775 Byte/s, = 734200 bit/s, time = 109s
I (122501) GATTS_DEMO: GATTC write Bit rate = 91776 Byte/s, = 734208 bit/s, time = 111s
I (124501) GATTS_DEMO: GATTC write Bit rate = 91778 Byte/s, = 734224 bit/s, time = 113s
I (126501) GATTS_DEMO: GATTC write Bit rate = 91780 Byte/s, = 734240 bit/s, time = 115s
I (128501) GATTS_DEMO: GATTC write Bit rate = 91781 Byte/s, = 734248 bit/s, time = 117s
I (130501) GATTS_DEMO: GATTC write Bit rate = 91783 Byte/s, = 734264 bit/s, time = 119s
I (132501) GATTS_DEMO: GATTC write Bit rate = 91756 Byte/s, = 734048 bit/s, time = 121s

并没有达到理想的计算速率,抓包看到每个连接间隔是 15 个收发包过程,如果按这个进行计算与实际速率相符

应用层传输速率 =  (1000/40) * (15/2 *490)*8 = 735000 bit/s

那如果是使用 LE 2M UNCODED PHY 呢, 我们假定使用连接间隔为 47.5ms 计算(其他值可以自己调试和计算)

LL层数据包长度 = Preamble + Access Address + LL Header + Data + CRC = 2+4+2+(497/2)+3=260 byte
LL层数据包占用时间 = (260*8) bits / 2 Mbps = 1040 us
空包长度 = Preamble + Access Address + LL Header + CRC = 2+4+2+3=11 byte
空包占用时间 =  =  88 bits / 2 Mbps = 44 us
一次收发包过程占用时间 = LL层数据包占用时间 + IFS + 空包占用时间 + IFS = 44 + 2*150 + 1040 =  1384 us
连接间隔包含收发包过程的个数 =   (47.5 * 1000)/1384 = 34
应用层传输速率 =  (1000/47.5) * (34/2 *490)*8 =  1402947 bit/s = 1.40 Mbit/s 

实际使用两块 ESP32-C3 使用 2M PHY 对跑测试

I (186511) GATTS_DEMO: GATTC write Bit rate = 169031 Byte/s, = 1352248 bit/s, time = 184s
I (188511) GATTS_DEMO: GATTC write Bit rate = 169017 Byte/s, = 1352136 bit/s, time = 186s
I (190511) GATTS_DEMO: GATTC write Bit rate = 169028 Byte/s, = 1352224 bit/s, time = 188s
I (192511) GATTS_DEMO: GATTC write Bit rate = 169041 Byte/s, = 1352328 bit/s, time = 190s
I (194511) GATTS_DEMO: GATTC write Bit rate = 169051 Byte/s, = 1352408 bit/s, time = 192s
I (196511) GATTS_DEMO: GATTC write Bit rate = 169059 Byte/s, = 1352472 bit/s, time = 194s
I (198511) GATTS_DEMO: GATTC write Bit rate = 169069 Byte/s, = 1352552 bit/s, time = 196s
I (200511) GATTS_DEMO: GATTC write Bit rate = 169074 Byte/s, = 1352592 bit/s, time = 198s
I (202511) GATTS_DEMO: GATTC write Bit rate = 169013 Byte/s, = 1352104 bit/s, time = 200s
I (204511) GATTS_DEMO: GATTC write Bit rate = 168962 Byte/s, = 1351696 bit/s, time = 202s
I (206511) GATTS_DEMO: GATTC write Bit rate = 168956 Byte/s, = 1351648 bit/s, time = 204s

能达到 1.35 Mbit/s 左右,基本上也是接近计算数据,实际可能是连接事件中并没有包含 34 个收发包过程,不好确定,因为当前的 sniffer 设备很少可以抓 LE 2M UNCODED PHY 数据包的,具备此功能的也价格比较昂贵。

3、修改 ESP32C3 吞吐量测试示例

最简单方法是将 吞吐量示例 与 ble50_security_client 和 ble50_security_server 两个示例进行结合, 修改扫描、广播和发起连接的 API 为 扩展 API

  • throughput_server

    修改广播参数与广播数据

    static uint8_t ext_adv_raw_data[] = {
            0x02, 0x01, 0x06,
            0x02, 0x0a, 0xeb, 0x03, 0x03, 0xab, 0xcd,
            0x11, 0X09,  'B', 'L', 'E', '5', '0', '_', 'T', 'H', 'R', 'O', 'U', 'G', 'H','P', 'U', 'T',
    };
    
    static esp_ble_gap_ext_adv_t ext_adv[1] = {
        [0] = {EXT_ADV_HANDLE, EXT_ADV_DURATION, EXT_ADV_MAX_EVENTS},
    };
    
    esp_ble_gap_ext_adv_params_t ext_adv_params_2M = {
        .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE,
        .interval_min = 0x20,
        .interval_max = 0x20,
        .channel_map = ADV_CHNL_ALL,
        .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
        .primary_phy = ESP_BLE_GAP_PHY_1M,
        .max_skip = 0,
        .secondary_phy = ESP_BLE_GAP_PHY_2M,
        .sid = 0,
        .scan_req_notif = false,
        .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
        .tx_power = EXT_ADV_TX_PWR_NO_PREFERENCE,
    };
    

    修改设置广播参数、数据及开启广播的流程

    static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
        switch (event) {
        case ESP_GATTS_REG_EVT:
    		 //...
             esp_ble_gap_ext_adv_set_params(EXT_ADV_HANDLE, &ext_adv_params_2M);
    	//...
    }
    
    static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
    {
        case ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT:
            ESP_LOGI(GATTS_TAG,"ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT status %d",  param->ext_adv_set_params.status);
            esp_ble_gap_config_ext_adv_data_raw(EXT_ADV_HANDLE,  sizeof(ext_adv_raw_data), &ext_adv_raw_data[0]);
            break;
        case ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT:
           ESP_LOGI(GATTS_TAG,"ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT status %d",  param->ext_adv_data_set.status);
             esp_ble_gap_ext_adv_start(NUM_EXT_ADV_SET, &ext_adv[0]);
             break;
        //...
    }
    
    

    连接后更新连接参数

    static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
        switch (event) {
        case ESP_GATTS_CONNECT_EVT:
    		 //...
            is_connect = true;
            esp_ble_conn_update_params_t conn_params = {0};
            memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
    
            conn_params.latency = 0;
            conn_params.max_int = 38;    // max_int = 38*1.25ms = 47.5ms
            conn_params.min_int = 38;    // min_int = 38*1.25ms = 47.5ms
            conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
            gl_profile_tab[PROFILE_A_APP_ID].conn_id = param->connect.conn_id;
            //start sent the update connection parameters to the peer device.
            esp_ble_gap_update_conn_params(&conn_params);
            break;
    	//...
    }
    
  • throughput_client

    设置扫描参数和要寻找的对端设备名称

    static const char remote_device_name[] = "BLE50_THROUGHPUT";
    
    static esp_ble_ext_scan_params_t ext_scan_params = {
        .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
        .filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
        .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE,
        .cfg_mask = ESP_BLE_GAP_EXT_SCAN_CFG_UNCODE_MASK | ESP_BLE_GAP_EXT_SCAN_CFG_CODE_MASK,
        .uncoded_cfg = {BLE_SCAN_TYPE_ACTIVE, 40, 40},
        .coded_cfg = {BLE_SCAN_TYPE_ACTIVE, 40, 40},
    };
    
    const esp_ble_gap_conn_params_t phy_1m_conn_params = {
        .scan_interval = 0x40,
        .scan_window = 0x40,
        .interval_min = 0x10,
        .interval_max = 0x20,
        .latency = 0,
        .supervision_timeout = 600,
        .min_ce_len  = 0,
        .max_ce_len = 0,
    };
    const esp_ble_gap_conn_params_t phy_2m_conn_params = {
        .scan_interval = 0x40,
        .scan_window = 0x40,
        .interval_min = 0x10,
        .interval_max = 0x20,
        .latency = 0,
        .supervision_timeout = 600,
        .min_ce_len  = 0,
        .max_ce_len = 0,
    };
    const esp_ble_gap_conn_params_t phy_coded_conn_params = {
        .scan_interval = 0x40,
        .scan_window = 0x40,
        .interval_min = 0x10,
        .interval_max = 0x20,
        .latency = 0,
        .supervision_timeout = 600,
        .min_ce_len  = 0,
        .max_ce_len = 0,
    };
    

    设置扫描参数以及扫描结果处理并发起连接

    static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
    {
        esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
        switch (event) {
        case ESP_GATTC_REG_EVT:
            ESP_LOGI(GATTC_TAG, "REG_EVT");
            esp_err_t scan_ret = esp_ble_gap_set_ext_scan_params(&ext_scan_params);
            if (scan_ret){
                ESP_LOGE(GATTC_TAG, "set extend scan params error, error code = %x", scan_ret);
            }
            break;
    	//...
    }
            
    static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
    {
        uint8_t *adv_name = NULL;
        uint8_t adv_name_len = 0;
        switch (event) {
        case ESP_GAP_BLE_SET_EXT_SCAN_PARAMS_COMPLETE_EVT: {
            if (param->set_ext_scan_params.status != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(GATTC_TAG, "extend scan parameters set failed, error status = %x", param->set_ext_scan_params.status);
                break;
            }
            esp_ble_gap_start_ext_scan(EXT_SCAN_DURATION, EXT_SCAN_PERIOD);
            break;
        }
        case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
            //scan start complete event to indicate scan start successfully or failed
            if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(GATTC_TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status);
                break;
            }
            ESP_LOGI(GATTC_TAG, "scan start success");
            break;
        case ESP_GAP_BLE_EXT_ADV_REPORT_EVT: {
            uint8_t *adv_name = NULL;
            uint8_t adv_name_len = 0;
            if(param->ext_adv_report.params.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) {
                ESP_LOGI(GATTC_TAG, "legacy adv, adv type 0x%x data len %d", param->ext_adv_report.params.event_type, param->ext_adv_report.params.adv_data_len);
            } else {
                ESP_LOGI(GATTC_TAG, "extend adv, adv type 0x%x data len %d", param->ext_adv_report.params.event_type, param->ext_adv_report.params.adv_data_len);
            }
            adv_name = esp_ble_resolve_adv_data(param->ext_adv_report.params.adv_data,
                                                ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
            if (!connect && strlen(remote_device_name) == adv_name_len && strncmp((char *)adv_name, remote_device_name, adv_name_len) == 0) {
                connect = true;
                esp_ble_gap_stop_ext_scan();
                esp_log_buffer_hex("adv addr", param->ext_adv_report.params.addr, 6);
                esp_log_buffer_char("adv name", adv_name, adv_name_len);
                ESP_LOGI(GATTC_TAG, "Stop extend scan and create aux open, primary_phy %d secondary phy %d\n", param->ext_adv_report.params.primary_phy, param->ext_adv_report.params.secondly_phy);
    
                esp_ble_gap_prefer_ext_connect_params_set(param->ext_adv_report.params.addr,
                                                         ESP_BLE_GAP_PHY_1M_PREF_MASK | ESP_BLE_GAP_PHY_2M_PREF_MASK | ESP_BLE_GAP_PHY_CODED_PREF_MASK ,
                                                         &phy_1m_conn_params, &phy_2m_conn_params, &phy_coded_conn_params);
                esp_ble_gattc_aux_open(gl_profile_tab[PROFILE_A_APP_ID].gattc_if,
                                        param->ext_adv_report.params.addr,
                                        param->ext_adv_report.params.addr_type, true);
            }
            break;
        }
        //...
    }
    

    esp_ble_gap_prefer_ext_connect_params_set 也可以不用去配置

两个demo 示例修改后在编译前要在 menuconfig 中打开 CONFIG_BT_BLE_50_FEATURES_SUPPORTED 宏,不然编译不通过, ESP32S3 配置流程与 ESP32C3 相同

以上使用的 write command 方式或者 notify 方式,类似于 网络协议中的 UDP, 并不能保证数据可达,实际中一些重要的不能丢包的场合如 OTA 过程可以使用 write request 方式或者 indicate 方式发送数据,但传输速率可能达不到以上数据传输速率的一半,所以以上测试速率可以作为一个极限速率参考

参考:

https://novelbits.io/bluetooth-5-speed-maximum-throughput/文章来源地址https://www.toymoban.com/news/detail-664394.html

到了这里,关于ESP32C3 BLE5.0 吞吐速率的分析与测试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【esp32c3配置arduino IDE教程】

    本文主线FastBond2阶段1——基于ESP32C3开发的简易IO调试设备,esp32c3环境搭建,设计目标如下 设计用户操作界面,该设备具备简单易用的操作界面,外加显示屏SSD1306和旋转编码器进行显示和控制,用户后期可进行二次开发WiFi或蓝牙连接电脑或手机监控。 多种数字和模拟信号的

    2024年02月03日
    浏览(57)
  • ESP32C3简约版---笔记(一)&固件烧录

      前段时间买了块合宙的ESP32C3简约版。正好有时间,就试着尝试玩一下。顺便记录一下过程,方便以后回忆时,能快速使用。大体是按照官网的流程来,加上自己的一些记录。其实官网也有比较详细教程了,也可以看看。合宙ESP32C3简约版官方教程   文章虽然主要是以介

    2024年02月05日
    浏览(55)
  • ESP32C3学习&开发之路——VScode开发环境搭建

    上次搭建好了ESP IDF离线版的开发环境,但是我不想每次开发的时候都要打开“PowerShell”终端,也不想要输入指令进行编译和下载的操作,所以再搭建在VScode的软件上开发ESP32系列WiFi模组的开发环境。 VScode全称Visual Studio Code,免费而强大,可在Windows、Linux和Mac OS上运行。所以

    2024年02月10日
    浏览(58)
  • 物联网开发笔记(87)- 使用Micropython开发ESP32开发板之烧录合宙ESP32C3开发板

    一、目的         这一节我们学习如何使用我们的ESP32开发板来学习合宙ESP32C3开发板,该开发板有两种:一种是带串口通讯的,一种是通过使用USB通讯接口的。  二、环境         ESP32 + 合宙ESP32C3开发板 + USB转type-C线  + Win10 接线方法:         开发板通过USB线插到

    2024年02月14日
    浏览(53)
  • arduino Xiao ESP32C3 oled0.96 下雪花

    雪花下落的时候, 随机生成半径和位置 sandR和sandX,sandY 保存雪花下落位置的时候, 将其周边一圈设置为-1, 标记为有雪花 其他雪花下落的时候, 其他雪花的一圈如果遇到-1, 则停止下落, 并重复2

    2024年02月12日
    浏览(42)
  • Conmi的正确答案——使用eclipse进行ESP32C3的debug

    eclipse IDE 版本:2023-12 参考大神的教程:【图文】手把手教你使用 Eclipse IDE 开发 ESP32 (这里是为了我下次回来速通才写的部分) 相关软件参数: 汉化(安装完成会提示重启应用): Name: Chinese Location: https://mirrors.nju.edu.cn/eclipse/technology/babel/update-site/latest/ 乐鑫(选中两个

    2024年01月19日
    浏览(45)
  • 【Arduino环境下驱动合宙esp32c3单片机基本外设】

    本教程是参加FastBond2活动主题4 - 测量仪器中的【Arduino环境下驱动合宙esp32c3单片机基本外设】。 围绕FastBond2阶段1——基于ESP32C3开发的简易IO调试设备项目需求开发。 设计目标: 多种数字和模拟信号的输入输出:用户可以选择不同的输入输出模式,并通过设备的操作界面进行

    2024年02月04日
    浏览(60)
  • 新上架的简约版合宙ESP32C3使用arduino开发的教程

    经过两个月的缺货下架后,9块9包邮的合宙ESP32C3又重新上架了,真香。这一批都是没有带串口芯片的简约版(9块9要啥自行车)。在下架前,简约版要使用2.0.0版本的ESP32开发板库才能下载,而2.0.0版本有一些丢失arduino自带库的诡异BUG,所以一直没法用于下载。现在由于发布了2

    2024年02月05日
    浏览(92)
  • ESP32C3 LuatOS RC522①写入数据并读取M1卡

    LuatOS RC522官方示例  ESP32C3-CORE开发板    程序在数据块8中写入数据{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}

    2024年02月10日
    浏览(51)
  • ESP32C3:ninja failed with exit code 1解决方案

    这个图片是CSDN上偷的= =,自己解决了截不到图了 特征是:使用 ESP-IDF PowerShell 最后两行出现 第一步 找到安装IDF工具的安装包(离线版) https://dl.espressif.cn/dl/esp-idf/ 离线安装版快速跳转Click Here 打开后第三行 检查 Windows 注册表中的“启用长路径” [正常] 是不正常的 我是这个方

    2023年04月27日
    浏览(93)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包