STM32 ESP8266 WiFi模块驱动

1. 简介

ESP8266是一款高度集成的WiFi芯片,可以为其他设备提供WiFi联网功能。本笔记记录了基于STM32 HAL库的ESP8266驱动实现,包括硬件连接、初始化配置、AT指令交互等关键部分。

项目源码仓库:STM32_Sensor_Drives

2. 硬件连接

在这里插入图片描述

2.1 引脚定义

ESP8266与STM32的连接引脚定义如下:

/******************************** ESP8266 连接引脚定义 ***********************************/
#define      macESP8266_CH_PD_PORT                            GPIOA
#define      macESP8266_CH_PD_PIN                             GPIO_PIN_11
#define      macESP8266_RST_PORT                              GPIOA
#define      macESP8266_RST_PIN                               GPIO_PIN_12#define      macESP8266_USART_BAUD_RATE                       115200
#define      macESP8266_USART_TX_PORT                         GPIOB   
#define      macESP8266_USART_TX_PIN                          GPIO_Pin_10
#define      macESP8266_USART_RX_PORT                         GPIOB
#define      macESP8266_USART_RX_PIN                          GPIO_Pin_11
#define      macESP8266_USARTx                                huart3

2.2 GPIO初始化

gpio.c中,我们初始化了ESP8266所需的GPIO引脚:

void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);/*Configure GPIO pins : PA4 PA11 PA12 */GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_11|GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// ... 其他GPIO配置 ...
}

3. 数据结构定义

3.1 ESP8266工作模式枚举

/******************************* ESP8266 数据类型定义 ***************************/
typedef enum{STA,        // 客户端模式AP,         // 热点模式STA_AP      // 客户端+热点模式
} ENUM_Net_ModeTypeDef;typedef enum{enumTCP,    // TCP协议enumUDP,    // UDP协议
} ENUM_NetPro_TypeDef;typedef enum{Multiple_ID_0 = 0,Multiple_ID_1 = 1,Multiple_ID_2 = 2,Multiple_ID_3 = 3,Multiple_ID_4 = 4,Single_ID_0 = 5,
} ENUM_ID_NO_TypeDef;typedef enum{OPEN = 0,      // 开放模式WEP = 1,       // WEP加密WPA_PSK = 2,   // WPA-PSK加密WPA2_PSK = 3,  // WPA2-PSK加密WPA_WPA2_PSK = 4, // WPA/WPA2混合加密
} ENUM_AP_PsdMode_TypeDef;

3.2 数据接收缓冲区结构

/******************************* ESP8266 外部全局变量声明 ***************************/
#define RX_BUF_MAX_LEN     1024                                     //最大接收缓存字节数extern struct  STRUCT_USARTx_Fram                                  //串口数据帧的处理结构体
{char  Data_RX_BUF [ RX_BUF_MAX_LEN ];  // 数据接收缓冲区union {__IO uint16_t InfAll;struct  {__IO uint16_t FramLength       :15;  // 数据帧长度__IO uint16_t FramFinishFlag   :1;   // 数据帧接收完成标志} InfBit;}Inf;} strEsp8266_Fram_Record;

4. 函数宏定义

/*********************************************** ESP8266 函数宏定义 *******************************************/
#define     macESP8266_CH_ENABLE()                 HAL_GPIO_WritePin(macESP8266_CH_PD_PORT, macESP8266_CH_PD_PIN, GPIO_PIN_SET)
#define     macESP8266_CH_DISABLE()                HAL_GPIO_WritePin(macESP8266_CH_PD_PORT, macESP8266_CH_PD_PIN, GPIO_PIN_RESET)#define     macESP8266_RST_HIGH_LEVEL()            HAL_GPIO_WritePin(macESP8266_RST_PORT, macESP8266_RST_PIN, GPIO_PIN_SET)
#define     macESP8266_RST_LOW_LEVEL()             HAL_GPIO_WritePin(macESP8266_RST_PORT, macESP8266_RST_PIN, GPIO_PIN_RESET)

5. 串口重定向

为了方便打印调试信息,重定向了printf函数:

/* 串口重定向相关定义 */
extern UART_HandleTypeDef *current_huart;
#define printf_log(...) do { \current_huart = &huart2; \printf(__VA_ARGS__); \
} while(0)#define printf_wifi(...) do { \current_huart = &macESP8266_USARTx; \printf(__VA_ARGS__); \
} while(0)/* printf重定向实现 */
int fputc(int ch, FILE *f)
{if (f == stdout) // 仅处理标准输出{HAL_UART_Transmit(current_huart, (uint8_t *)&ch, 1, 100); // 阻塞发送if (ch == '\n')                                           // 发送\n时自动补充\rHAL_UART_Transmit(current_huart, (uint8_t *)"\r", 1, 100);}return ch;
}

6. ESP8266初始化与配置

6.1 ESP8266启动函数

/*** @brief  ESP8266 (Sta Tcp Client)透传* @param  无* @retval 无*/
void ESP8266_start(void)
{printf_log("\r\n正在配置 ESP8266 ......\r\n");HAL_UART_Receive_IT(&macESP8266_USARTx, &UART_TEMP_CHAR, 1);macESP8266_CH_ENABLE();  // 使能ESP8266ESP8266_AT_Test();       // AT测试ESP8266_Net_Mode_Choose(STA_AP);  // 设置为STA+AP模式// 连接到指定的WiFi热点while (!ESP8266_JoinAP(macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd));ESP8266_Cmd("AT+CIFSR", "OK", 0, 1000);  // 查询IP地址ESP8266_Cmd("AT+CIPMUX=1", "OK", 0, 1000);  // 启用多连接ESP8266_Cmd("AT+CIPSERVER=1,8288", "OK", 0, 1000);  // 创建TCP服务器// ESP8266_Cmd("AT+CIPSTART="TCP",192.168.1.1,8000","OK",0,1000);printf_log("\r\n配置 ESP8266 完毕\r\n");
}

6.2 ESP8266复位函数

/** 函数名:ESP8266_Rst* 描述  :重启WF-ESP8266模块* 输入  :无* 返回  : 无* 调用  :被 ESP8266_AT_Test 调用*/
void ESP8266_Rst(void)
{
#if 0ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );#elsemacESP8266_RST_LOW_LEVEL();  // 复位引脚拉低HAL_Delay(500);macESP8266_RST_HIGH_LEVEL();  // 复位引脚拉高
#endif
}

7. AT指令交互

7.1 AT指令发送与响应检查

/** 函数名:ESP8266_Cmd* 描述  :对WF-ESP8266模块发送AT指令* 输入  :cmd,待发送的指令*         reply1,reply2,期待的响应,为NULL表不需响应,两者为或逻辑关系*         waittime,等待响应的时间* 返回  : 1,指令发送成功*         0,指令发送失败* 调用  :被外部调用*/
uint8_t ESP8266_Cmd(char *cmd, char *reply1, char *reply2, uint32_t waittime)
{strEsp8266_Fram_Record.Inf.InfBit.FramLength = 0; // 从新开始接收新的数据包printf_wifi("%s\r\n", cmd);  // 发送AT指令if ((reply1 == NULL) && (reply2 == NULL)) // 不需要接收数据return 1;HAL_Delay(waittime); // 延时等待响应strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.Inf.InfBit.FramLength] = '\0';printf_log("%s", strEsp8266_Fram_Record.Data_RX_BUF);  // 打印响应数据// 检查响应是否包含期望的字符串if ((reply1 != NULL) && (reply2 != NULL)){if (strstr(strEsp8266_Fram_Record.Data_RX_BUF, reply1) != NULL ||strstr(strEsp8266_Fram_Record.Data_RX_BUF, reply2) != NULL)return 1;return 0;}else if (reply1 != NULL){if (strstr(strEsp8266_Fram_Record.Data_RX_BUF, reply1) != NULL)return 1;return 0;}else{if (strstr(strEsp8266_Fram_Record.Data_RX_BUF, reply2) != NULL)return 1;return 0;}
}

7.2 AT测试函数

/** 函数名:ESP8266_AT_Test* 描述  :对WF-ESP8266模块进行AT测试启动* 输入  :无* 返回  : 无* 调用  :被外部调用*/
void ESP8266_AT_Test(void)
{char count = 0;macESP8266_RST_HIGH_LEVEL();HAL_Delay(1000);while (count < 10){if (ESP8266_Cmd("AT", "OK", NULL, 500))  // 发送AT测试指令return;ESP8266_Rst();  // 如果失败则复位ESP8266++count;}
}

8. WiFi连接功能

8.1 设置工作模式

/** 函数名:ESP8266_Net_Mode_Choose* 描述  :选择WF-ESP8266模块的工作模式* 输入  :enumMode,工作模式* 返回  : 1,选择成功*         0,选择失败* 调用  :被外部调用*/
uint8_t ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode)
{switch (enumMode){case STA:  // 客户端模式return ESP8266_Cmd("AT+CWMODE=1", "OK", "no change", 2500);case AP:   // 热点模式return ESP8266_Cmd("AT+CWMODE=2", "OK", "no change", 2500);case STA_AP:  // 客户端+热点模式return ESP8266_Cmd("AT+CWMODE=3", "OK", "no change", 2500);default:return 0;}
}

8.2 连接WiFi热点

/** 函数名:ESP8266_JoinAP* 描述  :WF-ESP8266模块连接外部WiFi* 输入  :pSSID,WiFi名称字符串*       :pPassWord,WiFi密码字符串* 返回  : 1,连接成功*         0,连接失败* 调用  :被外部调用*/
uint8_t ESP8266_JoinAP(char *pSSID, char *pPassWord)
{char cCmd[120];sprintf(cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord);return ESP8266_Cmd(cCmd, "OK", NULL, 5000);
}

8.3 创建WiFi热点

/** 函数名:ESP8266_BuildAP* 描述  :WF-ESP8266模块创建WiFi热点* 输入  :pSSID,WiFi名称字符串*       :pPassWord,WiFi密码字符串*       :enunPsdMode,WiFi加密方式代号字符串* 返回  : 1,创建成功*         0,创建失败* 调用  :被外部调用*/
uint8_t ESP8266_BuildAP(char *pSSID, char *pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode)
{char cCmd[120];sprintf(cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode);return ESP8266_Cmd(cCmd, "OK", 0, 1000);
}

9. TCP/IP通信功能

9.1 启用多连接

/** 函数名:ESP8266_Enable_MultipleId* 描述  :WF-ESP8266模块启动多连接* 输入  :enumEnUnvarnishTx,配置是否多连接* 返回  : 1,配置成功*         0,配置失败* 调用  :被外部调用*/
uint8_t ESP8266_Enable_MultipleId(FunctionalState enumEnUnvarnishTx)
{return ESP8266_Cmd("AT+CIPMUX=%d", "OK", 0, 500);
}

9.2 连接服务器

/** 函数名:ESP8266_Link_Server* 描述  :WF-ESP8266模块连接外部服务器* 输入  :enumE,网络协议*       :ip,服务器IP字符串*       :ComNum,服务器端口字符串*       :id,模块连接服务器的ID* 返回  : 1,连接成功*         0,连接失败* 调用  :被外部调用*/
uint8_t ESP8266_Link_Server(ENUM_NetPro_TypeDef enumE, char *ip, char *ComNum, ENUM_ID_NO_TypeDef id)
{char cStr[100] = {0}, cCmd[120];switch (enumE){case enumTCP:sprintf(cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum);break;case enumUDP:sprintf(cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum);break;default:break;}if (id < 5)sprintf(cCmd, "AT+CIPSTART=%d,%s", id, cStr);elsesprintf(cCmd, "AT+CIPSTART=%s", cStr);return ESP8266_Cmd(cCmd, "OK", "ALREAY CONNECT", 4000);
}

9.3 创建/关闭TCP服务器

/** 函数名:ESP8266_StartOrShutServer* 描述  :WF-ESP8266模块开启或关闭服务器模式* 输入  :enumMode,开启/关闭*       :pPortNum,服务器端口号字符串*       :pTimeOver,服务器超时时间字符串,单位:秒* 返回  : 1,操作成功*         0,操作失败* 调用  :被外部调用*/
uint8_t ESP8266_StartOrShutServer(FunctionalState enumMode, char *pPortNum, char *pTimeOver)
{char cCmd1[120], cCmd2[120];if (enumMode)  // 开启服务器{sprintf(cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum);sprintf(cCmd2, "AT+CIPSTO=%s", pTimeOver);return (ESP8266_Cmd(cCmd1, "OK", 0, 500) &&ESP8266_Cmd(cCmd2, "OK", 0, 500));}else  // 关闭服务器{sprintf(cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum);return ESP8266_Cmd(cCmd1, "OK", 0, 500);}
}

10. 数据收发功能

10.1 发送数据

/** 函数名:ESP8266_SendString* 描述  :WF-ESP8266模块发送字符串* 输入  :enumEnUnvarnishTx,声明是否已使能了透传模式*       :pStr,要发送的字符串*       :ulStrLength,要发送的字符串的字节数*       :ucId,哪个ID发送的字符串* 返回  : 1,发送成功*         0,发送失败* 调用  :被外部调用*/
uint8_t ESP8266_SendString(FunctionalState enumEnUnvarnishTx, char *pStr, uint32_t ulStrLength, ENUM_ID_NO_TypeDef ucId)
{char cStr[20];uint8_t bRet = 0;if (enumEnUnvarnishTx)  // 透传模式{printf_wifi("%s", pStr);bRet = 1;}else  // 非透传模式{if (ucId < 5)sprintf(cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2);elsesprintf(cStr, "AT+CIPSEND=%d", ulStrLength + 2);ESP8266_Cmd(cStr, "> ", 0, 1000);  // 等待发送指令的响应bRet = ESP8266_Cmd(pStr, "SEND OK", 0, 1000);  // 发送数据}return bRet;
}

10.2 接收数据

/** 函数名:ESP8266_ReceiveString* 描述  :WF-ESP8266模块接收字符串* 输入  :enumEnUnvarnishTx,声明是否已使能了透传模式* 返回  : 接收到的字符串首地址* 调用  :被外部调用*/
char *ESP8266_ReceiveString(FunctionalState enumEnUnvarnishTx)
{char *pRecStr = 0;strEsp8266_Fram_Record.Inf.InfBit.FramLength = 0;strEsp8266_Fram_Record.Inf.InfBit.FramFinishFlag = 0;while (!strEsp8266_Fram_Record.Inf.InfBit.FramFinishFlag);  // 等待接收完成strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.Inf.InfBit.FramLength] = '\0';if (enumEnUnvarnishTx)  // 透传模式pRecStr = strEsp8266_Fram_Record.Data_RX_BUF;else  // 非透传模式{if (strstr(strEsp8266_Fram_Record.Data_RX_BUF, "+IPD"))pRecStr = strEsp8266_Fram_Record.Data_RX_BUF;}return pRecStr;
}

10.3 UART接收中断回调

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart == &macESP8266_USARTx){if (strEsp8266_Fram_Record.Inf.InfBit.FramLength < (RX_BUF_MAX_LEN - 1))strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.Inf.InfBit.FramLength++] = UART_TEMP_CHAR;if (HAL_UART_GetState(&macESP8266_USARTx) == HAL_UART_STATE_READY){strEsp8266_Fram_Record.Inf.InfBit.FramFinishFlag = 1;ucTcpClosedFlag = strstr(strEsp8266_Fram_Record.Data_RX_BUF, "CLOSED\r\n") ? 1 : 0;strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.Inf.InfBit.FramLength] = '\0';if (strEsp8266_Fram_Record.Data_RX_BUF[strEsp8266_Fram_Record.Inf.InfBit.FramLength-1] == '}'){printf_log(strEsp8266_Fram_Record.Data_RX_BUF);strEsp8266_Fram_Record.Inf.InfBit.FramLength = 0;}}HAL_UART_Receive_IT(&macESP8266_USARTx, &UART_TEMP_CHAR, 1);}
}

11. 主程序调用

main.c中,我们初始化外设并调用ESP8266启动函数:

int main(void)
{/* 初始化HAL库 */HAL_Init();/* 配置系统时钟 */SystemClock_Config();/* 初始化外设 */MX_GPIO_Init();MX_USART2_UART_Init();MX_USART3_UART_Init();/* 启动ESP8266 WiFi模块 */ESP8266_start();/* 主循环 */while (1){HAL_Delay(200);}
}

12. 总结

本驱动实现了基于STM32 HAL库的ESP8266 WiFi模块驱动,主要功能包括:

  1. ESP8266初始化与复位
  2. AT指令交互
  3. WiFi连接与热点创建
  4. TCP/IP服务器创建与客户端连接
  5. 数据收发功能

通过这些功能,可以实现STM32与ESP8266的通信,进而实现WiFi联网功能,为物联网应用提供基础。

使用时,只需修改macUser_ESP8266_ApSsidmacUser_ESP8266_ApPwd为实际的WiFi名称和密码即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92828.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92828.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92828.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7 种最佳 DBAN 替代方案,彻底擦除硬盘数据

DBAN&#xff08;Darik 的 Boot and Nuke&#xff09;长期以来一直是安全擦除计算机数据的首选解决方案。然而&#xff0c;尽管 DBAN 广受欢迎&#xff0c;但它也存在一些明显的局限性&#xff0c;这些局限性随着时间的推移变得越来越明显。现在&#xff0c;本文将更详细地探讨…

【K8s】K8s控制器——Deamonset、Statefulset、Job与CronJob

1、Deamonset2、Statefulset3、Job与CronJob一次性作业与周期性作业#- 8.6 #cat > daemonset.yml <<EOF apiVersion: apps/v1 kind: DaemonSet metadata:name: test-demonsetlabels:daemonset: test spec:selector:matchLabels:name: testpodtemplate:metadata:labels…

基于柔性管控终端的新能源汽车充电站有序充电系统设计与实现

摘要&#xff1a;随着新能源汽车的迅猛发展&#xff0c;充电基础设施面临着电力负荷激增、电网稳定性下降等挑战。本文针对当前充电设施无序充电导致的电网压力问题&#xff0c;提出了一种基于柔性管控终端的充电站有序充电系统解决方案。通过分析国内外有序充电技术发展现状&a…

10-docker基于dockerfile自动制作镜像

文章目录一.为什么要学习自动构建镜像1.为什么要学习自动化构建镜像2.根据dockerfile自动构建镜像的流程3.常用的dockerfile指令二.使用dockerfile构建nginx服务镜像&#xff08;FR0M&#xff0c;RUN&#xff0c;CMD&#xff09;1.创建dockerfile的存储路径2.编写dockerfile文件…

如何解决大模型API明明一分钟内只发起了一次请求,却触发了 “Your account reached max request” 的错误

问题背景 在使用 OpenAI SDK 进行 API 调用时&#xff0c;你可能会遇到这样的困惑&#xff1a;明明一分钟内只发起了一次请求&#xff0c;却触发了 “Your account reached max request” 的错误。仔细排查之后发现&#xff0c;并不是 SDK 真正向服务端发送了超限的多次请求&a…

使用Spring Boot+Vue3开源的即时通讯 IM 系统

1. 产品概述V-IM 是一款基于 Electron 和 Vue 3 开发的跨平台即时通讯客户端&#xff0c;目前正在进行2025年版本的开发。该应用提供了丰富的即时通讯功能&#xff0c;支持个人聊天、群组聊天、文件传输等功能&#xff0c;适用于企业内部通讯或团队协作场景。2. 核心功能2.1 用…

在Mac上搭建本地AI工作流:Dify与DeepSeek的完美结合

在Mac上搭建本地AI工作流&#xff1a;Dify与DeepSeek的完美结合 一、Dify平台简介 Dify是一个开源的大语言模型(LLM)应用开发平台&#xff0c;旨在简化和加速生成式AI应用的创建和部署。其名字蕴含着"Define&#xff08;定义&#xff09; Modify&#xff08;修改&#x…

centos出现ping: baidu.com: 未知的名称或服务问题

出现的问题如下&#xff1a;自己电脑连接的是实验室的无线网&#xff0c;宿主机可以上网&#xff0c;但是虚拟机无法ping通百度 解决&#xff1a; 将连接的网络换成自己的手机热点&#xff0c;然后就解决了。。。

GitHub第三方登录全解析:OAuth 2.0流程详解(适合初学者)

&#x1f510; GitHub第三方登录全解析&#xff1a;OAuth 2.0流程详解&#xff08;适合初学者&#xff09; &#x1f31f; 什么是OAuth&#xff1f;为什么需要它&#xff1f; 想象一下&#xff1a;你开发了一个学习笔记应用"DocFlow"&#xff0c;用户需要登录才能使用…

MyBatis持久层实现

MyBatis持久层实现 package com.example.usermanagement.mapper;import com.example.usermanagement.entity.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List;/*** 用户Mapper接口* Mapper: 标识这是M…

BW处理链日志存储分析与清理

处理链日志存储分析使用程序 RSPC_LOGS_ANALYZE 分析处理链日志占用空间*&---------------------------------------------------------------------* *& Report RSPC_LOGS_ANALYZE *&---------------------------------------------------------------------* *&a…

mysql 简单操作手册

以下是一份 MySQL 日常操作速查手册&#xff0c;包含启动/停止服务、连接/退出客户端、数据库管理、用户权限等常用命令&#xff0c;适用于 macOS&#xff08;Homebrew 安装&#xff09;和 Linux 系统&#xff1a;一、服务管理 &#x1f6a6;操作命令&#xff08;Homebrew&…

HTML5 Web Workers 深度剖析:助力网页性能飞速提升

在当今数字化时代&#xff0c;Web 应用的性能已成为决定用户体验和业务成功的关键因素。随着 Web 应用的复杂性不断增加&#xff0c;如何高效利用设备资源、提升网页响应速度成为开发者面临的重大挑战。 HTML5 Web Workers 的诞生与意义 在传统的网页开发中&#xff0c;JavaScr…

调度系统部署架构是什么样的呢?

简单示例一个部署架构图&#xff0c;如下所示&#xff1a;&#x1f4d8; 各组件说明&#xff1a;✅ 服务器端组件&#xff08;控制节点&#xff09;Slurm&#xff1a;slurmctld&#xff08;主控调度器&#xff09;&#xff0c;slurmdbd&#xff08;数据库服务&#xff09;PBS P…

SQL 与 NoSQL 的核心区别

数据库是存储、管理和检索数据的系统。根据数据模型和设计理念&#xff0c;可分为SQL 数据库&#xff08;关系型数据库&#xff09; 和NoSQL 数据库&#xff08;非关系型数据库&#xff09;。两者的核心区别在于数据的组织方式、灵活性、事务支持和适用场景。&#x1f4a1;一、…

力扣 hot100 Day71

45. 跳跃游戏 II 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说&#xff0c;如果你在索引 i 处&#xff0c;你可以跳转到任意 (i j) 处&#xff1a; 0 < j < nums[i] 且i j < n …

什么是 Spring MVC?

题目详细答案Spring MVC 是 Spring 框架中的一个模块&#xff0c;用于构建基于 Web 的应用程序。它遵循 Model-View-Controller#&#xff08;MVC&#xff09;设计模式&#xff0c;将业务逻辑、用户界面和数据分离&#xff0c;以促进代码的可维护性和可扩展性。主要包含几个概念…

第十篇:3D模型性能优化:从入门到实践

第十篇&#xff1a;3D模型性能优化&#xff1a;从入门到实践 引言 在3D开发中&#xff0c;性能优化是区分普通应用和卓越应用的关键。Three.js应用的流畅运行需要60FPS的渲染效率&#xff0c;而移动端设备更面临严格的资源限制。本文将深入解析性能优化核心技术&#xff0c;并通…

基于 Easy Rules 的电商订单智能决策系统:构建可扩展的业务规则引擎实践

Easy Rules 是一个轻量级且易于使用的规则引擎&#xff0c;适用于Java应用。下面是一个简单的示例&#xff0c;演示如何使用 Easy Rules 定义和执行规则。 添加依赖 首先&#xff0c;在你的Java项目中添加 Easy Rules 的 Maven 依赖&#xff08;如果你使用的是Maven构建工具&am…

如何使用gpt进行模型微调?

对 GPT 类大语言模型&#xff08;如 GPT-3、GPT-2、Hugging Face 的 GPT 系列、ChatGLM 等开源或闭源模型&#xff09;进行微调&#xff08;Fine-tuning&#xff09;&#xff0c;目的是让模型在特定任务或领域&#xff08;如法律、医疗、客服、代码生成等&#xff09;上表现更优…