从零构建STM32 HAL库工程:Keil环境下的高效开发指南

[STM32] Keil 创建 HAL 库的工程模板 Keil 创建 HAL 库的工程模板跟着的第7章步骤进行Keil工程的创建。 阅读详情

1. 为什么你需要一个“干净”的HAL库工程

如果你刚开始接触STM32,或者刚从标准库(Standard Peripheral Library)转向HAL库,你可能会被STM32CubeMX生成的庞大工程吓到。它确实方便,一键生成,但里面文件繁多,结构复杂,对于新手来说,就像走进了一个装满精密仪器的房间,你知道它能干活,但不知道从哪下手,也不敢乱动,生怕碰坏了什么。

我自己刚开始用HAL库时,也依赖CubeMX。但很快我就发现,当我想深入理解一个外设的初始化流程,或者想优化代码结构时,面对那个自动生成的工程,总有种“隔靴搔痒”的感觉。文件之间的依赖关系不清晰,很多配置散落在各个角落。更重要的是,如果你想在不同的项目间复用自己精心编写的驱动模块,从CubeMX工程里剥离出来非常麻烦。

所以,我决定回归“原始”,从零开始,手动搭建一个最精简、最清晰的HAL库工程。这个过程就像自己组装一台电脑,从选择每一个零件(文件)开始,到最终点亮(编译通过)。这么做的好处太多了:首先,你对工程的每一个文件、每一条编译选项都了如指掌,出了问题能快速定位;其次,工程结构完全由你掌控,可以设计出最适合自己或团队开发的目录规范;最后,这个工程模板一旦建立,就是属于你自己的“瑞士军刀”,后续任何新项目都可以基于它快速开始,效率倍增。

这个指南,就是带你一起完成这次“组装”。我们不依赖任何自动化工具,就用最“笨”但最有效的方法,在Keil MDK这个经典的环境里,构建一个专属于你的、高效且易于维护的STM32 HAL库开发地基。不用担心复杂,我会一步步拆解,把每个环节都讲透。

2. 战前准备:理清思路与备齐“弹药”

动手之前,我们得先想清楚这个工程最终要长什么样,以及需要准备哪些材料。盲目开始只会导致中途不断返工。

2.1 规划你的工程目录结构

一个清晰、合理的目录结构是高效开发的基石。它能让你的代码模块化,便于管理和团队协作。我经过多个项目的迭代,总结出了一个非常实用的结构,你可以直接参考:

My_STM32_Project/
├── Core/
│   ├── Inc/           # 核心头文件:启动文件、系统文件、中断文件等
│   └── Src/           # 核心源文件
├── Drivers/
│   ├── HAL_Driver/    # 存放从ST官方包拷贝的HAL库源文件(.c/.h)
│   └── BSP/          # 板级支持包,你的LED、按键、屏幕等硬件驱动
├── Middlewares/       # 中间件,如FatFS、FreeRTOS、USB库等(后续扩展用)
├── User/
│   ├── Inc/           # 用户应用头文件
│   └── Src/           # 用户应用源文件,main.c就在这里
├── Project/
│   └── MDK-ARM/       # Keil工程文件(.uvprojx)及其输出文件(.axf, .hex)
├── Docs/              # 项目文档
└── Utilities/         # 工具脚本,如批处理清理脚本

这个结构的关键在于分离。Core和Drivers/HAL_Driver里的东西,一旦确定基本不会动,它们是ST官方提供的“地基”。Drivers/BSP和User里的才是你发挥创意的地方。Project目录只放工程相关文件,编译生成的中间文件也在这里,这样你用一个简单的Clean.bat脚本就能一键清理,保持仓库干净。

2.2 下载必备的软件与资料包

工欲善其事,必先利其器。我们需要三样东西:

  1. Keil MDK-ARM开发环境:这个不用说,你得先安装好。建议使用V5版本,兼容性和稳定性都经过时间检验。
  2. STM32F1的Device Family Pack (DFP):这是Keil用来认识你芯片的“户口本”。没有它,Keil连STM32F103是谁都不知道。
  3. STM32CubeF1固件包:这是HAL库的“源代码仓库”,我们需要的所有HAL驱动文件、启动文件、系统文件都从这里取。

获取DFP芯片支持包: 最简单的方法是在Keil软件内直接安装。打开Keil,点击菜单栏的 Pack Installer 图标(那个小盒子)。在打开的窗口中,左侧找到 All Devices -> STMicroelectronics -> STM32F1 Series -> STM32F103 -> STM32F103ZE。选中后,右侧 Packs 选项卡里应该能看到 Keil::STM32F1xx_DFP,点击旁边的 Install 按钮,等待下载安装完成即可。这种方式省去了手动查找的麻烦。

获取STM32CubeF1固件包: 我们需要访问ST的官网。找到 Tools & Software -> Embedded Software -> STM32Cube MCU & MPU Packages 页面。在里面找到 STM32CubeF1 这个包,点击进入其详情页。你会看到一个 Get Latest 或类似版本的下载按钮,通常是一个ZIP压缩包,大小在100MB左右。下载它,这就是我们全部的“原料”。

3. 动手搭建:创建工程与组织文件

现在,让我们在电脑上实际创建这个工程框架,并把必要的文件“搬运”到位。

3.1 创建工程根目录与子文件夹

首先,在你喜欢的位置(比如D:\Projects)创建一个新的文件夹,命名为你的项目名,例如 STM32_HAL_Template。然后,按照我们之前规划的结构,在里面创建好所有子文件夹。你可以直接在资源管理器里手动新建,但我更推荐写一个简单的批处理脚本(create_dirs.bat)来一键生成,方便以后复用。

@echo off
mkdir Core\Inc
mkdir Core\Src
mkdir Drivers\HAL_Driver
mkdir Drivers\BSP
mkdir User\Inc
mkdir User\Src
mkdir Project\MDK-ARM
mkdir Docs
mkdir Utilities
echo 目录结构创建完成!
pause

双击运行这个脚本,骨架就立起来了。

3.2 从固件包中抽取核心文件

接下来是最关键的一步:从下载好的 STM32Cube_FW_F1_Vx.x.x 压缩包中,找出我们工程必需的文件。解压固件包,你会看到一个结构清晰的目录。

第一步:拷贝启动文件。 这是芯片上电后运行的第一段代码,用汇编写的。路径通常在:Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\arm。对于STM32F103ZE(大容量),我们需要 startup_stm32f103xe.s 这个文件。把它拷贝到我们工程的 Core\Src 目录下。注意,.s是汇编文件。

第二步:拷贝系统与设备相关文件。

  1. 头文件:从 Drivers\CMSIS\Device\ST\STM32F1xx\Include 拷贝以下文件到 Core\Inc:
    • stm32f1xx.h:所有F1系列芯片的通用头文件,包含外设寄存器定义。
    • stm32f103xe.h:针对F103xE系列的具体定义。
    • system_stm32f1xx.h:系统时钟配置的头文件。
  2. 源文件:从 Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates 拷贝 system_stm32f1xx.c 到 Core\Src。这个文件里包含了 SystemInit() 函数,负责初始化系统时钟。

第三步:拷贝CMSIS核心文件。 CMSIS是ARM制定的 Cortex-M 处理器通用接口标准。我们需要其核心头文件。从 Drivers\CMSIS\Core\Include 拷贝 core_cm3.h(因为F103是Cortex-M3内核)到 Core\Inc。

第四步:拷贝中断与HAL配置文件。 这些是HAL库运行的“脚手架”。

  1. 从固件包示例模板里找,例如 Projects\STM3210E_EVAL\Templates。
  2. 将 Inc 目录下的 stm32f1xx_it.h(中断头文件)和 stm32f1xx_hal_conf.h(HAL库裁剪配置文件)拷贝到 Core\Inc。
  3. 将 Src 目录下的 stm32f1xx_it.c(中断源文件)拷贝到 Core\Src。

第五步:拷贝HAL库驱动文件。 这是HAL库的主体。将整个 Drivers\STM32F1xx_HAL_Driver 文件夹(里面包含 Inc 和 Src)拷贝到我们工程的 Drivers\HAL_Driver 目录下。这样,我们就拥有了所有外设的HAL驱动源码。

至此,文件搬运工作完成。你的 Core 和 Drivers\HAL_Driver 目录应该已经充实起来。其他目录(如User, BSP)暂时空着,等着我们填充自己的代码。

4. 在Keil中构建工程骨架

文件准备好了,现在打开Keil,把它们组织成一个真正的项目。

4.1 新建工程与选择芯片

打开Keil MDK,点击 Project -> New uVision Project...。在弹出的对话框中,导航到你工程的 Project\MDK-ARM 目录,为工程取个名,比如 MyHALTemplate,点击保存。

紧接着会弹出设备选择窗口。因为我们已经安装了DFP包,所以可以在搜索框输入 STM32F103ZE,然后在列表中选择 STMicroelectronics 下的 STM32F103ZE。右侧会显示该芯片的详细描述,确认无误后点击 OK。

随后会弹出一个“Manage Run-Time Environment”窗口,这是Keil RTE环境,用于添加软件组件。对于我们的纯手动工程,直接点击 Cancel 取消即可。 我们要完全自己管理文件。

4.2 创建工程分组与添加文件

一个清晰的工程分组(Group)能让项目管理更直观。在Keil左侧的 Project 窗口中,右键点击 Target 1,选择 Manage Project Items...。

在弹出的对话框中,我们可以创建分组:

  1. 在 Project Targets 页签,可以将 Target 1 改名为更有意义的名字,如 MyHALTemplate。

  2. 切换到 Groups/ Files 页签。这里默认有一个 Source Group 1。我们删除它,然后点击上方的 New (Insert) 按钮,创建与我们目录对应的分组:

    • Core
    • HAL_Driver
    • BSP
    • User (Middlewares等可以后续需要时再加)
  3. 向分组添加文件:

    • 选中 Core 分组,点击下方的 Add Files,导航到 Core\Src,选择 startup_stm32f103xe.s, system_stm32f1xx.c, stm32f1xx_it.c。注意:.h 头文件不要在这里添加!
    • 选中 HAL_Driver 分组,点击 Add Files,导航到 Drivers\HAL_Driver\Src。这里文件很多,我们不需要全部添加。对于初始模板,可以先添加最常用和必需的,例如:
      • stm32f1xx_hal.c
      • stm32f1xx_hal_cortex.c
      • stm32f1xx_hal_rcc.c
      • stm32f1xx_hal_gpio.c 其他外设驱动(如 hal_uart.c, hal_spi.c)等用到时再加,避免工程臃肿。特别注意:不要添加文件名中带 _template.c 的文件,这些是模板,不是最终源码。
    • 选中 User 分组,添加 User\Src 目录下的文件(目前还没有,我们可以先创建一个空的 main.c 加进去)。

一个关键设置: 添加完 .s 汇编文件后,需要右键点击它,选择 Options for File...,在 Properties 选项卡中,将 File Type 设置为 ARM Assembler,这样Keil才知道用汇编器来编译它。同样,.c 文件应保持为 C Source file。

4.3 配置关键的工程选项

工程选项是灵魂所在,配置错了就会编译失败。右键点击工程目标(MyHALTemplate),选择 Options for Target...。

  1. Target 选项卡:

    • 确认芯片型号正确。
    • Xtal (MHz) 可以填你板载外部晶振的频率,比如8.0。这个主要用于软件模拟。
    • Use MicroLIB:强烈建议勾选。这是一个针对嵌入式系统优化的精简C库,可以显著减少代码体积。
  2. Output 选项卡:

    • 点击 Select Folder for Objects...,将输出路径设置为 .\Project\MDK-ARM\Objects。这样所有的 .o 中间文件都会集中在这里。
    • 勾选 Create HEX File,方便后续烧录。
  3. Listing 选项卡:

    • 点击 Select Folder for Listings...,将列表文件输出路径设置为 .\Project\MDK-ARM\Listings。
  4. C/C++ (AC6) 选项卡:(这是最重要的部分)

    • Define:在这里输入全局宏定义。必须添加 USE_HAL_DRIVER 和 STM32F103xE。
      • USE_HAL_DRIVER:告诉编译器我们要使用HAL库。
      • STM32F103xE:指定我们使用的是大容量型号。这个宏必须和启动文件 startup_stm32f103xe.s 中的 xe 后缀匹配。
    • Include Paths:点击后面的 ... 按钮,添加头文件搜索路径。必须添加以下路径:
      • ../Core/Inc
      • ../Drivers/HAL_Driver/Inc
      • ../User/Inc
      • ../Drivers/BSP (为后续准备) 添加时使用相对路径(..表示上一级目录),这样工程移动到别的电脑上也能正常编译。
    • Language / Code Generation:ARM Compiler 选择 Use default compiler version 5。AC6编译器更严格,一些HAL库代码可能需要调整,用AC5兼容性更好。
  5. Debug 选项卡:

    • 根据你的调试器选择,比如 ST-Link Debugger,然后点击旁边的 Settings,检查 Debug 和 Flash Download 配置是否正确,确保能正常下载和调试。

5. 编写用户代码与解决编译问题

骨架和配置都好了,现在让我们注入“灵魂”——编写用户代码,并解决可能出现的编译错误。

5.1 编写最简单的main.c进行验证

在 User\Src 目录下创建 main.c 文件,并添加到Keil的 User 分组中。我们先写一个最简单的程序,点亮一个LED(假设连接在PB1引脚)。

/* main.c */
#include "main.h" // 我们将创建这个头文件,集中包含常用头文件
#include "stm32f1xx_hal.h" // 通过main.h间接包含

// 简单的毫秒延时函数(软件循环,不精确,仅用于测试)
void Delay_ms(uint32_t ms)
{
    for(uint32_t i = 0; i < ms; i++)
    {
        for(uint32_t j = 0; j < 7200; j++) // 这个循环次数需要根据主频调整
        {
            __NOP(); // 空操作
        }
    }
}

// 错误处理函数,HAL库出错时会调用
void Error_Handler(void)
{
    while(1) { } // 死循环,实际项目中可以点亮错误灯或重启
}

// 系统时钟配置函数
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    // 配置HSE(外部高速时钟)和PLL(锁相环)
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 8MHz * 9 = 72MHz
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    // 配置系统时钟(SYSCLK)、AHB、APB1、APB2时钟
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟源为PLL
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟 = SYSCLK = 72MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  // APB1时钟 = 36MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  // APB2时钟 = 72MHz
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) // Flash等待周期为2
    {
        Error_Handler();
    }
}

int main(void)
{
    // 初始化HAL库,会重置所有外设,初始化SysTick定时器
    HAL_Init();

    // 配置系统时钟到72MHz
    SystemClock_Config();

    // 初始化GPIOB的时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();

    // 配置PB1为推挽输出模式
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 主循环,闪烁LED
    while (1)
    {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1); // 翻转PB1电平
        Delay_ms(500); // 延时约500ms
    }
}

同时,在 User\Inc 创建 main.h,用于包含常用头文件和声明全局函数。

/* main.h */
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32f1xx_hal.h" // 包含HAL库
#include "stm32f1xx_it.h"   // 包含中断处理函数声明

// 这里可以放你的全局函数声明或变量声明
void Error_Handler(void);

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

5.2 处理常见的编译与链接错误

第一次编译(点击 Rebuild 按钮)很大概率不会一帆风顺。别慌,我们来逐一破解。

错误1:undefined symbol SystemInit 这个函数在 system_stm32f1xx.c 中定义,但它是弱定义。我们需要确保它被调用。检查 startup_stm32f103xe.s 汇编文件,在复位中断服务程序 Reset_Handler 里,是否有一句 bl SystemInit。通常有。如果没有,可能是文件不对。另外,确保 system_stm32f1xx.c 已添加到工程并正确编译。

错误2:大量HAL库函数未定义 这通常是因为头文件包含路径没设对,或者 USE_HAL_DRIVER 宏没有定义。请返回 4.3节,仔细检查 C/C++ 选项卡下的 Include Paths 和 Define 设置,确保路径正确且宏已添加。

错误3:.s 文件编译报错 确认已按照 4.2节 末尾所述,将 .s 文件的 File Type 设置为 ARM Assembler。

错误4:链接错误,关于 _printf 或 _scanf 这是因为我们使用了标准库函数(如 printf),但链接器找不到实现。我们勾选了 Use MicroLIB,所以需要确保在代码中包含了 stdio.h,并且重定向了 fputc 函数(如果要用串口打印)。对于初始模板,如果不使用 printf,可以暂时不处理。如果使用,需要实现 int fputc(int ch, FILE *f) 函数,将其指向你的串口发送函数。

错误5:HAL_Init 中关于 HAL_NVIC_SetPriorityGrouping 的警告或错误 检查 stm32f1xx_hal_conf.h 文件。找到 #define TICK_INT_PRIORITY 这一行,确保其值是一个有效的优先级(如 0x0F)。STM32F1的中断优先级分组,HAL库默认使用 NVIC_PRIORITYGROUP_4,即4位抢占优先级,0位子优先级。这个配置在 HAL_Init 里设置,通常没问题。

解决完这些错误,再次点击 Rebuild,你应该能看到编译进度条快速滚动,最后在底部的 Build Output 窗口出现 "0 Error(s), 0 Warning(s)" 的字样。恭喜你,一个从零搭建的、纯净的STM32 HAL库工程模板诞生了!

6. 工程优化与进阶技巧

得到一个能编译的工程只是开始,让它变得“好用”和“专业”才是目标。

6.1 创建实用的批处理脚本

在工程根目录下创建两个批处理脚本,会极大提升效率。

Clean.bat:一键清理编译生成文件。

@echo off
echo 正在清理Keil生成文件...
if exist .\Project\MDK-ARM\Objects ( rmdir /s /q .\Project\MDK-ARM\Objects )
if exist .\Project\MDK-ARM\Listings ( rmdir /s /q .\Project\MDK-ARM\Listings )
del /q .\Project\MDK-ARM\*.axf .\Project\MDK-ARM\*.hex .\Project\MDK-ARM\*.bin .\Project\MDK-ARM\*.map 2>nul
echo 清理完成!
pause

在提交代码到Git或打包项目前运行一下,可以清除所有中间文件,保持仓库清洁。

OpenProject.bat:快速打开工程。

@echo off
start .\Project\MDK-ARM\MyHALTemplate.uvprojx

把工程文件夹扔在桌面,双击这个脚本就能直接打开Keil工程,比一层层点进去方便多了。

6.2 配置HAL库与裁剪

stm32f1xx_hal_conf.h 这个文件是HAL库的“配置中心”。你可以通过注释或取消注释里面的 #define 来启用或禁用特定的外设驱动。例如,如果你的项目只用GPIO和UART,那么可以把 HAL_ADC_MODULE_ENABLED、HAL_SPI_MODULE_ENABLED 等都注释掉。这样做有两个好处:一是编译速度更快,二是最终生成的代码体积更小。记得,用哪个外设,就使能哪个模块。

6.3 建立自己的板级支持包

在 Drivers/BSP 目录下,开始建立你自己的硬件抽象层。例如,创建 BSP_LED.c 和 BSP_LED.h,将初始化GPIO、点亮、熄灭LED的操作封装成 BSP_LED_Init(), BSP_LED_On(), BSP_LED_Off() 这样的函数。同样,为按键、蜂鸣器、特定的传感器都创建独立的BSP模块。

这样做的好处是硬件无关性。你的应用层代码(在 User/Src 里)只调用 BSP_LED_On(LED1),而不关心LED1具体连在哪个GPIO引脚上。如果哪天你换了一块板子,只需要修改 BSP_LED.c 里的引脚定义,应用层代码一行都不用改。这是写出可移植、易维护代码的关键。

6.4 版本管理与文档

立即为这个工程模板初始化一个Git仓库(在根目录执行 git init)。将 Core, Drivers/HAL_Driver, User/Inc, User/Src/main.c 等你自己创建和修改的核心文件提交进去。而 Project/MDK-ARM 目录下的 .uvprojx 等工程文件,因为包含本地绝对路径信息,建议添加到 .gitignore 文件中,或者团队成员约定好使用相对路径配置后也可纳入管理。

在 Docs 目录下,简单写一个 README.md,说明这个工程的结构、编译方法、以及主要功能。好记性不如烂笔头,也为日后可能的团队协作打下基础。

走到这一步,你已经不仅仅是一个HAL库的使用者,更是一个拥有自己强大“开发武器库”的创造者。这个亲手搭建的工程模板,会成为你未来所有STM32项目的坚实起点。每次开启新项目,只需复制这个模板,修改芯片型号和BSP驱动,就能迅速进入业务逻辑开发,把时间花在真正创造价值的地方。

stm32CubeMX,配合Keil,使用HAL库(或标准库)方式进行串口通信 今天我们学习STM32CubeMX串口的操作,以及HAL库串口的配置,我们会详细的讲解各个模块的使用和具体功能,并且基于HAL库实现Printf函数功能重定向,USART中断接收,本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 阅读详情

相关推荐

【STM32】标准库与HAL库对照学习教程零--开发环境的搭建

【STM32】标准库与HAL库对照学习教程零--开发环境的搭建一、keil5的下载与安装1、keil5的下载2、keil5的安装3、keil5的破译4、keil5的软件包安装二、STM32Cube 的下载与安装1、JAVA 运行环境安装2、cubemx安装3、安装相关芯片HAL库 一、keil5的下载与安装 1、keil5的下载 下载 Keil5 方法:进入 https://www.keil.com/网址 1.1 点击 Downloads,如图所示: 1.2 然后点击 MDK-Arm,如图所示: 1.

修成真的博客 5869

keil添加hal库_一、使用HAL库建立STM32工程

一、建立一个空文件夹,在其中建立四个空文件夹 Doc : 存放说明文档等Libraries : 存放CMSIS文件和HAL库文件Project :存放Keil工程User : 存放用户自己的文件二、向空文件夹中添加目标文件1. Libraries文件所需要的文件在Cube驱动包中:STM32Cube_FW_H7_V1.5.0 →Drivers : 将这两个文件复制到Liraries中。2. ...

weixin_29660181的博客 6576

Keil创建自定义的STM32 HAL库工程

将 STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Include 目录下的 {system_stm32f1xx.h, stm32f101xe.h, stm32f1xx.h} 拷贝到 00_STM32_Demo\Core 目录下。将 STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Core\Include 目录下的 {core_cm3.h} 拷贝到 00_STM32_Demo\Core 目录下。

qq_42851449的博客 1937

STM32开发——简介、开发环境(Keil5、CubeMX)、HAL库

什么是单片机?单片机(Single-Chip Microcomputer)是一种集成电路芯片,把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。STM系列单片机命名规则ST -- 意法半导体M -- Microelectronics 微电子32 -- 总线宽度项目。

m0_67794575的博客 1万+

STM32教你从零创建一个HAL库工程文件(STM32G4版)

关于从0创建stm32的hal库工程

ldfmq的博客 2520

STM32实验——HAl库点灯

自动代码生成:该工具能够自动生成C语言的初始化代码,这些代码可以直接用于微控制器的编程。配置微控制器:使用STM32CubeMX时,用户可以选择特定的STM32微控制器型号,然后根据项目需求配置时钟、GPIO、中断、外设等参数。生成代码:配置完成后,STM32CubeMX可以生成相应的初始化代码,这些代码可以被集成到开发环境中,如Keil、IAR或SW4STM32。:STM32CubeMX提供了一个直观的图形用户界面(GUI),允许用户通过拖放和选择的方式来配置微控制器的各种参数。端口输出电平选高电平。

Kamisama6930的博客 1275

[STM32]从零开始的STM32 HAL库环境搭建

讲解了cubeMX的安装以及相关固件库的安装和STM32HAL库环境生成。

c858845275的博客 7135

Keil5新建HAL库工程

打开,选择驱动;选择芯片厂家和内核型号;找到对应的pack点击下载即可,下载完成后双击下载即可。温馨提示:下载速度可能比较慢,建议科学上网。

m0_58575898的博客 4930

STM32(HAL库) CubeMX+Keil5 建立工程

参考的成电应电科协 觉得老师讲得很好 就记下来了。

m0_73640344的博客 5578

避坑指南:Abaqus网格划分中90%用户会遇到的5个质量陷阱(附解决方案)

本文深入剖析Abaqus网格划分中90%用户会遇到的5个典型质量陷阱,包括单元扭曲、扫掠网格失败、尺寸梯度控制等,并提供工程级解决方案。通过Python脚本和虚拟拓扑等技巧,帮助用户提升网格质量,确保有限元分析结果的可靠性,适用于CAE工程师和仿真分析师。

weixin_29243279的博客 101

怎么用phpstudy制作网站

随着实践的深入,你会逐渐掌握更多高级技巧和技术,让你的网站变得更加完善和吸引人。现在你已经成功设置了你的本地Web服务器环境,接下来我们将指导你如何利用这个环境来创建一个简单的PHP网页项目。为了使网站更加动态且功能丰富,我们需要学会如何让PHP脚本与MySQL数据库交互。为了让网站看起来更专业美观,可以考虑引入CSS样式表来定制网页布局及视觉效果。当你对本地开发的网站感到满意后,下一步就是将其发布到互联网上供他人访问了。让我们进一步扩展我们的网站,加入一个简单的用户注册与登录系统。

2401_87999399的博客 6575

STM32创建HAL库工程 (手把手教)

HAL库是ST公司目前主力推行的开发方式,全称就是Hardware Abstraction Layer(抽象印象层)。库如其名,很抽象,一眼看上去不太容易知道他的作用是什么。但它相对于标准库来说更加简洁高效,同样的功能,标准库可能要用几句话,HAL库只需用一句话就够了。并且HAL库也很好的解决了程序移植的问题。因此HAL库是ST未来主推的库。

2301_80262474的博客 6856

Python实战:3分钟搞定A股K线数据抓取(附东方财富/腾讯API完整代码)

本文为量化交易初学者提供了一份快速获取A股K线数据的实战指南。通过对比东方财富与腾讯财经两大免费API的优劣,并附上可直接运行的完整Python代码,帮助读者在3分钟内搭建起自己的数据抓取管道,为构建量化交易系统奠定坚实的数据基础。

weixin_29062255的博客 2920

【STM32】STM32F103ZET6 创建工程模版详解(HAL库)

HAL库,全称为Hardware Abstraction Layer(硬件抽象层)库,是STMicroelectronics(ST)为STM32微控制器提供的较新的固件库。HAL库的定义与特点定义:HAL库是一个中间件,为应用程序和硬件之间提供了一个接口,允许开发者在不知道底层硬件细节的情况下编写控制硬件的代码。特点跨平台支持:HAL库支持STM32全系列微控制器,使得开发者编写的代码可以在不同的STM32产品之间移植。结构统一:为所有外设提供统一的API和驱动结构,简化了开发过程。易于使用。

C/C++软件工程师、嵌入式软件工程师、物联网研发工程师、C/C++讲师、物联网讲师、嵌入式讲师、鸿蒙讲师---欢迎大家一起交流(私信添加博主微信) 4259

手把手教你用Nangate 45nm开源工艺库搞定数字电路仿真(附FreePDK资源)

本文详细介绍了如何使用Nangate 45nm开源工艺库进行数字电路仿真,包括环境搭建、关键文件解析、仿真环境配置及低功耗设计等实战内容。特别推荐FreePDK资源,帮助读者快速掌握从理论到实践的全流程操作,适用于学术研究和小规模数字电路设计。

weixin_30352645的博客 490

时间序列预测 | Python实现ARIMAX和VARMAX时间序列数据预测

时间序列预测 | Python实现ARIMAX和VARMAX时间序列数据预测 目录时间序列预测 | Python实现ARIMAX和VARMAX时间序列数据预测基本介绍ARIMAXVARVARMAVARMAXSESHWES参考资料 基本介绍 本文介绍ARIMAX、VAR、VARMA和VARMAX基本概念及其Python程序设计。 ARIMAX 具有外源回归量的自回归整合移动平均值(ARIMAX)是 ARIMA 模型的扩展,其还包括外生变量的建模。 外生变量也称为协变量,可以被认为是并行输入序列,其在与

前程算法屋的博客 6689

STM32-HAL库开发快速入门

STM32-HAL库开发:记录使用HAL库开发时候如何配置STM32的各个外设-

xuhc_zd的博客 7301

基于 STM32 单片机的实验室多参数安全监测系统设计与实现

本系统以 STM32F103C8T6 单片机为核心,集成温湿度监测、烟雾检测、气体泄漏报警、人体移动监测等功能模块,通过 OLED 显示屏实时显示数据,并支持 Wi-Fi 远程传输。系统可对实验室异常环境参数(如高温、烟雾、燃气泄漏)及非法入侵实时报警,保障实验室安全。本文从硬件选型、电路设计到软件实现提供了完整的实验室安全监测系统方案,可根据实际需求调整传感器类型和通信方式,适用于科研、教学等场景的环境安全防护。:可增加继电器模块控制通风设备或切断电源,集成 ZigBee 组网实现多实验室联动监测。

weixin_42300449的博客 1285

【STM32开发指南】手把手带你从零开始搭建工程(HAL库版)

本文将带领大家通过STM32标准库,一步步创建并配置一个Keil工程,无论是初学者还是有一定经验的开发者,希望都能从中获得实用的指导和启发。本文以STM32F103芯片开发为例,从环境搭建开始,逐步到项目配置、代码编写与编译调试,让每一位读者都能掌握基于STM32标准库在Keil环境下的工程创建方法。

Exun Blog 2599

以太网_RGMII接口与GMII接口的转化_03

RGMII接口转GMII接口!

weixin_42499230的博客 379

CS 188 Project3(RL) Q10:Approximate Q-Learning

实现一个近似的Q-learning学习代理,它学习状态特征的权重,其中许多状态可能共享相同的特征。在qlearningAgents.py中的ApproximateQAgent类中编写实现,它是PacmanQAgent的子类。 注:近似Q-learning学习假设在状态和动作对上存在一个特征函数f(s,a),它产生一个向量f1(s,a) .. fi(s,a) .. fn(s,a)特征值。我们在fe...

大模型与Agent智能体 2657

STM32手动创建工程-HAL库,超详细

T

wwh219的博客 9762

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

使用HAL库、STM32CubeMX和Keil 5开发入门教程(一):点亮一盏LED灯(NUCLEO-F411RE)

本教程以点亮一盏LED灯为目的为大家演示用STM32CubeMX、Keil、ST-Link开发STM32程序的一般方法。一、学习前的准备工作硬件:一块STM32开发板,一个ST-Link;(我使用的开发板是NUCLEO-F411RE) 软件:装好ST-Link的驱动程序,装好STM32CubeMX,装好Keil; 文档:开发板的原理图、芯片的参考手册和HAL驱动说明书。 附:STM32F4xx

CharmingSun的博客 3万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

KEIL V5切换STM32标准库与HAL库方法

KEIL V5切换STM32标准库与HAL库方法 在STM32开发过程中,偶尔要使用STM32标准库函数与STM32 HAL库,但是发现,如果安装HAL后,再打开标准库的工程后,发现编译出错了,看下图 原理是标准库找不到了。怎么解决呢 打开STM32库函数默认的安装路径 可以看有两个库函数,文件夹1.0.8是安装的标准库文件,2.14.0文件夹是HAL库文件。 解决步骤 打开标准库工程,打开库操作图标 再点击上层的OK 重新编译工程,完美解决 当然,如果标准库切换为HAL也是同样的方法了。

wwwqqq2014的博客 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

KEIL5环境下利用HAL库开发STM32项目_工程搭建方法

本文主要讲述在KEIL5环境下,如何搭建基于HAL库的STM32项目模板工程,全篇以STM32F103ZE芯片为例进行讲解,并对工程中主要的几个关键文件作用进行了阐述,适合入门级别同学参考借鉴。

Leon的博客 2093

从零到一:用KEIL5与HAL库构建STM32H7的工程脚手架

本文详细介绍了如何使用KEIL5与HAL库从零开始构建STM32H7的工程脚手架。内容涵盖工程架构设计哲学、KEIL5的精细配置、HAL库的深度解析与配置策略,以及编译优化和调试技巧,旨在帮助嵌入式开发者建立规范、健壮且可维护的项目基础框架。

leaf8的博客 664
上一篇: 半导体表面与MIS结构的物理特性及其在微电子器件中的应用
下一篇: Magics21 快速安装指南:从零到完成的详细步骤
php55
博客等级 码龄15年 51粉丝 1553原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值