news 2026/2/14 11:33:06

FDCAN与TT-FDCAN:原理与实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FDCAN与TT-FDCAN:原理与实战解析

目录

一、核心定义与核心差异(先理清 “是什么”)

二、原理详解(从基础到特化)

1. FDCAN 核心原理(事件触发的通用型 CAN FD)

(1)FDCAN 核心特性

(2)FDCAN 帧结构(核心规则)

2. TT-FDCAN 核心原理(时间触发的硬实时 CAN)

(1)TT-FDCAN 核心特性

三、典型应用场景与选型建议

1. 典型应用场景

2. 选型核心原则

四、程序案例详解(STM32H743,HAL 库)

前置准备

案例 1:FDCAN 普通通信(事件触发,汽车车身控制)

功能说明

1. STM32CubeMX 配置(Node A/Node B 通用)

2. 核心代码(Node A:发送端)

3. 核心代码(Node B:接收端)

4. 测试效果

案例 2:TT-FDCAN 时间触发通信(汽车线控制动)

功能说明

1. STM32CubeMX 配置(核心差异)

2. 核心代码(Master 节点:Node A)

3. 核心代码(Slave 节点:Node B)

4. 测试效果

五、避坑点(新手常犯)

总结

关键点回顾


全面理解 TT-FDCAN 与 FDCAN 的核心差异、工作原理,掌握两者的典型应用场景,并通过可落地的实战案例掌握实际使用方法 —— 核心是 “区分差异→原理解析→场景适配→代码落地”,这也是车载 / 工业 CAN 总线开发的核心知识点。我会以 STM32H7 系列(主流支持 TT-FDCAN/FDCAN 的 MCU)为例,从基础原理到实战案例层层拆解,所有代码均基于 STM32 HAL 库(新手易上手)。

一、核心定义与核心差异(先理清 “是什么”)

FDCAN 是基础,TT-FDCAN 是 FDCAN 的时间触发特化版本,核心差异在于 “通信触发方式” 和 “实时性保障”,用表格快速区分:

接口类型全称核心特征核心差异点实时性等级
FDCANFlexible Data-Rate CAN(灵活数据速率 CAN)事件触发式通信,兼容传统 CAN 2.0,数据段可高速传输(最高 8Mbps),帧长度扩展至 64 字节事件触发、无严格时间调度、通用型软实时(毫秒级)
TT-FDCANTime-Triggered FDCAN(时间触发型 FDCAN)基于 FDCAN 的时间触发机制,按预设静态调度表通信,无总线仲裁,硬实时 + 容错时间触发、静态调度、硬实时、容错硬实时(微秒级)

关键结论

  • TT-FDCAN 是 FDCAN 的 “超集”(兼容 FDCAN 所有功能),额外增加时间触发调度机制;
  • FDCAN 解决传统 CAN“速率低、数据短” 的问题,TT-FDCAN 解决 FDCAN“实时性不可预测、无容错” 的问题;
  • FDCAN 适用于普通场景,TT-FDCAN 适用于安全关键 / 硬实时场景(如汽车线控、自动驾驶)。

二、原理详解(从基础到特化)

1. FDCAN 核心原理(事件触发的通用型 CAN FD)

FDCAN 是传统 CAN 2.0 的升级版,核心解决 “速率低(最高 1Mbps)、数据帧短(仅 8 字节)” 的痛点,是车载 / 工业 CAN 总线的主流方案。

(1)FDCAN 核心特性
  • 双波特率机制
    • 仲裁段(Arbitration Phase):兼容 CAN 2.0,用低波特率(如 500kbps)传输帧 ID,保证总线仲裁的稳定性;
    • 数据段(Data Phase):用高波特率(如 2Mbps/8Mbps)传输数据,提升整体传输效率;
  • 帧长度扩展:数据帧长度从 8 字节扩展至 64 字节,无需分包传输大数据;
  • 事件触发通信:节点有数据要发送时,按帧 ID 的优先级参与总线仲裁(ID 越小优先级越高),仲裁成功则发送,失败则等待重传;
  • 兼容 CAN 2.0:可配置为 CAN 2.0 模式,向下兼容传统 CAN 节点。
(2)FDCAN 帧结构(核心规则)

plaintext

仲裁段(11/29位ID + 控制位)→ 数据段(0-64字节)→ CRC校验段 → 确认段 → 结束段
  • 仲裁段:决定帧的优先级,标准 ID(11 位)用于普通场景,扩展 ID(29 位)用于复杂场景;
  • 数据段:核心传输内容,64 字节满足大多数车载 / 工业数据传输需求;
  • CRC 校验:针对长数据帧优化,提升容错能力。

2. TT-FDCAN 核心原理(时间触发的硬实时 CAN)

TT-FDCAN 是基于 FDCAN 的时间触发通信协议(继承 TT-CAN 的核心思想),专为 “安全关键、硬实时” 场景设计(如汽车线控制动 / 转向、自动驾驶域控制器通信)。

(1)TT-FDCAN 核心特性
  • 静态时间调度表:所有节点预先约定 “通信周期(Matrix Cycle)” 和 “时间窗(Time Slot)”,每个节点在指定时间窗内发送固定 ID 的帧,无总线仲裁(时间窗不重叠);
  • 全局时钟同步:由一个 “主节点(Master)” 发送同步帧(SYNC 帧),所有从节点(Slave)校准本地时钟,确保时间调度精准(时钟偏移≤1μs);
  • 硬实时保障:帧发送 / 接收的延迟可预测,抖动≤1μs,满足 ISO 26262 功能安全等级(ASIL-D);
  • 容错机制:时间窗监控,若节点未在指定时间发送帧,系统可立即检测并触发容错策略(如切换备用节点)。

三、典型应用场景与选型建议

1. 典型应用场景

接口类型核心适用场景选型优先级工业 / 车载案例
FDCAN非安全关键、事件触发、数据量中等的场景普通场景优先汽车车身控制(灯光 / 门窗 / 空调)、工业传感器通信、工程机械液压控制
TT-FDCAN安全关键、硬实时、容错要求高的场景高实时场景优先汽车线控(制动 / 转向 / 油门)、自动驾驶域控制器通信、工业机器人实时控制、航空航天关键控制

2. 选型核心原则

  • 优先选 FDCAN:若场景无严格实时性要求(延迟允许毫秒级)、非安全关键;
  • 必须选 TT-FDCAN:若场景要求硬实时(延迟 / 抖动微秒级)、安全关键(如 ISO 26262 ASIL-C/D);
  • 成本考量:TT-FDCAN 需额外设计静态调度表和时钟同步逻辑,开发成本更高,仅在必要时使用。

四、程序案例详解(STM32H743,HAL 库)

以 STM32H743(主流车载 MCU,支持 FDCAN/TT-FDCAN)为例,分别实现 FDCAN 普通通信和 TT-FDCAN 时间触发通信。

前置准备

  • 开发环境:STM32CubeMX + Keil5/VS Code;
  • 硬件:STM32H743 开发板 + CAN FD 收发器(如 TJA1057) + 双节点通信线(CAN_H/CAN_L/GND);
  • 调试工具:CANoe/CANalyzer(可选,用于监控 CAN 总线)。

案例 1:FDCAN 普通通信(事件触发,汽车车身控制)

功能说明

两个 STM32 节点(Node A/Node B)通过 FDCAN 通信:Node A 发送车身状态(如灯光状态:0 = 关,1 = 开),Node B 接收并回显该状态,模拟汽车车身控制场景。

1. STM32CubeMX 配置(Node A/Node B 通用)
  • 引脚配置:FDCAN1_TX→PB9,FDCAN1_RX→PB8(接 TJA1057 的 TXD/RXD);
  • 时钟配置:FDCAN 时钟源为 PCLK1(42MHz);
  • FDCAN 配置:
    • 模式:Normal Mode(正常模式);
    • 波特率:仲裁段 500kbps(分频系数 84,同步段 1,传播段 6,相位段 1 6,相位段 2 7),数据段 2Mbps(分频系数 21,同步段 1,传播段 6,相位段 1 6,相位段 2 7);
    • 帧格式:CAN FD(启用 FD Mode),标准 ID(11 位),数据长度 8 字节;
    • 过滤器:Node A 禁用过滤器(仅发送),Node B 启用过滤器(过滤 ID 0x123)。
2. 核心代码(Node A:发送端)
/* 头文件包含 */ #include "stm32h7xx_hal.h" #include <string.h> /* 全局句柄 */ FDCAN_HandleTypeDef hfdcan1; /* 定义FDCAN发送帧结构体 */ FDCAN_TxHeaderTypeDef TxHeader; uint8_t TxData[8] = {0}; // 发送数据:TxData[0] = 灯光状态(0/1) /* === 1. FDCAN初始化(CubeMX自动生成,无需修改) === */ void MX_FDCAN1_Init(void) { hfdcan1.Instance = FDCAN1; hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1; hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD; // CAN FD格式 hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; // 正常模式 hfdcan1.Init.AutoRetransmission = ENABLE; // 自动重传 hfdcan1.Init.TransmitPause = DISABLE; hfdcan1.Init.ProtocolException = DISABLE; // 仲裁段波特率配置(500kbps) hfdcan1.Init.NominalPrescaler = 84; hfdcan1.Init.NominalSyncJumpWidth = 1; hfdcan1.Init.NominalTimeSeg1 = 12; hfdcan1.Init.NominalTimeSeg2 = 7; // 数据段波特率配置(2Mbps) hfdcan1.Init.DataPrescaler = 21; hfdcan1.Init.DataSyncJumpWidth = 1; hfdcan1.Init.DataTimeSeg1 = 12; hfdcan1.Init.DataTimeSeg2 = 7; hfdcan1.Init.StdFiltersNbr = 0; // 发送端禁用过滤器 hfdcan1.Init.ExtFiltersNbr = 0; hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) { Error_Handler(); } } /* === 2. FDCAN发送函数 === */ void FDCAN_SendData(uint32_t std_id, uint8_t *data, uint8_t len) { // 配置发送帧头 TxHeader.Identifier = std_id; // 标准ID TxHeader.IdType = FDCAN_STANDARD_ID;// 标准ID模式 TxHeader.TxFrameType = FDCAN_DATA_FRAME; // 数据帧 TxHeader.DataLength = FDCAN_DLC_BYTES_8; // 8字节数据长度 TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; TxHeader.BitRateSwitch = ENABLE; // 启用位速率切换(仲裁段/数据段不同波特率) TxHeader.FDFormat = ENABLE; // 启用CAN FD格式 TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; TxHeader.MessageMarker = 0; // 发送数据 if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, data) != HAL_OK) { Error_Handler(); } } /* === 3. 主函数测试(Node A) === */ int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_FDCAN1_Init(); // 启动FDCAN HAL_FDCAN_Start(&hfdcan1); uint8_t light_state = 0; // 灯光状态:0=关,1=开 while (1) { // 填充发送数据:TxData[0] = 灯光状态,其余为0 TxData[0] = light_state; memset(TxData+1, 0, 7); // 发送数据(ID 0x123) FDCAN_SendData(0x123, TxData, 8); HAL_Delay(1000); // 切换灯光状态 light_state = !light_state; } } /* 错误处理函数 */ void Error_Handler(void) { __disable_irq(); while (1) { } }
3. 核心代码(Node B:接收端)
/* 全局句柄 */ FDCAN_HandleTypeDef hfdcan1; /* 定义FDCAN接收帧结构体 */ FDCAN_RxHeaderTypeDef RxHeader; uint8_t RxData[8] = {0}; /* === 1. FDCAN初始化(增加过滤器配置) === */ void MX_FDCAN1_Init(void) { // 基础配置同Node A,仅增加过滤器配置 hfdcan1.Init.StdFiltersNbr = 1; // 启用1个标准ID过滤器 if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) { Error_Handler(); } // 配置过滤器:过滤ID 0x123 FDCAN_FilterTypeDef sFilterConfig; sFilterConfig.IdType = FDCAN_STANDARD_ID; sFilterConfig.FilterIndex = 0; sFilterConfig.FilterType = FDCAN_FILTER_MASK; sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; sFilterConfig.FilterID1 = 0x123; // 过滤ID sFilterConfig.FilterID2 = 0x7FF; // 掩码(匹配所有11位ID) if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK) { Error_Handler(); } // 启用FIFO0非空中断 HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); } /* === 2. FDCAN接收中断回调函数 === */ void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) { if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET) { // 读取接收数据 if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) { // 打印灯光状态(实际项目中可控制硬件) if (RxData[0] == 0) { printf("灯光状态:关\r\n"); } else { printf("灯光状态:开\r\n"); } } // 清除中断标志 HAL_FDCAN_ClearInterruptFlag(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE); } } /* === 3. 主函数测试(Node B) === */ int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); // 初始化串口(用于打印) MX_FDCAN1_Init(); // 启动FDCAN HAL_FDCAN_Start(&hfdcan1); while (1) { // 主循环无需操作,接收靠中断 HAL_Delay(100); } }
4. 测试效果
  • 硬件连接:Node A 和 Node B 的 FDCAN_TX/RX 通过 TJA1057 连接 CAN_H/CAN_L,共地;
  • 运行 Node A:每秒发送灯光状态(0/1 交替);
  • 运行 Node B:串口助手打印 “灯光状态:关 / 开”,与 Node A 发送的状态一致。

案例 2:TT-FDCAN 时间触发通信(汽车线控制动)

功能说明

两个节点(Master=Node A,Slave=Node B)通过 TT-FDCAN 通信:

  • Master:每 10ms 发送 SYNC 帧(ID 0x001)同步时钟,随后在 Time Slot 2(1-2ms)发送制动指令(ID 0x100);
  • Slave:同步时钟后,在 Time Slot 3(2-3ms)发送制动反馈(ID 0x200),模拟汽车线控制动场景。
1. STM32CubeMX 配置(核心差异)
  • 启用 TT-FDCAN 模式:在 FDCAN 配置中勾选 “Time Triggered Mode”;
  • 同步配置:SYNC 帧周期 10ms,主节点发送 SYNC 帧(ID 0x001);
  • 调度表配置:
    • Time Slot 1(0-1ms):SYNC 帧(ID 0x001);
    • Time Slot 2(1-2ms):制动指令(ID 0x100);
    • Time Slot 3(2-3ms):制动反馈(ID 0x200)。
2. 核心代码(Master 节点:Node A)
/* 全局变量 */ FDCAN_HandleTypeDef hfdcan1; FDCAN_TxHeaderTypeDef TxHeader; uint8_t TxData[8] = {0}; uint32_t sync_counter = 0; // 同步帧计数器 /* === 1. TT-FDCAN初始化(增加时间触发配置) === */ void MX_FDCAN1_Init(void) { // 基础FDCAN配置同案例1 hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; hfdcan1.Init.TimeTriggeredMode = ENABLE; // 启用时间触发模式 if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) { Error_Handler(); } // 配置SYNC帧(主节点) FDCAN_TtConfigTypeDef sTtConfig; sTtConfig.SyncInterval = 10; // SYNC帧周期10ms sTtConfig.SyncOffset = 0; // 同步偏移0ms sTtConfig.SyncId = 0x001; // SYNC帧ID sTtConfig.MasterMode = ENABLE; // 主节点模式 if (HAL_FDCAN_ConfigTtMode(&hfdcan1, &sTtConfig) != HAL_OK) { Error_Handler(); } } /* === 2. 时间调度函数 === */ void TT_FDCAN_Schedule(void) { uint32_t current_time = HAL_GetTick(); // 获取当前时间(ms) uint32_t cycle_time = current_time % 10; // 通信周期10ms // Time Slot 1(0-1ms):发送SYNC帧 if (cycle_time >= 0 && cycle_time < 1) { TxHeader.Identifier = 0x001; TxData[0] = sync_counter++; // 同步计数器 HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData); } // Time Slot 2(1-2ms):发送制动指令(0x100=制动,0x00=释放) else if (cycle_time >= 1 && cycle_time < 2) { TxHeader.Identifier = 0x100; TxData[0] = 0x100; // 制动指令:轻踩制动 HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData); } } /* === 3. 主函数 === */ int main(void) { HAL_Init(); SystemClock_Config(); MX_FDCAN1_Init(); // 启动TT-FDCAN HAL_FDCAN_Start(&hfdcan1); HAL_FDCAN_EnableTtMode(&hfdcan1); // 启用时间触发模式 while (1) { TT_FDCAN_Schedule(); // 执行时间调度 HAL_Delay(1); // 1ms精度调度 } }
3. 核心代码(Slave 节点:Node B)
/* 全局变量 */ FDCAN_HandleTypeDef hfdcan1; FDCAN_RxHeaderTypeDef RxHeader; uint8_t RxData[8] = {0}, TxData[8] = {0}; uint32_t sync_time = 0; // 同步时间戳 /* === 1. TT-FDCAN初始化(从节点) === */ void MX_FDCAN1_Init(void) { // 基础配置同主节点,仅设置为从节点 hfdcan1.Init.TimeTriggeredMode = ENABLE; if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) { Error_Handler(); } FDCAN_TtConfigTypeDef sTtConfig; sTtConfig.SyncInterval = 10; sTtConfig.SyncOffset = 0; sTtConfig.SyncId = 0x001; sTtConfig.MasterMode = DISABLE; // 从节点模式 if (HAL_FDCAN_ConfigTtMode(&hfdcan1, &sTtConfig) != HAL_OK) { Error_Handler(); } // 配置过滤器:过滤SYNC帧(0x001)和制动指令(0x100) FDCAN_FilterTypeDef sFilterConfig; sFilterConfig.IdType = FDCAN_STANDARD_ID; sFilterConfig.FilterIndex = 0; sFilterConfig.FilterType = FDCAN_FILTER_MASK; sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; sFilterConfig.FilterID1 = 0x001; sFilterConfig.FilterID2 = 0x7FF; HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig); sFilterConfig.FilterIndex = 1; sFilterConfig.FilterID1 = 0x100; HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig); // 启用SYNC帧中断 HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_SYNC, 0); } /* === 2. SYNC帧中断回调函数(同步时钟) === */ void HAL_FDCAN_SyncCallback(FDCAN_HandleTypeDef *hfdcan) { sync_time = HAL_GetTick(); // 同步本地时间戳 } /* === 3. 时间调度函数 === */ void TT_FDCAN_Schedule(void) { uint32_t current_time = HAL_GetTick() - sync_time; // 相对同步时间 // Time Slot 3(2-3ms):发送制动反馈 if (current_time >= 2 && current_time < 3) { FDCAN_TxHeaderTypeDef TxHeader; TxHeader.Identifier = 0x200; TxHeader.IdType = FDCAN_STANDARD_ID; TxHeader.TxFrameType = FDCAN_DATA_FRAME; TxHeader.DataLength = FDCAN_DLC_BYTES_8; TxHeader.BitRateSwitch = ENABLE; TxHeader.FDFormat = ENABLE; TxData[0] = 0x01; // 制动反馈:已执行 HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData); } } /* === 4. 主函数 === */ int main(void) { HAL_Init(); SystemClock_Config(); MX_FDCAN1_Init(); HAL_FDCAN_Start(&hfdcan1); HAL_FDCAN_EnableTtMode(&hfdcan1); while (1) { TT_FDCAN_Schedule(); HAL_Delay(1); } }
4. 测试效果
  • 用 CANoe 监控总线:每 10ms 出现 SYNC 帧(0x001),随后 1ms 出现制动指令(0x100),2ms 出现制动反馈(0x200),时间窗无重叠,无总线冲突;
  • 实时性测试:帧发送延迟抖动≤1μs,满足线控制动的硬实时要求。

五、避坑点(新手常犯)

  1. FDCAN 波特率配置:仲裁段和数据段的分频系数需与时钟源匹配,否则会出现 “仲裁段通信正常,数据段乱码”;
  2. TT-FDCAN 时钟同步:主节点 SYNC 帧周期需精准,从节点本地时钟偏移过大会导致调度错乱(建议用硬件定时器校准);
  3. 时间窗设计:TT-FDCAN 的时间窗需预留≥100μs 的容错时间,避免因硬件延迟导致帧发送超时;
  4. 自动重传禁用:TT-FDCAN 需禁用自动重传(重传会破坏时间调度),改为 “一次发送 + 容错检测”;
  5. 功能安全配置:TT-FDCAN 用于安全关键场景时,需启用错误监控(如 CRC 校验、时间窗超时检测)。

总结

关键点回顾

  1. 核心差异:FDCAN 是事件触发的通用型 CAN FD 控制器,TT-FDCAN 是 FDCAN 的时间触发特化版,主打硬实时和容错;
  2. 选型原则:普通场景选 FDCAN,安全关键 / 硬实时场景(如汽车线控、自动驾驶)选 TT-FDCAN;
  3. 编程核心
    • FDCAN:重点配置双波特率、帧格式和过滤器,实现事件触发的收发;
    • TT-FDCAN:额外配置全局时钟同步和静态时间调度表,保证时间触发的精准性;
  4. 关键保障:TT-FDCAN 的硬实时性依赖 “精准的时间调度表” 和 “全局时钟同步”,FDCAN 的可靠性依赖自动重传机制。

这些案例覆盖了车载 / 工业 CAN 总线的核心应用场景,你可以根据实际需求调整(如 TT-FDCAN 的调度表周期、FDCAN 的波特率)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/11 15:36:31

新手友好!ChatGLM3-6B快速上手与实战演练

新手友好&#xff01;ChatGLM3-6B快速上手与实战演练 你是不是也经历过这些时刻&#xff1a; 想本地跑一个大模型&#xff0c;结果卡在环境配置里一整天&#xff1b; 好不容易装好了&#xff0c;点开网页却转圈十分钟没反应&#xff1b; 刚聊两句&#xff0c;模型突然“失忆”…

作者头像 李华
网站建设 2026/2/10 1:02:07

从零开始:用Gradio快速搭建通义千问2.5-7B-Instruct交互界面

从零开始&#xff1a;用Gradio快速搭建通义千问2.5-7B-Instruct交互界面 你是否试过下载一个大模型&#xff0c;却卡在“怎么让它开口说话”这一步&#xff1f;明明模型文件已就位&#xff0c;vLLM服务也跑起来了&#xff0c;可面对终端黑屏和API文档&#xff0c;总感觉缺了点…

作者头像 李华
网站建设 2026/2/11 15:02:51

Java毕设项目推荐-基于springboot的毕业生就业系统本科毕业生就业信息管理平台【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/2/11 14:49:05

对比两款制冷剂的效果

对比两款制冷剂的效果 01 制冷剂的效果 这是我手边的两款制冷剂。  下面使用这个热电偶温度计测试一下他们制冷的效果。  首先测量一下小罐制冷剂的制冷效果。 可以看到热电偶的温度降低到零下56摄氏度。  重新再测试一下&#xff0c; 这一次接近 零下60摄氏度了。  接下来…

作者头像 李华
网站建设 2026/2/11 17:57:50

Flowise商业价值:降低AI应用开发成本70%以上

Flowise商业价值&#xff1a;降低AI应用开发成本70%以上 1. 为什么企业正在悄悄替换LangChain原生开发&#xff1f; 你有没有遇到过这样的场景&#xff1a; 技术团队花了三周时间&#xff0c;用LangChain从零搭建一个内部知识库问答系统——写完Prompt模板、配置向量数据库、…

作者头像 李华
网站建设 2026/2/13 17:13:26

STM32CubeMX安装包下载与环境搭建完整指南

以下是对您提供的博文内容进行 深度润色与结构化重构后的专业级技术文章 。全文已彻底去除AI痕迹&#xff0c;采用嵌入式工程师真实写作口吻&#xff0c;强化逻辑连贯性、教学引导性与工程实用性&#xff1b;摒弃模板化标题&#xff0c;以自然段落推进知识流&#xff1b;关键…

作者头像 李华