创建标准库 和 HAL库工程
一、创建标准库工程
1、下载 STM32F4 标准固件库

| 名称 | 类型 | 作用说明 |
|---|---|---|
_htmresc |
文件夹 | 存放官方 logo、图片等网页资源,开发中可忽略 |
Libraries |
文件夹 | 核心库文件目录,包含 CMSIS 标准文件和外设驱动源码 |
Project |
文件夹 | 官方提供的外设例程、模板工程(支持 Keil、IAR 等工具) |
Utilities |
文件夹 | 开发板相关的辅助工具 / 驱动(如板级支持包、第三方组件) |
stm32f4xx_dsp_stdperiph_lib_um |
编译的 HTML 帮助文档(.chm) |
官方库函数手册,包含所有外设驱动、DSP 函数的 API 说明、用法示例 |
Package_license/Release_Notes |
文档 | 库的许可协议和版本更新说明 |
解压得到

💡 关键文件说明
Libraries文件夹这是开发中最核心的部分,包含两个关键子目录:CMSIS:ARM Cortex-M 内核的通用接口文件,包含启动文件、系统时钟配置、内核寄存器定义STM32F4xx_StdPeriph_Driver:所有外设(GPIO、UART、SPI、ADC 等)的驱动源码和头文件,以及 DSP 数字信号处理库
stm32f4xx_dsp_stdperiph_lib_um.chm这是开发中必备的 “工具书”,你可以在这里:- 按外设分类查找所有库函数的定义、参数、返回值
- 查看函数使用示例、寄存器配置说明
- 查阅 DSP 库(FFT、滤波、矩阵运算等)的使用方法

2、新建工程目录结构

3、从官方库复制文件(关键)

4、MDK创建工程

5、设置MDK
① 设置编译输出文件路径

② 设置编译器版本
| 工程类型 | 必须用的编译器 |
|---|---|
| STM32 标准库 StdPeriph | V5 (ARMCC) |
| HAL 库 / LL 库 / 新项目 | V6 (ARMClang) |

③ 设置宏和包含头文件
- 设置宏
USE_STDPERIPH_DRIVER:告诉编译器启用标准外设库驱动,而不是直接操作寄存器。- USE_HAL_DRIVER:告诉编译器启用HAL库驱动
STM32F40_41xxx:指定目标芯片型号,这是条件编译的开关。- 标准外设库的头文件(如
stm32f4xx.h)会根据这个宏,只编译对应芯片外设代码
- 标准外设库的头文件(如

- 包含头文件
-
编译时会在这些路径里查找对应的文件,未包含会直接报 “头文件找不到” 的错误。

-
④ 禁止参与编译
DMA2D:F407 没有。这是一个专门用于图形加速的 2D DMA 控制器,是 F429 及以上型号才有的外设。FMC:F407 有的是FSMC(静态存储控制器),不是 FMC。FMC 是 F429 等型号对 FSMC 的升级版本,两者寄存器定义不完全兼容。LTDC:F407 没有。这是 LCD-TFT 显示控制器,也是 F429 及以上型号才有的外设。
如何在 Keil 里禁用:
- 右键点击文件 →
Options for File - 取消勾选
Include in Target Build - 点击
OK,文件图标上会出现一个小叉,表示不参与编译

禁用与不禁用的区别
| 不禁用的风险 | 禁用的好处 |
|---|---|
| 工程文件杂乱,编译时间变长 | 工程更清爽,编译速度更快 |
| 误操作调用这些函数,会导致程序跑飞、HardFault | 从根源上杜绝误调用的可能 |
| 调试时容易被无关文件干扰 | 代码结构更清晰,维护更方便 |
⑤ 处理宏重定义警告
注释掉 stm32f4xx.h 里重复定义的 5 行
//#define DBGMCU_APB2_FZ_DBG_TIM1_STOP DBGMCU_APB1_FZ_DBG_TIM1_STOP
//#define DBGMCU_APB2_FZ_DBG_TIM8_STOP DBGMCU_APB1_FZ_DBG_TIM8_STOP
//#define DBGMCU_APB2_FZ_DBG_TIM9_STOP DBGMCU_APB1_FZ_DBG_TIM9_STOP
//#define DBGMCU_APB2_FZ_DBG_TIM10_STOP DBGMCU_APB1_FZ_DBG_TIM10_STOP
//#define DBGMCU_APB2_FZ_DBG_TIM11_STOP DBGMCU_APB1_FZ_DBG_TIM11_STOP
⑥ 查看 HSE (外部高速时钟) 定义
上电默认使用HSI(内部高速时钟)

二、创建HAL库工程
1、下载HAL库固件包
-
① STM32CubeMX 内直接下载(最方便)
- 安装并打开 STM32CubeMX(官网可下)。
- 菜单栏:Help → Manage embedded software packages

- ② 官网手动下载
- 网址:STM32Cube MCU和MPU包: 相关产品 - STMicroelectronics


- ③ 解压固件包

2、新建工程目录结构

3、从官方库复制文件(关键)
复制文件其实无论是标准库还是HAL库其实几乎都是一样
- 最主要的5个文件
- 启动文件.s (startup_stm32f4xx.s)
- 系统初始化.c (system_stm32f4xx.c )
- 内核寄存器.c (core_cm4.h)
- 外设寄存器.c (stm32f4xx.h)
- 外设库.c (STM32F4xx_StdPeriph_Driver整个文件夹)
4、MDK创建工程

5、设置MDK
以下2处和标准库有差异,其余都一样
① 设置预处理器符号,用“,”隔开


② 查看 HSE (外部高速时钟) 定义
在 stm32f407xx_hal_conf.h 里修改成实际硬件晶振值

解答这里为啥标准库和HAL库不同的疑惑
- 配置路径
-
库类型 晶振配置位置 原因 标准库 stm32f4xx.h单文件大一统,所有定义放一起 HAL 库 xxx_hal_conf.h专门给用户改的配置文件,内核文件不动
-
- 配置值
-
库 默认 HSE 原因 标准库 25MHz 老官方板用 25M HAL 库 8MHz 新官方板用 8M
-
三、工程代码执行顺序
硬件上电 → 真实执行顺序(5个主要文件)
-
① 第一个运行: startup_stm32f4xx.s(启动文件)
-
硬件强制、无法改变(绝对第一个执行)
- → 初始化栈指针
SP - → 初始化数据段、清零未初始化段
- → 定义中断向量表(包括复位向量)
-
→ 跳去执行 system_stm32f4xx.c 里的 SystemInit ()
-
Reset_Handler PROC /* 定义复位处理函数(CPU一上电,就跳这里执行!) */ EXPORT Reset_Handler [WEAK] /* 导出复位函数,让编译器知道这是入口 */ IMPORT SystemInit /* 告诉汇编器:SystemInit 函数在别的C文件里(system_stm32f4xx.c) */ IMPORT __main /* 告诉汇编器 __main 是C语言主函数入口 */ LDR R0, =SystemInit /* 把 SystemInit 函数的地址 加载到 R0 寄存器 */ BLX R0 /* 调用执行 SystemInit() 函数 */ LDR R0, =__main /* 把 main 函数地址加载到 R0 */ BX R0 /* 跳转到 main() 函数!进入C语言世界 */ ENDP /* 函数结束 */
-
- → 初始化栈指针
-
② 第二个运行:system_stm32f4xx.c 里的 SystemInit ()
- system_stm32f4xx.c 就干1件事:实现 SystemInit () 配置系统时钟
- 它是 C 语言第一个运行的函数,是整个芯片能跑起来的底层基石。
- 执行 SystemInit ()
-
开启 FPU 浮点单元(让 CPU 支持硬件浮点运算)
-
复位所有时钟寄存器(安全初始状态(仅 HSI 16MHz 运行))
-
初始化外部存储器(外部 SRAM/SDRAM(可选,极少用到))
-
配置系统时钟(SetSysClock 核心步骤)
- 配置 FLASH 等待周期(CPU 等 5 个时周期,才读 Flash 指令 / 数据)
- 配置总线分频(AHB / APB1 / APB2)
- 开启 HSE 外部晶振
- 配置 PLL 倍频(从低速 → 倍频到 168MHz)
- 切换系统时钟源为 PLL
- 更新 SystemCoreClock 全局时钟变量
-
-
配置中断向量表的存放位置(告诉 CPU:中断表在 Flash 中的地址)
-
注意了:HAL库 和 标准库 SystemInit () 函数实现 不一样
- 前面讲的是标准库的,而下面才是HAL库的
SystemInit只做两件事:开启 FPU、配置向量表- 时钟复位、配置全由 用户自己实现(
SystemClock_Config()来完成) -
导致 执行完 SystemInit,依旧跑在16MHz HSI(内部慢时钟)
- 前面讲的是标准库的,而下面才是HAL库的
-
总结:
-
库 SystemInit 做了什么? 进 main 时时钟 你需要手动配时钟吗? 标准库 完整配置 PLL 168MHz 168MHz 不需要,自动好了 HAL 库 仅复位,不配置 PLL 16MHz HSI 必须手动些函数 SystemClock_Config ()
-
- 执行 SystemInit ()
-
③ 第三个运行:main ()
-
SystemInit 执行完 → 跳去 main ()
-
然后才用到:
- 内核寄存器.c
- 外设寄存器.c
- hal 外设库.c
-
-
- ④ 官方 标准库 和 HAL库 SystemInit 函数对比
- 标准库
void SystemInit(void) { // ===================== 1. 开启硬件浮点单元 FPU ===================== // 如果芯片支持FPU,并且开启了硬件浮点 // 给CP10、CP11权限,让CPU可以执行浮点指令(不开启则浮点运算巨慢) #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); #endif // ===================== 2. 复位所有时钟 → 最干净、最安全的初始状态 ===================== // 打开内部16MHz时钟 HSI(上电默认时钟,最可靠) RCC->CR |= (uint32_t)0x00000001; // 复位时钟配置寄存器 CFGR(清空所有分频、时钟源选择) RCC->CFGR = 0x00000000; // 关闭 HSE外部晶振、PLL锁相环、时钟安全系统 RCC->CR &= (uint32_t)0xFEF6FFFF; // 复位PLL配置寄存器(清空倍频、分频) RCC->PLLCFGR = 0x24003010; // 关闭外部晶振旁路模式 RCC->CR &= (uint32_t)0xFFFBFFFF; // 关闭所有时钟中断,防止干扰 RCC->CIR = 0x00000000; // ===================== 3. 外部RAM初始化(几乎不用,忽略) ===================== #if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM) SystemInit_ExtMemCtl(); #endif // ===================== 4. 核心:配置系统时钟到168MHz ===================== // 里面完成: // 1. 打开HSE外部晶振 // 2. 配置PLL倍频到168MHz // 3. 配置FLASH等待周期(CPU等Flash) // 4. 配置AHB/APB1/APB2总线分频 // 5. 切换系统时钟为PLL // 6. 更新全局时钟变量 SystemCoreClock SetSysClock(); // ===================== 5. 配置中断向量表的存放位置 ===================== // 告诉CPU:中断函数列表放在哪里 #ifdef VECT_TAB_SRAM // 放在SRAM(极少用) SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; #else // 放在FLASH(正常程序都放这里) SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; #endif } - HAL库
// 系统初始化函数(芯片上电后自动第一个执行) void SystemInit(void) { // ==================== 1. 硬件浮点单元 FPU 配置 ==================== // 如果芯片硬件支持 FPU,并且工程开启了硬件浮点计算 // 给 CP10 / CP11 完全权限,让 CPU 可以执行浮点运算指令 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); #endif // ==================== 2. 外部存储器初始化(几乎不用) ==================== // 只有使用外部 SRAM 或 SDRAM 时才会执行 // 普通单片机项目 99.9% 用不到,直接忽略 #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) SystemInit_ExtMemCtl(); #endif // ==================== 3. 配置中断向量表的存放位置 ==================== // 如果用户自定义了中断向量表地址(如Bootloader跳转) // 告诉CPU:中断函数列表放在哪个内存地址(Flash 或 SRAM) #if defined(USER_VECT_TAB_ADDRESS) SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; #endif }
- 标准库
-
四、标准 \ HAL库 最小模板
-
1. 标准库最小模板
- 执行顺序:启动文件.s → SystemInit () → main () → 开时钟 → 初始化外设
-
#include "stm32f4xx.h" int main(void) { // 【标准库 唯一必须:先开时钟!】 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 然后配置 GPIO GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStruct); while(1) { // 业务代码 } }
-
- 执行顺序:启动文件.s → SystemInit () → main () → 开时钟 → 初始化外设
-
2. HAL 库最小模板
- 执行顺序:启动.s → SystemInit () → main () → HAL_Init () → 配置时钟 → 初始化外设
#include "stm32f4xx_hal.h" int main(void) { // 【HAL 库 必须第一个调用!】 HAL_Init(); // 【必须:配置系统时钟】 SystemClock_Config(); // 然后初始化外设(HAL 会自动开时钟) __HAL_RCC_GPIOA_CLK_ENABLE(); // 这句也可以在 MX_GPIO_Init 里 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; 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); while(1) { // 业务代码 } } // 时钟配置函数(必须) void SystemClock_Config(void) { // 内部实现:配置 PLL 到 168MHz } -
HAL_Init () 做的 4 件大事
-
1. 设置中断优先级分组
-
配置整个芯片的中断规则(NVIC 分组)
-
保证后续中断(时钟、外设、定时器)不乱优先级
-
是系统稳定运行的基础
-
-
2. 初始化 SysTick 系统滴答定时器
-
提供 1ms 系统时基
-
HAL_Delay()、超时判断、时间戳都依赖它
-
不初始化 → HAL 延时功能完全失效
-
-
3. 开启 Flash 缓存加速
-
指令缓存、数据缓存、预取指功能打开
-
让 CPU 在 ** 高主频(168MHz)** 下读取代码更快、不卡顿
-
-
4. 调用底层硬件初始化接口 HAL_MspInit()
-
这是一个弱定义空函数
-
需要用户自己实现
-
真正在这里面做:
-
复位所有外设(APB1/APB2)
-
开启底层时钟(PWR 等)
-
让系统进入干净、安全、默认状态
-
-
-
-
- 执行顺序:启动.s → SystemInit () → main () → HAL_Init () → 配置时钟 → 初始化外设
-
3. 两者最核心区别
-
步骤
标准库
HAL 库
上电
启动文件.s
启动文件.s
C 入口
SystemInit()
SystemInit()
main 第一句
直接开外设时钟
必须 HAL_Init ()
时钟
由 SystemInit 配置
(更改HSE,需用户实现)
必须手动调用 SystemClock_Config
(选用HSI还是HSE,用户一次性实现)
外设使用
先开时钟,再初始化
直接初始化(库自动处理时钟)
统一初始化
无
必须 HAL_Init ()
-
五、标准 \ HAL库 自定义系统时钟
- 标准库:
// 功能:标准库 —— 系统时钟初始化(HSE 25MHz → 系统时钟 168MHz) void SystemClock_Config(void) { // 1. 复位时钟 RCC_DeInit(); // 2. 使能 PWR 电源时钟(跑168MHz必须开) // 默认电压等级 2(默认) 最高支持:144MHz RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_VoltageScalingConfig(PWR_VoltageScaling_1); // 3. 开启 25MHz 外部晶振 RCC_HSEConfig(RCC_HSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //========================================================================= // 【重点】25MHz 晶振 PLL 配置 // 公式:SYSCLK = HSE / PLLM * PLLN / PLLP // 25MHz / 25 * 336 / 2 = 168MHz //========================================================================= RCC_PLLConfig(RCC_PLLSource_HSE, 25, 336, 2, 4); // 4. 开启 PLL 并等待锁定 RCC_PLLCmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); // 5. Flash 完整配置(预取 + 指令缓存 + 数据缓存 + 5个等待周期) FLASH_PrefetchBufferCmd(ENABLE); FLASH_InstructionCacheCmd(ENABLE); FLASH_DataCacheCmd(ENABLE); FLASH_SetLatency(FLASH_Latency_5); // 6. 总线分频配置 RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB = 168MHz RCC_PCLK1Config(RCC_HCLK_Div4); // APB1 = 42MHz RCC_PCLK2Config(RCC_HCLK_Div2); // APB2 = 84MHz // 7. 切换时钟到 PLL RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); while (RCC_GetSYSCLKSource() != 0x08); // 8. 更新全局时钟变量(必须!) SystemCoreClockUpdate(); }
- HAL库:
// 系统时钟配置函数(必须在 HAL_Init() 之后、main 函数里调用) void SystemClock_Config(void) { // 定义两个时钟配置结构体,清零初始值 RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 用于配置振荡器(HSE/HSI/PLL) RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 用于配置总线时钟(SYSCLK/AHB/APB) //==================== 1. 电源配置 ==================== // 使能电源时钟(必须开,否则无法配置电压等级) __HAL_RCC_PWR_CLK_ENABLE(); // 设置电源调压器为 1 档(最高性能,支持 180MHz) // STM32 主频越高,所需内核电压就越高,若默认低档电压,强行配 180MHz:芯片不稳定、死机、跑飞 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); //==================== 2. 配置 HSE + PLL ==================== // 选择要配置的振荡器类型(我要使用 HSE,给外部晶振通电、启动):HSE RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 打开外部高速晶振 HSE(你的 8M/25M 晶振) RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 打开 PLL(锁相环,用来倍频到 180MHz) RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 时钟来源:选择 HSE RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; //==================== PLL 计算公式 ==================== // SYSCLK = HSE / PLLM * PLLN / PLLP // 例:25MHz /25 *360 /2 = 180MHz // 如果你是 8MHz 晶振:PLLM=8, PLLN=360, PLLP=2 → 8/8*360/2=180MHz RCC_OscInitStruct.PLL.PLLM = 25; // HSE 分频系数 RCC_OscInitStruct.PLL.PLLN = 360; // 倍频系数 RCC_OscInitStruct.PLL.PLLP = 2; // 最终分频系数(输出系统时钟) RCC_OscInitStruct.PLL.PLLQ = 7; // USB/SDIO 时钟用(可选) // 把上面配置写入硬件寄存器 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); // 配置失败进入错误处理 } //==================== 3. 配置总线分频 ==================== // 选择要配置的时钟:系统时钟 + AHB + APB1 + APB2 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; // 系统时钟来源:PLL(180MHz) RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // AHB 总线分频:1 分频 → HCLK = 180MHz(CPU 主频) RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // APB1 总线分频:4 分频 → 45MHz(APB1 最高不能超过 42MHz,F4 可超频到 45) RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // APB2 总线分频:2 分频 → 90MHz(APB2 最高可到 90MHz) RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 把总线配置写入硬件,并设置 Flash 等待周期(5 个周期对应 180MHz) if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5WS) != HAL_OK) { Error_Handler(); // 配置失败进入错误处理 } // ========= 4. 更新全局时钟变量 (SystemCoreClockUpdate 标准库自带)======== SystemCoreClockUpdate(); //告诉所有库和外设:现在 CPU 真正跑的速度是 168MHz } - 更新全局时钟变量(库函数自带)
- SystemCoreClockUpdate():动态计算(读寄存器→ 判断 HSI/HSE/PLL→ 套公式→ 计算)
void SystemCoreClockUpdate(void) { // 先定义几个计算器变量 uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; /*!!!第一步:去硬件里看一眼 —— 现在CPU用的是谁的时钟?!*/ tmp = RCC->CFGR & RCC_CFGR_SWS; // 根据时钟来源,分 4 种情况计算速度 switch (tmp) { // ========================== // 情况1:用内部16M时钟 HSI // ========================== case 0x00: SystemCoreClock = 16000000; // 直接写死 16MHz break; // ========================== // 情况2:用外部晶振 HSE // ========================== case 0x04: SystemCoreClock = HSE_VALUE; // 直接用你配置的 8M/25M break; // ========================== // 情况3:用 PLL 倍频时钟(你现在168MHz就是这种!) // ========================== case 0x08: // 1. 看 PLL 用的是 HSI 还是 HSE pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; // 2. 读 PLL_M 分频值 pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; // 3. 如果是 HSE 做时钟源 if (pllsource != 0) { // 计算公式: // PLL_VCO = HSE / M * N pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); } else { // 用 HSI 内部时钟算 pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); } // 4. 读 PLL_P 分频 pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; // 5. 最终算出系统时钟! // SYSCLK = PLL_VCO / P SystemCoreClock = pllvco / pllp; break; // 其他情况... default: SystemCoreClock = HSI_VALUE; break; } // 最后再算一下 AHB 分频,得到最终 CPU 速度 tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; SystemCoreClock >>= tmp; }
- SystemCoreClockUpdate():动态计算(读寄存器→ 判断 HSI/HSE/PLL→ 套公式→ 计算)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)