news 2026/4/28 18:27:24

01-1软件开发与2-1新建工程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
01-1软件开发与2-1新建工程

参考

STM32+PCB设计+物联网,手牵手带你从零开始画板子+写代码

https://www.bilibili.com/video/BV18arkYjEuL

STM32入门教程-2023版 细致讲解 中文字幕

https://www.bilibili.com/video/BV1th411z7sn

【已完结STM32】–自学江协科技笔记汇总

https://blog.csdn.net/2301_81011494/article/details/147069164

1.1课程简介

https://www.bilibili.com/video/BV1th411z7sn/

2-1软件开发

安装过程见
00-Keil与STLINK与CH340安装

2-2新建工程

1.新建文件夹

新建工程的文件夹,

d:\stm32pro\

打开Keil5软件–>选择Project—>New uVision Project -->选择d:\stm32pro\

然后选择刚刚我们新建的文件夹,在 新建文件夹 里面再建一个文件夹

d:\stm32pro\2-1STM32工程模板

进入

d:\stm32pro\2-1STM32工程模板

输入工程文件名Project,然后点击保存工程,

接下来就是选择芯片型号,我们的芯片型号是STM32F103C8T6。

用来存放本次工程。

点击OK,弹出来的是新建工程小助手,这个可以帮助我们快速新建工程,我们暂时用不到这个,直接选择叉掉。

这样就新建好一个工程,但是还不完整,还需要添加文件

此时的工程目录如下

2.start启动文件

添加文件到本地的Start目录下

工程建好之后 还需要添加一些库文件,首先在工程文件夹下新建一个Start启动文件

然后打开固件库文件夹

D:\BaiduNetdiskDownload\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\

找到启动文件,

D:\BaiduNetdiskDownload\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm

(固件库文件来自b站江科大,可自行下载,见固件库的下载方式)

将arm里面的启动文件全部复制到工程模板文件夹Start文件夹下

接着回到STM32F10x文件夹,找到STM32头文件和配置时钟文件,也复制到Star文件夹下

接着还需要添加内核寄存器的描述文件,打开文件路径:

D:\BaiduNetdiskDownload\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport\

,同样复制到Start文件夹下

把本地Start目录下的文件添加到Keil5工程中

接着回到Kile5,把刚才复制到的文件添加到工程里,单击Source Group 1可将其改为Start

然后右键单击Start,选择AddExisting Files to Group ‘Start’

弹出的页面默认只添加.c文件

选择文件类型中的所有类型,可以看到所有文件

这里只需要添加后缀为md.s的启动文件就可以了 ,选择add,然后单击close

然后把 本地Start目录中剩下的的.c和.h文件都要添加进来

3、添加头文件路径

最后还需要在工程选项添加头文件路径

首先确定ARM 的Compiler ,选择version5

右键Keil5中左侧,选择Options for Target ‘Target1’

弹出的选项界面中,选择C/C++选项,然后选择Include Paths,选择新建new,选择三个点的图标,选择头文件的目录

按照要求选择目录即可

4、 测试工程

测试工程是否可行,在工程本地文件夹下新建一个User文件用来存放main函数

进来Kile5右击Target1添加组

并将其改名为User

,然后右击User添加新项目到组里

选择文件类型,设置文件名,文件的路径

单击确定即可

这样工程文件夹里面就可以看到有一个main文件了

插入头文件

并编写一个main函数,注意代码最后一行必须空行,否则会报警告

#include "stm32f10x.h" // Device header int main(void) { while(1) { } }

以上配置就可以用寄存器开发32单片机了。当然用寄存器开发STM32不太适合初学者,后面还要添加库函数。

现在进行build, 编译通过0错误0警告就证明工程建立成功

5、连接下载器ST-LINK(注意事项)

ST-LINK通过杜邦线链接最小系统版,注意接线

插上后,会出现一个灯亮表示电源,链接在PC13的灯默认是闪烁状态,这是芯片里的一个测试程序

插上下载器ST-LINK,点击魔术棒找到Debug,选择ST-Link ,然后选择Flash Download为自动复位

然后选择工程的build,编译成功后,单击load,如果load成功,Keil会提示,同时最小系统版的灯不再闪烁

因为load进去的代码没有操作

6、测试点灯

基于寄存器配置,测试点灯程序 ,最小系统板上的的灯是低电平点亮的,0x00002000是灯灭,0x00000000是灯亮

打开

D:\BaiduNetdiskDownload\STM32入门教程资料\参考文档\参考文档\STM32F10xxx参考手册(中文).pdf
7.3.7 APB2外设时钟使能寄存器(RCC_APB2ENR)

GPIO都是APB2的外设,在7.3.7 APB2外设时钟使能寄存器(RCC_APB2ENR)

00000000 00000000 00000000 00010000 00 00 00 10 0X00000010
#include "stm32f10x.h" // Device header int main(void) { // 使能GPIOC RCC->APB2ENR = 0X00000010; while(1) { } }
在8.2.2端口配置寄存器(GPIOx_CRH)(x=A…E)

这样如果给GPIOC的13设置为通用推挽 输出模式设置为50MHz,

21:20位为 11输出模式设置为50MHz 23:22位为00通用推挽模式 00000000 00110000 00000000 00000000 00 30 00 00 00300000

代码如下

#include "stm32f10x.h" // Device header int main(void) { // 使能GPIOC RCC->APB2ENR = 0X00000010; // 设置GPIOC 推挽与50MHz GPIOC->CRH=0X00300000; while(1) { } }
在8.2.4端口输出寄存器(GPIOx_ODR)(x=A…E)

可以看到,如果想给PC13上的灯点亮(低电平点亮),给ODR设置为0,可以都设置为0,即

GPIOC->ODR=0X00000000 表示灯亮

给GPIOC->ODR=0X00002000表示灯灭

二进制和十六进制为

00000000 00000000 00100000 00000000 00 00 20 00 00002000 00000000 00000000 00100000 00000000 00 00 20 00 00002000
#include "stm32f10x.h" // Device header int main(void) { // 使能GPIOC RCC->APB2ENR = 0X00000010; // 设置GPIOC 推挽与50MHz GPIOC->CRH=0X00300000; // 设置灯亮 GPIOC->ODR=0X00000000; // 设置灯灭 //GPIOC->ODR=0X00002000; while(1) { } }

实现闪烁

#include "stm32f10x.h" // Device header int main(void){ RCC->APB2ENR = 0x00000010; // 设置GPIOC 推挽与50MHz GPIOC->CRH=0X00300000; while(1){ uint32_t i, j; // 在循环外声明变量(兼容C90标准) for(i = 0; i < 3000; i++) for(j = 0; j < 3600; j++); // 大约1ms的延时 GPIOC->ODR=0X00000000 ;//表示灯亮 for(i = 0; i < 3000; i++) for( j = 0; j < 3600; j++); // 大约1ms的延时 GPIOC->ODR=0X00002000 ;//表示灯灭 } }

循环版本

#include "stm32f10x.h" // Device header // 延时函数,大约延时ms毫秒 void Delay_ms(uint32_t ms) { uint32_t i, j; // 简单的软件延时,具体值需要根据实际系统时钟校准 for(i = 0; i < ms; i++) for(j = 0; j < 7200; j++); // 大约1ms的延时 } int main(void){ //RCC->APB2ENR=0X00000010; // 使能GPIOC RCC->APB2ENR = 0X00000010; // 设置GPIOC 推挽与50MHz GPIOC->CRH=0X00300000; while(1){ // 设置灯亮 GPIOC->ODR=0X00000000; Delay_ms(3000); // 延时3秒 // 设置灯灭 GPIOC->ODR=0X00002000; Delay_ms(3000); // 延时3秒 } }

7.添加库函数

上面的方式需要经常查看手册的寄存器,采用库函数可以解决这个问题

打开工程文件夹,新建一个文件夹Library,用来存放库函数

打开固件库文件找内核库函数源文件,路径:

D:\BaiduNetdiskDownload\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src

打开固件库文件找内核库函数头文件,路径:

D:\BaiduNetdiskDownload\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc

然后Ctrl+a全选复制刚刚新建的到工程文件夹下Library文件夹下

回到Kile5右击Target1添加组并命名为Library,右击Library添加存在的文件,将库函数源文件和头文件全部添加进来

至此库函数还不能直接使用,还需要再添加一个文件。接着打开固件库文件

D:\BaiduNetdiskDownload\STM32入门教程资料\固件库\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template\

stm32f10x_it.h stm32f10x_it.c stm32f10x_conf.h

复制到User目录下

接着回到Kile5把刚刚的三个文件添加到User组里

最后我们还需要一个宏定义,跳转到头文件stm32f10x.h下滑到最后,找到 USE_STDPERIPH_DRIVER

然后选择魔法棒–选择C++,将USE_STDPERIPH_DRIVER复制到Define ,同时在include中添加User和Library目录

最后编译一下,0错误0警告说明工程建立成功

8.用库函数点灯

RCC_APB2PeriphClockCmd函数

通过右键RCC_APB2PeriphClockCmd()跳转到定义的位置

第一个参数选择 RCC_APB2Periph_GPIOC,第二个参数ENABLE

// #define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Init函数

通过右键RCC_APB2PeriphClockCmd()跳转到定义的位置

第一个参数为GPIO_TypeDef* GPIOx, 第二个参数为GPIO_InitTypeDef* GPIO_InitStruct

参数需要一个结构体,就需要先定义一个结构体

// 定义GPIO的结构体,通过.设置结构体的属性 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_InitStructure.GPIO_Pin = GPIO_InitStructure.GPIO_Speed =

右键GPIO_Mode可以看到定义的位置,注释中的无法跳转,选择GPIOMode_TypeDef然后复制查找

可以看到GPIOMode_TypeDef是一个枚举,可以把GPIO_Mode_Out_PP设置给结构体

// 定义GPIO的结构体,通过.设置结构体的属性 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_InitStructure.GPIO_Speed =

右键GPIO_Pin查看定义,出现左下角的多个定义,选择member,

跳转到

选择注释中的GPIO_pins_define,ctrl+f可以快速查找,选择Find Next

复制 GPIO_Pin_13 到GPIO_Pin

// 定义GPIO的结构体,通过.设置结构体的属性 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed =

右键跳转,在注释中ctrl+f查找,可以看到是一个枚举类型,选择GPIO_Speed_50MHz

复制GPIO_Speed_50MHz到 GPIO_InitStructure.GPIO_Speed如下:

// 定义GPIO的结构体,通过.设置结构体的属性 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

把结构体地址赋值给GPIO_Init函数

// 定义GPIO的结构体,通过.设置结构体的属性 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 初始化GPIOC // 第一个参数为GPIO_TypeDef* GPIOx, 第二个参数为GPIO_InitTypeDef* GPIO_InitStruct // 先在上面初始化一个GPIO_InitTypeDef结构体 变量名为 GPIO_InitStructure GPIO_Init(GPIOC,&GPIO_InitStructure);

编译下,出现如下问题

问题13:编译时,出现错误declaration may not appear after executable statement in block

可以把GPIO_InitTypeDef GPIO_InitStructure;放在句首,也可以在c/c++选项卡在,勾选C99 Mode,就可以在 在函数的可执行语句之后定义变量了。

GPIO_SetBits和GPIO_ResetBits函数
// 给GPIOC的13端口设置高电平 //GPIO_SetBits(GPIOC,GPIO_Pin_13); // 给GPIOC的13端口设置低电平 GPIO_ResetBits(GPIOC,GPIO_Pin_13);

编译下,然后load 就出现灯亮了

9.新建工程步骤

建立工程文件夹,Keil中新建工程,选择型号
工程文件夹里建立Start、Library、User等文件夹,复制固件库里面的文件到工程文件夹
工程里对应建立Start、Library、User等同名称的分组,然后将文件夹内的文件添加到工程分组里
工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹
工程选项,C/C++,Define内定义USE_STDPERIPH_DRIVER
工程选项,Debug,下拉列表选择对应调试器,Settings,Flash Download里勾选Reset and Run

10.工程结构

所以复位键后,程序后重新启动

单片机的程序最后为一个死循环,永远不会结束

SystemInit的函数定义在system开头.c的里了

拓展:固件库的下载方式

进入官网

意法半导体官网 | ST官网 - STMicroelectronics

选择产品–微处理器

选择主流MCU,选择F1系列,选择STM32F103

选择工具与软件

选择嵌入式软件中的MCU and MPU embedded software,

选择

STM32 Standard Peripheral Libraries,选择STSW-STM32054

选择打开Open software page,选择对应的版本,这里选择的是3.5

选择版本后,谈成是否接受界面

单击接受后,进入登录或访客下载页面

登录或访客都可以,

进入版本选择并选择版本边上的下载按钮,即完成下载的功能

下载后的压缩包与提供的压缩包内容一致。

拓展:固件库的目录说明

STM32 标准外设库(StdPeriph Library)是 ST 官方为简化开发提供的工具包,其目录结构分工明确。以下结合典型目录(以 STM32F1 系列为例),解析核心目录的作用:

一、核心目录:Libraries(驱动库核心)

是外设库的底层支撑,包含CMSIS 内核抽象层STM32 外设驱动层,让开发者无需直接操作寄存器即可控制硬件。

1.CMSIS 文件夹(Cortex-M 软件接口标准)
  • 作用:实现 Cortex-M 内核与芯片外设的解耦,让代码兼容不同厂商的 Cortex-M 芯片,同时简化内核相关操作(如中断、调试)。
  • 子目录分解
    • Core_Support

      • core_cm3.c/h(对应 Cortex-M3 内核,M4/M7 内核则为core_cm4.c/h等):
        定义内核寄存器的操作函数(如配置 NVIC 中断优先级、系统滴答定时器),实现内核外设(如 SysTick、NVIC)的驱动。
      • 这些文件是 ARM 官方提供的通用代码,与 STM32 芯片无关,只负责内核层面的抽象。
    • Device/ST/STM32F1xx

      • 启动文件(如startup_stm32f10x_h/m/ld.s,汇编编写):
        芯片上电后第一步执行的代码,负责初始化栈指针、复制全局变量到 RAM、跳转到main函数。不同容量的芯片(小/中/大容量)对应不同启动文件(如hd代表大容量)。
      • system_stm32f10x.c/h
        定义SystemInit()函数,初始化系统时钟(配置 HSE、HSI、PLL 等,设置 AHB/APB 总线分频),是启动流程的关键步骤。 STM32主频是72MHz,就是这个文件中配置的
      • stm32f10x.h
        外设寄存器的映射文件,通过宏和结构体(如GPIO_TypeDef)定义所有外设的寄存器地址(如GPIOA->CRL对应 GPIOA 的配置寄存器),是库函数操作硬件的基础。类似Reg51.h ,描述有哪些寄存器和地址,有些类似域名与ip地址的关系
2.STM32F10x_StdPeriph_Driver 文件夹(外设驱动层)
  • 作用:为 STM32 的每个外设(GPIO、UART、SPI 等)提供封装好的库函数,开发者通过调用函数即可配置外设,无需深入寄存器细节。
  • 子目录分解
    • inc 文件夹
      存放外设的头文件(如stm32f10x_gpio.hstm32f10x_usart.h):

      • 定义初始化结构体(如GPIO_InitTypeDef,包含引脚模式、速度、上下拉等参数)。
      • 声明库函数(如GPIO_Init()USART_SendData())。
      • 定义寄存器的位掩码(如GPIO_Mode_Out_PP代表推挽输出模式)。
    • src 文件夹
      存放外设的源文件(如stm32f10x_gpio.cstm32f10x_usart.c):

      • 实现inc中声明的函数,内部通过操作stm32f10x.h的寄存器完成功能(如GPIO_Init()会修改GPIOx->CRL/CRH寄存器)。
      • 每个外设的功能(如 GPIO 翻转、UART 发送数据)都通过这里的函数封装。
    • 特殊文件:misc.c/h
      提供对**内核 NVIC(中断控制器)**的操作函数(如NVIC_Init()配置中断优先级、NVIC_EnableIRQ()使能中断),因为 NVIC 属于内核外设,需与芯片外设的中断配合使用。

二、辅助目录(项目开发相关)
1.Project 文件夹
  • 作用:提供官方示例工程编译器模板,快速上手开发。
  • 内容
    • STM32F10x_StdPeriph_Examples:按外设分类的示例(如 GPIO 翻转、UART 通信、SPI 传输),可直接导入 Keil/IAR 编译,学习外设的典型用法。
    • Templates:针对不同编译器(Keil、IAR)的工程模板,包含最小化的文件结构(已关联库路径、包含必要头文件),开发者可在此基础上扩展功能。
2.Utilities 文件夹
  • 作用:存放 ST 官方评估板(如 STM32 Discovery、Eval 板)的专用驱动和示例
  • 内容
    • 评估板上的扩展硬件(如显示屏、传感器、按键)的驱动代码(如stm32_eval_led.c)。
    • 若使用通用开发板,这部分可忽略,但其中的驱动设计思路(如分层封装、状态机)可借鉴。
3.根目录文件
  • stm32f10x_stdperiph_lib_um.chm
    库函数帮助文档(CHM 格式),详细说明每个库函数的参数、功能、使用示例(如USART_Config()如何配置波特率、校验位),是开发时的核心参考。
  • Release_Notes.html
    版本说明,记录库的更新内容、支持的芯片型号、已知问题,用于确认库的兼容性。
三、目录协作关系与开发流程
  1. 底层支撑Libraries/CMSIS负责内核和芯片的基础初始化(启动、时钟、寄存器映射)。
  2. 外设控制Libraries/STM32F10x_StdPeriph_Driver提供外设的库函数,开发者通过调用这些函数配置硬件(如GPIO_Init()设置引脚模式)。
  3. 快速验证Project中的示例和模板可直接复用,减少搭建工程的时间。
  4. 参考学习Utilities中的评估板代码和chm文档辅助理解外设用法。

通过合理利用这些目录,开发者可跳过寄存器级的繁琐操作,专注于应用层逻辑,大幅提升开发效率。若需深入底层,也可通过stm32f10x.hcore_cm3.h查看寄存器定义,实现库函数的扩展或自定义。

拓展:GPIO 与 APB2

在STM32微控制器中,这句话描述的是GPIO(通用输入/输出端口)与系统总线架构中APB2总线的连接关系,以下从微控制器的总线架构、APB2总线特点、GPIO作为外设的属性这几个方面来深入理解:

微控制器的总线架构

STM32微控制器采用了先进的总线架构,以实现不同功能模块之间高效的数据传输和控制。其中,常见的总线有AHB(Advanced High-performance Bus,高级高性能总线)和APB(Advanced Peripheral Bus,高级外设总线) 。

  • AHB总线:主要用于连接高性能、高数据传输速率的模块,如CPU内核、存储器、DMA控制器等。它能够支持高速的数据传输,满足对带宽要求较高的设备之间的数据交互。
  • APB总线:则是用于连接低带宽的外设模块,为这些外设提供了一种相对简单且低功耗的通信方式。APB又分为APB1和APB2,它们的主要区别在于工作频率和所连接的外设类型。
APB2总线特点

APB2总线相较于APB1总线,通常具有更高的工作频率。这意味着连接到APB2总线上的外设可以在更快的时钟信号驱动下工作,从而具备更高的数据传输速率和响应速度。在STM32系列中,APB2总线通常用于连接那些对速度要求相对较高的外设。

GPIO作为APB2的外设
  • GPIO功能简介:GPIO是STM32中非常重要且常用的外设,它允许用户通过软件灵活地配置引脚的功能,如设置为输入模式来读取外部信号(像按键状态),或者设置为输出模式来控制外部设备(如点亮LED灯)。
  • 连接关系原因:GPIO在工作时,有时需要快速地响应外部信号的变化或者及时输出控制信号,比如在驱动高速通信接口的使能引脚,或者快速切换LED灯的亮灭状态来实现高频闪烁效果等场景下,就对数据传输和处理速度有一定要求。将GPIO连接到APB2总线上,利用APB2相对较高的工作频率,能够满足GPIO在这些快速操作场景下的性能需求。

不过需要注意,并不是所有STM32系列微控制器的GPIO都是APB2的外设 。不同型号的STM32,其外设与总线的连接情况会根据芯片的设计和定位有所差异。比如,一些低功耗或低成本的STM32型号,其GPIO可能会连接到APB1总线上,以平衡性能和功耗等方面的需求。

拓展:RCC_APB2ENR

在STM32微控制器中,RCC_APB2ENR是一个寄存器,它是复位和时钟控制(Reset and Clock Control,RCC)模块的一部分,全称为APB2外设时钟使能寄存器(Advanced Peripheral Bus 2 Peripheral Clock Enable Register),主要用于控制连接在APB2总线上的外设时钟的开启和关闭。以下从寄存器基本概念、作用原理以及使用方式这几个方面来理解它:

寄存器基本概念

寄存器是微控制器内部的一组存储单元,每个寄存器都被分配了特定的地址。通过对这些地址进行读写操作,就可以访问和修改寄存器中的值,进而实现对微控制器不同功能模块的配置和控制。RCC_APB2ENR寄存器也是如此,它在内存中占据特定的地址空间,用户可以通过编程来读写这个寄存器。

作用原理
  • 时钟控制机制:在STM32中,为了降低功耗以及对不同外设进行灵活管理,并不是所有外设的时钟在系统上电后都处于开启状态。每个外设都有对应的时钟使能位,当该位被设置为1时,相应外设的时钟才会被打开,外设才能正常工作;如果设置为0 ,外设时钟被关闭,此时外设处于低功耗状态,无法执行数据处理等操作。
  • 与APB2总线外设关联:APB2总线上连接着一些对速度要求相对较高的外设,比如GPIO端口(部分STM32型号)、ADC(模拟数字转换器)、SPI1(串行外设接口1)等。RCC_APB2ENR寄存器中的每一位都对应着一个连接在APB2总线上的外设。例如,在STM32F103系列中,RCC_APB2ENR寄存器的第2位对应着IOPAEN(GPIOA时钟使能位),第3位对应着IOPBEN(GPIOB时钟使能位)等。当要使用某个APB2外设时,就需要将该外设对应的时钟使能位置1 ,为其提供时钟信号,外设才能按照设定的功能运行。
具体使用方式(以STM32F103为例,基于标准外设库)
  1. 头文件包含:在使用与RCC_APB2ENR相关的功能之前,需要在代码中包含对应的头文件,如stm32f10x.h,该头文件中定义了RCC_APB2ENR寄存器以及相关的宏定义。
#include"stm32f10x.h"
  1. 使能外设时钟:比如要使用GPIOA端口,就需要使能GPIOA的时钟,示例代码如下:
// 使能GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

在上述代码中,RCC_APB2PeriphClockCmd是标准外设库中提供的函数,它的第一个参数指定要使能时钟的外设(这里是RCC_APB2Periph_GPIOA,对应RCC_APB2ENR寄存器中的IOPAEN位),第二个参数ENABLE表示使能该外设时钟,其本质就是对RCC_APB2ENR寄存器中对应的位进行置1操作。

  1. 关闭外设时钟:当某个外设不再使用时,为了降低功耗,可以关闭其时钟,示例代码如下:
// 关闭GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,DISABLE);

这里的DISABLE参数会将RCC_APB2ENR寄存器中IOPAEN位清0,从而关闭GPIOA的时钟。

总之,RCC_APB2ENR寄存器是STM32中管理APB2总线上外设时钟的关键部件,合理地配置它能够有效地控制外设的工作状态,实现对系统功耗和性能的优化。

拓展:GPIOx_CRH寄存器

在STM32微控制器中,配置完RCC_APB2ENR使能GPIO时钟后,还需要配置端口配置寄存器GPIOx_CRHx = A..E),这是因为两者承担着不同且互补的功能,具体如下:

时钟使能是基础前提

RCC_APB2ENR寄存器用于使能连接在APB2总线上的外设时钟,对于GPIO端口而言,使能其时钟是必不可少的准备工作。只有当GPIO对应的时钟使能位(例如RCC_APB2ENR中与GPIOA对应的IOPAEN位)被置1 ,GPIO端口才能正常工作。

这就好比给一个工厂供电,只有先接通电源,工厂里的机器(GPIO外设)才有可能运转起来, 但仅接通电源,机器并不会自动按照我们期望的方式工作,还需要对其进行功能设定。

GPIOx_CRH决定端口具体功能

GPIOx_CRH寄存器是GPIO端口的配置寄存器(高8位配置寄存器,对应引脚GPIOx_8 - GPIOx_15,低8位配置寄存器是GPIOx_CRL,对应引脚GPIOx_0 - GPIOx_7),它的作用是详细设定GPIO引脚的工作模式和输出速度等关键参数,具体如下:

1. 配置引脚工作模式

GPIO引脚可以配置为多种工作模式,以满足不同的应用需求,GPIOx_CRH中的相关位用于选择这些模式:

  • 输入模式
    • 浮空输入(IN_FLOATING):引脚的电平状态完全由外部输入决定,内部没有上拉或下拉电阻,常用于读取外部信号,如按键输入。
    • 上拉输入(IPU):引脚内部连接了上拉电阻,默认情况下引脚被拉高为高电平,当外部连接低电平信号时,引脚电平被拉低,适用于按键等外部信号常态为高电平的场景。
    • 下拉输入(IPD):与上拉输入相反,引脚内部连接下拉电阻,默认被拉低为低电平,用于外部信号常态为低电平的情况。
    • 模拟输入(AIN):引脚用于连接模拟信号源,关闭施密特触发器(一种用于波形整形的电路),直接将外部模拟信号接入内部ADC(模拟数字转换器),用于模拟量采集。
  • 输出模式
    • 通用推挽输出(GPIO_Mode_Out_PP):引脚可以输出高电平或低电平,驱动能力较强,常用于驱动LED灯、继电器等需要较大电流的负载。
    • 通用开漏输出(GPIO_Mode_Out_OD):引脚只能输出低电平,输出高电平时需要外部上拉电阻将引脚拉高,适用于需要“线与”逻辑(多个开漏输出引脚连接在一起,只要有一个输出低电平,整体就为低电平)的场景,或者用于电平转换。
    • 复用推挽输出(GPIO_Mode_AF_PP):引脚用于复用功能,如SPI、USART等外设的引脚,由外设模块控制引脚的输出信号,同样具有较强的驱动能力。
    • 复用开漏输出(GPIO_Mode_AF_OD):与复用推挽输出类似,但输出高电平时需要外部上拉电阻,常用于I2C等需要“线与”逻辑的复用功能场景。
2. 配置输出速度

在输出模式下,还可以通过GPIOx_CRH设置引脚的输出速度,常见的有2MHz、10MHz、50MHz等选项。 输出速度决定了引脚电平翻转的速率,合理选择输出速度可以避免信号干扰和电磁兼容性(EMC)问题。例如,驱动LED灯时,较低的输出速度(如2MHz)即可满足要求;而在高速通信接口(如SPI)中,可能就需要选择较高的输出速度(如50MHz)以满足数据传输速率的要求。

两者配合实现完整功能

配置RCC_APB2ENR打开GPIO时钟,是让GPIO模块能够正常工作;而配置GPIOx_CRH(和GPIOx_CRL)则是告诉GPIO模块具体要做什么,比如某个引脚是用于输入按键信号,还是用于输出驱动LED的信号,以及以什么样的速度和方式进行输入输出操作。

只有这两步配置都正确完成,GPIO引脚才能按照开发者的预期在电路中发挥作用,实现与外部设备的有效交互。

拓展:stm32f10x_it.hstm32f10x_it.cstm32f10x_conf.h作用

在STM32F10x系列的标准外设库项目中,stm32f10x_it.hstm32f10x_it.cstm32f10x_conf.h是三个具有特定功能的核心文件,分别承担中断服务程序管理和库配置的作用,具体解析如下:

1.stm32f10x_it.hstm32f10x_it.c:中断服务程序(ISR)的集中管理

这两个文件是中断服务程序的专用存放地,用于定义和实现STM32的所有中断处理函数,是系统响应外部事件(如GPIO触发、定时器溢出、串口接收等)的核心逻辑载体。

核心作用:
  • 中断函数声明与实现分离

    • stm32f10x_it.h:声明所有中断服务函数的原型(如EXTI0_IRQHandler()TIM2_IRQHandler()),供其他模块调用或引用。
    • stm32f10x_it.c:实现这些中断服务函数的具体逻辑,例如在外部中断触发时读取GPIO状态、在定时器中断中更新变量等。
  • 统一管理中断向量表映射
    STM32的中断向量表(启动文件中定义)会将硬件中断信号映射到stm32f10x_it.c中对应的函数。例如,当外部中断线0(EXTI0)触发时,系统会自动跳转到EXTI0_IRQHandler()函数执行。

  • 避免中断函数命名冲突
    中断服务函数的名称是固定的(由芯片硬件决定,如USART1_IRQHandler对应串口1中断),将其集中放在这两个文件中,可避免与其他模块的函数命名冲突,规范代码结构。

示例场景:

当需要处理按键触发的外部中断(如PA0引脚连接按键,触发EXTI0中断)时,会在stm32f10x_it.c中实现:

voidEXTI0_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line0)!=RESET){// 处理中断逻辑(如点亮LED、更新标志位)GPIO_SetBits(GPIOC,GPIO_Pin_13);// 清除中断标志位(必须操作,否则会持续触发中断)EXTI_ClearITPendingBit(EXTI_Line0);}}

stm32f10x_it.h中会声明该函数:

voidEXTI0_IRQHandler(void);
2.stm32f10x_conf.h:外设库的配置开关

该文件是标准外设库的“配置中心”,通过宏定义控制是否启用特定外设的驱动文件、中断向量和调试信息,用于裁剪项目代码、减少编译体积。

核心作用:
  • 选择性包含外设驱动头文件
    文件中通过#define宏控制是否包含某个外设的头文件。例如:

    #defineUSE_STDPERIPH_DRIVER// 启用标准外设库#include"stm32f10x_gpio.h"// 包含GPIO驱动#include"stm32f10x_usart.h"// 包含USART驱动// #include "stm32f10x_adc.h" // 注释掉则不启用ADC驱动

    未被包含的外设驱动不会被编译,从而减少固件体积。

  • 控制中断向量的使能
    部分外设的中断向量需要通过该文件间接控制(结合stm32f10x_it.c)。例如,若不启用ADC,则可注释掉#include "stm32f10x_adc.h",避免ADC相关的中断函数被编译。

  • 定义库函数的调试输出开关
    部分库函数(如assert_param()参数检查)的调试信息输出,可通过该文件中的宏(如USE_FULL_ASSERT)控制是否启用,便于开发阶段调试和量产阶段关闭冗余输出。

典型配置示例:
// 启用参数检查(开发阶段用,量产可关闭)#defineUSE_FULL_ASSERT// 包含需要使用的外设驱动#include"stm32f10x_rcc.h"// 时钟控制#include"stm32f10x_gpio.h"// GPIO控制#include"stm32f10x_tim.h"// 定时器控制// 不包含SPI和I2C驱动(项目中用不到)// #include "stm32f10x_spi.h"// #include "stm32f10x_i2c.h"
三者的协作关系
  • stm32f10x_conf.h决定项目中启用哪些外设驱动,为中断处理和其他功能提供基础支持。
  • 当外设触发中断时,中断向量表会引导系统执行stm32f10x_it.c中对应的中断服务函数,而这些函数的声明在stm32f10x_it.h中。
  • 三者共同构成了STM32中断系统和外设管理的核心框架,确保中断响应的规范性和代码的可维护性。

void);

#### 2. `stm32f10x_conf.h`:外设库的配置开关 该文件是**标准外设库的“配置中心”**,通过宏定义控制是否启用特定外设的驱动文件、中断向量和调试信息,用于裁剪项目代码、减少编译体积。 ##### 核心作用: - **选择性包含外设驱动头文件**: 文件中通过`#define`宏控制是否包含某个外设的头文件。例如: ```c #define USE_STDPERIPH_DRIVER // 启用标准外设库 #include "stm32f10x_gpio.h" // 包含GPIO驱动 #include "stm32f10x_usart.h" // 包含USART驱动 // #include "stm32f10x_adc.h" // 注释掉则不启用ADC驱动

未被包含的外设驱动不会被编译,从而减少固件体积。

  • 控制中断向量的使能
    部分外设的中断向量需要通过该文件间接控制(结合stm32f10x_it.c)。例如,若不启用ADC,则可注释掉#include "stm32f10x_adc.h",避免ADC相关的中断函数被编译。

  • 定义库函数的调试输出开关
    部分库函数(如assert_param()参数检查)的调试信息输出,可通过该文件中的宏(如USE_FULL_ASSERT)控制是否启用,便于开发阶段调试和量产阶段关闭冗余输出。

典型配置示例:
// 启用参数检查(开发阶段用,量产可关闭)#defineUSE_FULL_ASSERT// 包含需要使用的外设驱动#include"stm32f10x_rcc.h"// 时钟控制#include"stm32f10x_gpio.h"// GPIO控制#include"stm32f10x_tim.h"// 定时器控制// 不包含SPI和I2C驱动(项目中用不到)// #include "stm32f10x_spi.h"// #include "stm32f10x_i2c.h"
三者的协作关系
  • stm32f10x_conf.h决定项目中启用哪些外设驱动,为中断处理和其他功能提供基础支持。
  • 当外设触发中断时,中断向量表会引导系统执行stm32f10x_it.c中对应的中断服务函数,而这些函数的声明在stm32f10x_it.h中。
  • 三者共同构成了STM32中断系统和外设管理的核心框架,确保中断响应的规范性和代码的可维护性。

通过合理配置这三个文件,开发者可以高效管理中断逻辑、裁剪项目代码,适配不同场景的需求(如资源受限的嵌入式设备需最小化固件体积)。

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

LIBERO实战:深度图与RGB图像同屏可视化,让你的机器人‘看’得更清楚

LIBERO实战&#xff1a;深度图与RGB图像同屏可视化&#xff0c;让你的机器人‘看’得更清楚 在机器人视觉感知领域&#xff0c;同时理解场景的几何结构和纹理信息是完成抓取、导航等任务的关键。LIBERO作为机器人持续学习基准平台&#xff0c;为开发者提供了强大的多模态感知数…

作者头像 李华
网站建设 2026/4/28 18:21:22

3步永久保存微信聊天记录的终极解决方案:WeChatMsg完全指南

3步永久保存微信聊天记录的终极解决方案&#xff1a;WeChatMsg完全指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/…

作者头像 李华
网站建设 2026/4/28 18:21:20

D2RML终极指南:暗黑2重制版多账户管理神器,5分钟学会高效多开

D2RML终极指南&#xff1a;暗黑2重制版多账户管理神器&#xff0c;5分钟学会高效多开 【免费下载链接】D2RML Diablo 2 Resurrected Multilauncher 项目地址: https://gitcode.com/gh_mirrors/d2/D2RML 还在为《暗黑破坏神2&#xff1a;重制版》频繁切换账户而烦恼吗&am…

作者头像 李华
网站建设 2026/4/28 18:20:22

终极Python调试指南:掌握python-guide中的故障排除技巧与工具

终极Python调试指南&#xff1a;掌握python-guide中的故障排除技巧与工具 【免费下载链接】python-guide Python best practices guidebook, written for humans. 项目地址: https://gitcode.com/gh_mirrors/py/python-guide Python作为最受欢迎的编程语言之一&#xf…

作者头像 李华
网站建设 2026/4/28 18:14:51

AI可视化编辑在线模板:零代码快速生成专业设计内容的实操指南

当下数字内容生产节奏不断加快&#xff0c;不管是电商商家大促期间的批量物料产出&#xff0c;还是自媒体博主的多平台内容运营&#xff0c;或是中小企业的日常宣传需求&#xff0c;都对设计的效率和专业度提出了更高要求。传统设计流程依赖专业软件操作&#xff0c;门槛高周期…

作者头像 李华