SOC-ESP32S3部分:24-WiFi配网

article/2025/8/7 7:46:20

飞书文档https://x509p6c8to.feishu.cn/wiki/OD4pwTE8Jift2IkYKdNcSckOnfd

对于WiFi类设备,最重要的功能之一就是联网,WiFi需要联网,就需要知道我们家里路由的账号和密码,像手机类型的高端设备没什么问题,我们可以直接输入,但对没有屏幕的设备,或者小屏幕类没有输入键盘的设备,我们应该如何把家里的账号和密码告知设备呢?这就需要用到WiFi配网的功能。

需要特别说明的是,无论哪种配网方式,目前只能用2.4G的WiFi,不支持5GWiFi,这是模组本身频段决定的。

ESP32S3支持多种配网方式

  1. Wi-Fi AP配网(SoftAP + HTTP 服务器)
  2. 低功耗蓝牙配网
  3. Wi-Fi SmartConfig配网
  4. Wi-Fi Easy Connect(TM) (DPP)配网

方法一,方法二支持自定义协议,可扩展性更强,但是方法一体验不佳,方法二需要蓝牙支持。

方法三、方法四开发更快,其中方法四更多用于带屏幕设备,因为需要显示二维码。

那是不是方法三就是最好的呢?也不一定,我们可以了解下这种配网的技术原理:

ESP32处于混杂模式下,监听网络中的所有报文,手机APP将当前连接的ssid和password编码到UDP报文中,通过广播或者组播的方式发送报文,ESP32接收到UDP报文后解码,得到ssid和password,然后使用该组ssid和password去连接网络。
优缺点:这种方式简洁,用户也很容易操作,但是配网成功率受环境影响较大。

但是相对来说,方法三对用户的体验是较好的,产品化时,一般会考虑同时实现多种配网模式,这里我们主要讲解下方法三,其它方法的流程都是类似的,就是获取信息的管道有差异而已。

Wi-Fi SmartConfig配网

smartconfig配网支持多种协议,具体如下:

typedef enum {SC_TYPE_ESPTOUCH = 0,       /**< protocol: ESPTouch */SC_TYPE_AIRKISS,            /**< protocol: AirKiss */SC_TYPE_ESPTOUCH_AIRKISS,   /**< protocol: ESPTouch and AirKiss */SC_TYPE_ESPTOUCH_V2,        /**< protocol: ESPTouch v2*/
} smartconfig_type_t;ESPTouch:ESPTouch 是乐鑫科技推出的一种智能配网协议。
AirKiss:适用于微信生态。
ESPTouch_AirKiss:兼容两种协议。
ESPTouch_V2:ESPTouch的改进版,效率和稳定性更好,支持加密和自定义数据。ESPTouch类型的配网方式,可以使用ESPTouch APP进行配网,该APP源码开源,可以自行集成。
AirKiss类型的配网方式,可以使用微信小程序AirKiss进行配网,在乐鑫官方小程序也有这个工具。

ESPTouch,可以手机应用商店下载
 

乐鑫微信小程序
 

我们直接来看下代码部分,这类型的代码就不建议自己敲了,不用去记这些函数,是没有意义的,我们只需要懂得找到对应的官方例程,会结合AI工具看懂源码,然后参考例程去实现功能即可。

具体流程如下:

  1. 初始化NVS,因为配网成功后,路由的账号和密码需要存储在本地,下次启动可以直接联网,所以需要NVS
  2. 初始化网络协议栈
  3. 注册WiFi事件回调
  4. 开启WiFi,设置为STA模式
  5. 监听WiFi STA模式开启成功回调,初始化SmartConfig配网模式
  6. 监听WiFi 获取账号密码回调,进行联网,联网成功后关闭SmartConfig配网模式

初始化NVS

ESP_ERROR_CHECK( nvs_flash_init() );

初始化网络协议栈

    // 初始化网络接口ESP_ERROR_CHECK(esp_netif_init());// 创建默认事件循环ESP_ERROR_CHECK(esp_event_loop_create_default());// 创建默认的 WiFi 站点模式网络接口esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);// 初始化 WiFi 配置wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

注册WiFi事件回调

注册事件处理函数,这里需要注册多类事件,WIFI_EVENT、IP_EVENT、SC_EVENT
WIFI_EVENT: 处理Wi-Fi连接状态的变化。
IP_EVENT: 处理IP地址的获取和丢失。
SC_EVENT: 处理智能配置相关的事件。

1. WIFI_EVENT
描述: 涉及Wi-Fi连接的状态变化事件。
常见事件:
WIFI_EVENT_STA_START: Wi-Fi 站点模式启动。
WIFI_EVENT_STA_CONNECTED: Wi-Fi 站点成功连接到AP(接入点)。
WIFI_EVENT_STA_DISCONNECTED: Wi-Fi 站点与AP断开连接。
WIFI_EVENT_STA_STOP: Wi-Fi 站点模式停止。
WIFI_EVENT_SCAN_DONE: Wi-Fi 扫描完成。
用途: 用于监控Wi-Fi连接状态的变化,例如检测是否成功连接到Wi-Fi网络或是否断开连接。2. IP_EVENT
描述: 涉及IP地址分配或释放的事件。
常见事件:
IP_EVENT_STA_GOT_IP: 站点模式下成功获取IP地址。
IP_EVENT_STA_LOST_IP: 站点模式下丢失了IP地址。
用途: 用于确认设备是否已经成功获取到可用的IP地址,从而可以进行网络通信。3. SC_EVENT (Smart Config Event)
描述: 涉及智能配置(Smart Config)的事件。
常见事件:
SC_EVENT_SCAN_DONE: 智能配置扫描完成。
SC_EVENT_FOUND_CHANNEL: 智能配置找到目标Wi-Fi信道。
SC_EVENT_GOT_SSID_PSWD: 智能配置成功获取到Wi-Fi的SSID和密码。
SC_EVENT_CONN_SUCCESS: 智能配置成功连接到Wi-Fi。
用途: 用于通过Smart Config技术(如通过手机APP或其他设备)将Wi-Fi配置信息发送到ESP32设备。
注册事件处理函数
ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );事件回调函数
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {// WiFi 站点模式启动后,创建 SmartConfig 任务} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {// WiFi 断开连接时,重新连接并清除连接标志位} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {// 获取到 IP 地址后,代表联网成功} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {// SmartConfig 获取到 SSID 和密码事件ESP_LOGI(TAG, "Got SSID and password");} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {// SmartConfig 发送 ACK 完成事件,设置 SmartConfig 完成标志位}
}

开启WiFi,设置为STA模式

    // 设置 WiFi 模式为站点模式并启动 WiFiESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK( esp_wifi_start() );

监听WiFi STA模式开启成功回调,初始化SmartConfig配网模式

事件回调函数
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {// WiFi 站点模式启动后,创建 SmartConfig 任务xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);}//....//...
}static void smartconfig_example_task(void * parm)
{EventBits_t uxBits;// 设置 SmartConfig 类型为 SC_TYPE_ESPTOUCH_AIRKISSESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();// 启动 SmartConfigESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );while (1) {// 等待连接标志位或 SmartConfig 完成标志位uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);if(uxBits & CONNECTED_BIT) {// 连接到 AP 后的日志ESP_LOGI(TAG, "WiFi Connected to ap");}if(uxBits & ESPTOUCH_DONE_BIT) {// SmartConfig 完成后的日志ESP_LOGI(TAG, "smartconfig over");// 停止 SmartConfigesp_smartconfig_stop();// 删除 SmartConfig 任务vTaskDelete(NULL);}}
}

监听WiFi 获取账号密码回调,进行联网,联网成功后关闭SmartConfig配网模式

static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {// SmartConfig 获取到 SSID 和密码事件ESP_LOGI(TAG, "Got SSID and password");smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;wifi_config_t wifi_config;uint8_t ssid[33] = { 0 };uint8_t password[65] = { 0 };uint8_t rvd_data[33] = { 0 };bzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));memcpy(ssid, evt->ssid, sizeof(evt->ssid));memcpy(password, evt->password, sizeof(evt->password));ESP_LOGI(TAG, "SSID:%s", ssid);ESP_LOGI(TAG, "PASSWORD:%s", password);if (evt->type == SC_TYPE_ESPTOUCH_V2) {// 如果使用的是 ESPTouch V2,获取额外的数据ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );ESP_LOGI(TAG, "RVD_DATA:");for (int i=0; i<33; i++) {printf("%02x ", rvd_data[i]);}printf("\n");}// 断开当前 WiFi 连接,设置新的 WiFi 配置并重新连接ESP_ERROR_CHECK( esp_wifi_disconnect() );ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );esp_wifi_connect();} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {// SmartConfig 发送 ACK 完成事件,设置 SmartConfig 完成标志位xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}

最终整体代码如下:

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_eap_client.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "esp_mac.h"static EventGroupHandle_t s_wifi_event_group;static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "smartconfig_example";static void smartconfig_example_task(void * parm);static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {// WiFi 站点模式启动后,创建 SmartConfig 任务xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {// WiFi 断开连接时,重新连接并清除连接标志位esp_wifi_connect();xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {// 获取到 IP 地址后,设置连接标志位xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {// SmartConfig 扫描完成事件ESP_LOGI(TAG, "Scan done");} else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {// SmartConfig 找到信道事件ESP_LOGI(TAG, "Found channel");} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {// SmartConfig 获取到 SSID 和密码事件ESP_LOGI(TAG, "Got SSID and password");smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;wifi_config_t wifi_config;uint8_t ssid[33] = { 0 };uint8_t password[65] = { 0 };uint8_t rvd_data[33] = { 0 };bzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));memcpy(ssid, evt->ssid, sizeof(evt->ssid));memcpy(password, evt->password, sizeof(evt->password));ESP_LOGI(TAG, "SSID:%s", ssid);ESP_LOGI(TAG, "PASSWORD:%s", password);if (evt->type == SC_TYPE_ESPTOUCH_V2) {// 如果使用的是 ESPTouch V2,获取额外的数据ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );ESP_LOGI(TAG, "RVD_DATA:");for (int i=0; i<33; i++) {printf("%02x ", rvd_data[i]);}printf("\n");}// 断开当前 WiFi 连接,设置新的 WiFi 配置并重新连接ESP_ERROR_CHECK( esp_wifi_disconnect() );ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );esp_wifi_connect();} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {// SmartConfig 发送 ACK 完成事件,设置 SmartConfig 完成标志位xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}static void initialise_wifi(void)
{// 初始化网络接口ESP_ERROR_CHECK(esp_netif_init());// 创建事件组s_wifi_event_group = xEventGroupCreate();// 创建默认事件循环ESP_ERROR_CHECK(esp_event_loop_create_default());// 创建默认的 WiFi 站点模式网络接口esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);// 初始化 WiFi 配置wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_wifi_init(&cfg) );// 注册事件处理函数ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );// 设置 WiFi 模式为站点模式并启动 WiFiESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK( esp_wifi_start() );
}static void smartconfig_example_task(void * parm)
{EventBits_t uxBits;// 设置 SmartConfig 类型为 SC_TYPE_ESPTOUCH_AIRKISSESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();// 启动 SmartConfigESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );while (1) {// 等待连接标志位或 SmartConfig 完成标志位uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);if(uxBits & CONNECTED_BIT) {// 连接到 AP 后的日志ESP_LOGI(TAG, "WiFi Connected to ap");}if(uxBits & ESPTOUCH_DONE_BIT) {// SmartConfig 完成后的日志ESP_LOGI(TAG, "smartconfig over");// 停止 SmartConfigesp_smartconfig_stop();// 删除 SmartConfig 任务vTaskDelete(NULL);}}
}void app_main(void)
{// 初始化 NVS 闪存ESP_ERROR_CHECK( nvs_flash_init() );// 初始化 WiFiinitialise_wifi();
}

这部分代码编译运行后,就会进入SC_TYPE_ESPTOUCH_AIRKISS配网模式,并打印以下日志。

I (568) smartconfig: SC version: V3.0.2
I (5388) wifi:ic_enable_sniffer
I (5388) smartconfig: Start to find channel...
I (5388) smartconfig_example: Scan done

接着我们手机连接一个2.4G的路由(重要,不支持5G WiFi,打开乐鑫小程序,点击Airkiss配网,输入密码,点击配网即可。当然你下载ESPTouch APP进行配网也是可以的。

注意:Smartconfig配网通过UDP广播实现,所以手机离板卡越近越好,周围的环境干扰越少越好。

一般配网失败就两种情况

  1. 1、连接了5G的路由
  2. 2、输入密码错误,或者有特殊的字符
  3. 3、周围的2.4G干扰多

所以按上述流程排查下,多试几次即可,如果配网成功,就可以看到以下日志啦,主要看下接收到的SSID和PASSWORD对不对。

I (48578) smartconfig: TYPE: AIRKISS
I (48578) smartconfig: T|AP MAC: 00:94:ec:89:df:34
I (48578) smartconfig: Found channel on 6-0. Start to get ssid and password...
I (48588) smartconfig_example: Found channel
I (52068) smartconfig: T|pswd: 123456789
I (52068) smartconfig: T|ssid: leo
I (52068) wifi:ic_disable_sniffer
I (52068) smartconfig_example: Got SSID and password
I (52068) smartconfig_example: SSID:leo
I (52078) smartconfig_example: PASSWORD:123456789
W (52078) wifi:Password length matches WPA2 standards, authmode threshold changes from OPEN to WPA2
I (53168) wifi:new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1, snd_ch_cfg:0x0
I (53168) wifi:state: init -> auth (0xb0)
I (53178) wifi:state: auth -> assoc (0x0)
I (53178) wifi:state: assoc -> run (0x10)
I (53208) wifi:connected with smart_013, aid = 50, channel 6, BW20, bssid = 00:94:ec:89:df:34
I (53208) wifi:security: WPA2-PSK, phy: bgn, rssi: -35
I (53228) wifi:pm start, type: 1I (53228) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
I (53228) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
I (53288) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (54338) esp_netif_handlers: sta ip: 192.168.3.56, mask: 255.255.255.0, gw: 192.168.3.1
I (54338) smartconfig_example: WiFi Connected to ap
I (57418) smartconfig_example: smartconfig over

上述代码,每次启动后,不管之前有没有配置过,都会进入配网模式,不符合实际的应用,这里对代码进行修改,使配网的信息(帐号和密码)被保存在 NVS 中,每次配网之前读取NVS中的信息,如果未配网过,则进行配网操作,如果已经配网过,则直接连接路由器,只需要修改smartconfig_example_task函数即可。

static void smartconfig_example_task(void * parm)
{EventBits_t uxBits;wifi_config_t myconfig = {0};ESP_LOGI(TAG, "creat smartconfig_example_task");// 获取wifi配置信息esp_wifi_get_config(ESP_IF_WIFI_STA, &myconfig);if (strlen((char*)myconfig.sta.ssid) > 0){//如果配置过,就直接连接wifiESP_LOGI(TAG, "alrealy set, SSID is :%s,start connect", myconfig.sta.ssid);esp_wifi_connect();}else{// 如果没有配置过,就进行配网操作ESP_LOGI(TAG, "have no set, start to config");ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );//支持APP ESPTOUCH和微信AIRKISSsmartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );}while (1) {// 等待连接标志位或 SmartConfig 完成标志位uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);if(uxBits & CONNECTED_BIT) {// 连接到 AP 后的日志ESP_LOGI(TAG, "WiFi Connected to ap");}if(uxBits & ESPTOUCH_DONE_BIT) {// SmartConfig 完成后的日志ESP_LOGI(TAG, "smartconfig over");// 停止 SmartConfigesp_smartconfig_stop();// 删除 SmartConfig 任务vTaskDelete(NULL);}}
}

想要重新配网,需要删除原来配网保存的信息,这里提供两种方法。

方法一:调试阶段,执行idf.py erase_flash擦除flash

idf.py erase_flash

方法二:产品阶段,增加一个按键或交互入口来重置配网信息,适用实际项目开发。

通过触发按键,例如长按10秒来调用esp_wifi_restore()函数,重置配网信息。


http://www.hkcw.cn/article/SVaOmbtYPb.shtml

相关文章

使用langchain实现五种分块策略:语义分块、父文档分块、递归分块、特殊格式、固定长度分块

文章目录 分块策略详解1. 固定长度拆分&#xff08;简单粗暴&#xff09;2. 递归字符拆分&#xff08;智能切割&#xff09;3. 特殊格式拆分&#xff08;定向打击&#xff09;Markdown分块 4. 语义分割&#xff08;更智能切割&#xff09;基于Embedding的语义分块基于模型的端到…

(七)【Linux进程的创建、终止和等待】

1 进程创建 1.1 在谈fork函数 #include <unistd.h> // 需要的头文件// 返回值&#xff1a;子进程中返回0&#xff0c;父进程返回子进程id&#xff0c;出错返回-1调用fork函数后&#xff0c;内核做了下面的工作&#xff1a; 创建了一个子进程的PCB结构体、并拷贝一份相…

EMO2:基于末端执行器引导的音频驱动虚拟形象视频生成

今天带来EMO2&#xff08;全称End-Effector Guided Audio-Driven Avatar Video Generation&#xff09;是阿里巴巴智能计算研究院研发的创新型音频驱动视频生成技术。该技术通过结合音频输入和静态人像照片&#xff0c;生成高度逼真且富有表现力的动态视频内容&#xff0c;值得…

Baklib知识中台加速企业服务智能化实践

知识中台架构体系构建 Baklib 通过构建多层级架构体系实现知识中台的底层支撑&#xff0c;其核心包含数据采集层、知识加工层、服务输出层及智能应用层。在数据采集端&#xff0c;系统支持对接CRM、ERP等业务系统&#xff0c;结合NLP技术实现非结构化数据的自动抽取&#xff1…

GpuGeek 618大促引爆AI开发新体验

随着生成式AI技术迅猛发展&#xff0c;高效可靠的算力资源已成为企业和开发者突破创新瓶颈的战略支点。根据赛迪顾问最新发布的《2025中国AI Infra平台市场发展研究报告》显示&#xff0c;2025年中国生成式人工智能企业应用市场规模将达到629.0亿元&#xff0c;作为AI企业级应用…

Linux线程同步实战:多线程程序的同步与调度

个人主页&#xff1a;chian-ocean 文章专栏-Linux Linux线程同步实战&#xff1a;多线程程序的同步与调度 个人主页&#xff1a;chian-ocean文章专栏-Linux 前言&#xff1a;为什么要实现线程同步线程饥饿&#xff08;Thread Starvation&#xff09;示例&#xff1a;抢票问题 …

任务22:创建示例Django项目,展示ECharts图形示例

任务描述 知识点&#xff1a; DjangoECharts 重 点&#xff1a; DjangoECharts 内 容&#xff1a; 创建Django项目掌握ECharts绘制图形通过官网ECharts示例&#xff0c;完成Django项目&#xff0c;并通过配置项进行修改图形 任务指导 1、创建web_test的Django项目 2…

深度学习入门Day1--Python基础

一、基础语法 1.变量 python是“动态类型语言”的编程语言。用户无需明确指出x的类型是int。 x10 #初始化 print(x) #输出x x100 #赋值 print(x) print(type(x))#输出x的类型<class int>2.算术计算 >>>4*5 >20 >>>3**3#**表示乘方&#xff08;3…

九坤:熵最小化加速LLM收敛

&#x1f4d6;标题&#xff1a;One-shot Entropy Minimization &#x1f310;来源&#xff1a;arXiv, 2505.20282 &#x1f31f;摘要 我们训练了 13,440 个大型语言模型&#xff0c;发现熵最小化只需要一个未标记的数据和 10 步优化&#xff0c;以实现比使用数千个数据获得的…

微服务面试(分布式事务、注册中心、远程调用、服务保护)

1.分布式事务 分布式事务&#xff0c;就是指不是在单个服务或单个数据库架构下&#xff0c;产生的事务&#xff0c;例如&#xff1a; 跨数据源的分布式事务跨服务的分布式事务综合情况 我们之前解决分布式事务问题是直接使用Seata框架的AT模式&#xff0c;但是解决分布式事务…

儿童节快乐,聊聊数字的规律和同余原理

某年的6月1日是星期日。那么&#xff0c;同一年的6月30日是星期几&#xff1f; 星期是7天一个循环。所以说&#xff0c;这一天是星期几&#xff0c;7天之后同样也是星期几。而6月30日是在6月1日的29天之后&#xff1a;29 7 4 ... 1用29除以7&#xff0c;可以得出余数为1。而…

视觉分析明火检测助力山东化工厂火情防控

视觉分析技术赋能化工厂火情防控&#xff1a;从山东事故看明火与烟雾检测的应用价值 一、背景&#xff1a;山东化工事故中的火情防控痛点 近期&#xff0c;山东高密友道化学有限公司、淄博润兴化工科技有限公司等企业接连发生爆炸事故&#xff0c;暴露出传统火情防控手段的局…

javaEE->多线程:定时器

一. 定时器 约定一个时间&#xff0c;时间到了&#xff0c;执行某个代码逻辑&#xff08;进行网络通信时常见&#xff09; 客户端给服务器发送请求 之后就需要等待 服务器的响应&#xff0c;客户端不可能无限的等&#xff0c;需要一个最大的期限。这里“等待的最大时间”可以用…

HTML表单

1. 什么是表单 表单常用格式 文本框 密码框 单选按钮 复选框 列表框 按钮 多行文本域 文件域 邮箱 网址 数字 滑块 搜索框 2. 表单的高级应用 隐藏域&#xff08;⭐&#xff09; 隐藏域在网页中会经常被使用&#xff0c;比如我们登录了以后需要持续使用我们的登录信息&#xff…

STM32F407寄存器操作(ADC非连续扫描模式)

1.前言 书接上回&#xff0c;在看手册的时候我突然发现手册上还描述了另一种ADC扫描模式&#xff0c;即非连续扫描模式&#xff0c;想着连续扫描模式都已经探索过了&#xff0c;那就顺手把非非连续模式研究一下吧。 2.理论 我们先看看手册&#xff0c;这里我就以规则通道举例…

老年照护实训室建设方案设计:基础照护与专业护理实训

老年照护实训室的建设是提升老年照护人才培养质量的关键环节&#xff0c;其方案设计需精准对接基础照护与专业护理的实训需求&#xff0c;为学习者构建理论与实践深度融合的教学场景。点击获取实训室建设方案 一、建设背景与目标 &#xff08;一&#xff09;建设背景 随着人…

C语言 — 文件

目录 1.流1.1 流的概念1.2 常见的的流 2.文件的打开和关闭2.1 fopen函数2.2 fclose函数2.3 文件的打开和关闭 3.文件的输入输出函数3.1 fputc函数3.2 fgetc函数3.3 feof函数和ferror函数3.4 fputs函数3.5 fgets函数3.6 fwrite函数3.7 fread函数3.8 fprintf函数3.9 fscanf函数 4…

13. springCloud AlibabaSeata处理分布式事务

目录 一、分布式事务面试题 1.多个数据库之间如何处理分布式事务&#xff1f; 2.若拿出如下场景&#xff0c;阁下将如何应对? 3.阿里巴巴的Seata-AT模式如何做到对业务的无侵入? 4.对于分布式事务问题&#xff0c;你知道的解决方案有哪些?请你谈谈? 二、分布式事务问题…

java多线程与JUC

进程线程 进程&#xff1a;进程是操作系统分配资源的基本单位。在电脑中&#xff0c;一个软件就是一个进程 线程&#xff1a;线程是CPU调度的基本单位&#xff0c;是进程内的执行单元。相当于一个软件中的不同功能 多线程程序的特点&#xff1a;程序可以同时去做多件事&#…

GCC 下载安装

下载 官网&#xff1a;GCC, the GNU Compiler Collection- GNU Project Cygwin linux 环境 MinGW 在 Windows 上提供 GNU 开发工具比 Cygwin 更轻量&#xff08;不模拟完整的 POSIX 环境&#xff09;选择&#xff1a;binaries选择mingw-w64