当前位置: 首页 > news >正文

江协科技-1-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软件开发

安装Keil5 MDK

找到软件,双击MDK536.EXE

在这里插入图片描述

下一步,选择路径,

在这里插入图片描述

我在本地创建了一个目录

D:\zhangjun\

目录名不要包含特殊字符和中文

然后继续下一步,会安软件大概3min钟

安装后,出现是否安装ULINK调试器

在这里插入图片描述

选择是,就安装完成了

自动弹Pack Installer窗口,可以用于在线安装支持库,这一步先不用,后期可以在Keil中重新弹出来这个界面

在这里插入图片描述

安装器件支持包

离线安装

新建 一个工程,

在这里插入图片描述

会提示选择设备

在这里插入图片描述

这里只有GD32F4和STM32F4系列的,没有STM32F1系列的,需要安装下

找到离线支持包,进行离线安装

在这里插入图片描述

双击Keil.STM32F1xx_DFP.2.2.0.pack

在这里插入图片描述

目标路径为自动选择我们安装时的目录,单击Next就安装完成了

在这里插入图片描述

在线安装

如果没有对应的离线支持包,可以在Keil中,自动弹Pack Installer窗口,可以用于在线安装支持库,

在这里插入图片描述

也可以 通过project–manage–pack installer进行在线安装

在这里插入图片描述

在左侧筛选栏选择芯片厂商(如 STMicroelectronics),找到目标系列(如 STM32F2xx),右侧会列出对应的 DFP 版本(如Keil.STM32F2xx_DFP),点击 Install 即可自动下载并安装。

DFPDevice Family Pack(设备家族包) 的缩写。它是一种专门为特定微控制器系列提供支持的软件包,包含设备描述文件、启动代码、闪存算法、外设驱动及示例项目等核心资源,确保 Keil MDK(Microcontroller Development Kit)能够识别并适配目标芯片的硬件特性。

在这里插入图片描述

软件注册

右键Keil图标–以管理员身份运行,打开Keil

然后通过File–License Management

在这里插入图片描述

弹出的页面中复制CID,这里会发现我的版本已经注册了,可以使用到2032年

在这里插入图片描述

复制CID到注册机中,

在这里插入图片描述

把生成的License 复制到前一个图的 New License ID Code中,再单击Add LIC

安装STLINK驱动

把STLink插到电脑上
在这里插入图片描述

查看设备管理器

在这里插入图片描述

我的STLink驱动位置如下

在这里插入图片描述

双击DPinst_amd64.exe

在这里插入图片描述

选择

在这里插入图片描述

单击安装

在这里插入图片描述

安装完成后

在这里插入图片描述

在Segger中有JLink的驱动

在这里插入图片描述

一分钟制作STLink

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

https://mp.weixin.qq.com/s?__biz=MzA5NjQyNjc2NQ==&mid=2452268292&idx=1&sn=138625be0f589bfef8c483d80ae7635d&chksm=861d5a1ca3467bcfb6ad500387a86fd9038fc443f37f1c0cad799513f904ce756ed560f9400d&scene=27

安装USB转串口驱动-CH340

USB转串口工具连接电脑,查看设备管理器,如果出现感叹号,说明没有装驱动

在这里插入图片描述

打开本地的USB转串口CH340驱动

在这里插入图片描述

双击后,直接安装

在这里插入图片描述

安装完成后,会在端口处识别出USB-SERIAL

在这里插入图片描述

拓展

USB-SERIAL(通常称为“USB转串口工具”)是一种硬件转换设备,核心功能是在USB接口串口(UART/RS232/RS485等) 之间建立通信桥梁,实现两种不同接口设备的数据交互。

主要用途
  1. 设备调试与开发
    嵌入式设备(如单片机、PLC、传感器)通常采用串口(UART)作为调试接口,而现代电脑(PC/笔记本)普遍取消了物理串口,仅保留USB接口。通过USB-SERIAL工具,可将电脑的USB信号转换为串口信号,实现对嵌入式设备的程序下载、日志打印、参数配置等操作。

  2. 连接传统串口设备
    一些老式设备(如工业仪表、路由器控制台、POS机)仍依赖串口通信,USB-SERIAL工具可让这些设备与现代电脑或智能设备(如通过USB扩展的嵌入式系统)连接,实现数据采集或控制。

  3. 数据传输扩展
    在物联网或工业场景中,可通过USB-SERIAL将串口设备(如温湿度传感器、RFID读卡器)接入USB主机(如树莓派、工业电脑),扩展数据传输链路。

工作原理

USB-SERIAL的核心是“协议转换”,通过硬件芯片和软件驱动协同实现信号转换,具体分为三个层面:

1. 硬件层面:信号转换

工具内部包含一块USB-to-UART转换芯片(如常见的CH340、PL2303、CP2102等),这是核心部件:

  • 当数据从电脑USB发送到设备时:芯片接收USB总线上的差分信号(符合USB 2.0/3.0协议),将其解码为串口的TTL/RS232电平信号(如高低电平表示0/1),通过串口引脚(TX/RX)发送给目标设备。
  • 当数据从串口设备发送到电脑时:芯片接收串口的电平信号,编码为USB协议要求的数据包格式,通过USB线传输给电脑。

此外,芯片还会处理电平匹配(如将USB的5V/3.3V转换为串口设备所需的3.3V/5V)和时序同步(确保两种接口的波特率、校验位等参数一致)。

2. 软件层面:驱动与虚拟串口

电脑需要安装对应转换芯片的驱动程序,其作用是:

  • 将USB-SERIAL工具识别为“虚拟串口”(如Windows中的COM3、Linux中的/dev/ttyUSB0),让操作系统和应用程序(如串口调试助手、编程软件)将其视为物理串口,无需修改原有串口通信代码。
  • 负责USB协议与串口协议的软件适配(如将USB的批量传输转换为串口的异步通信,处理数据帧拆分与拼接)。
3. 协议层面:数据格式转换

USB和串口的通信协议完全不同:

  • USB采用主从式差分信号,基于数据包传输(包含地址、数据、校验等字段),支持热插拔和多种传输模式(控制、批量、中断、等时)。
  • 串口(以UART为例)采用单端信号,基于帧传输(包含起始位、数据位、校验位、停止位),通信双方需提前约定波特率(如9600、115200)。

转换芯片会自动完成两种协议的格式转换:例如,将USB数据包中的有效数据提取出来,按照串口帧格式封装后发送;反之,将串口接收的帧数据打包成USB数据包,上传给电脑。

总结

USB-SERIAL本质是“协议翻译器”,通过硬件芯片实现电信号和物理层转换,通过驱动程序实现操作系统层面的接口虚拟化,最终让USB设备和串口设备能够“无障碍对话”。它是现代电脑与传统串口设备、嵌入式系统交互的重要工具,在电子开发、工业控制、物联网等领域应用广泛。

2-2新建工程

1.新建文件夹

新建工程的文件夹,

d:\stm32pro\

在这里插入图片描述

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

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

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

在这里插入图片描述

进入

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

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

在这里插入图片描述

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

https://q3.itc.cn/images01/20250314/8df279bec137447da80b9ce550ee747f.jpeg

在这里插入图片描述

用来存放本次工程。

点击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 headerint 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 headerint 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 headerint main(void)
{// 使能GPIOC RCC->APB2ENR = 0X00000010;// 设置GPIOC 推挽与50MHzGPIOC->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
0000200000000000 00000000 00100000 00000000
00       00       20       00
00002000
#include "stm32f10x.h"                  // Device headerint main(void)
{// 使能GPIOC RCC->APB2ENR = 0X00000010;// 设置GPIOC 推挽与50MHzGPIOC->CRH=0X00300000;// 设置灯亮GPIOC->ODR=0X00000000;// 设置灯灭//GPIOC->ODR=0X00002000;while(1){}
}

实现闪烁

#include "stm32f10x.h"                  // Device headerint main(void){RCC->APB2ENR = 0x00000010;
// 设置GPIOC 推挽与50MHzGPIOC->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 推挽与50MHzGPIOC->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_InitStructureGPIO_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中实现:

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

stm32f10x_it.h中会声明该函数:

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

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

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

    #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)控制是否启用,便于开发阶段调试和量产阶段关闭冗余输出。

典型配置示例:
// 启用参数检查(开发阶段用,量产可关闭)
#define USE_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)控制是否启用,便于开发阶段调试和量产阶段关闭冗余输出。

典型配置示例:
// 启用参数检查(开发阶段用,量产可关闭)
#define USE_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中断系统和外设管理的核心框架,确保中断响应的规范性和代码的可维护性。

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


文章转载自:

http://fNQ1QoL8.dqbpf.cn
http://5sLk3jlz.dqbpf.cn
http://maWXydup.dqbpf.cn
http://26eCIggq.dqbpf.cn
http://xgk6mnUe.dqbpf.cn
http://ETX2P0KT.dqbpf.cn
http://RWwWCC14.dqbpf.cn
http://sG2eW0aw.dqbpf.cn
http://PGJE3671.dqbpf.cn
http://54fcvPxz.dqbpf.cn
http://rAeOwREv.dqbpf.cn
http://2e4vU98A.dqbpf.cn
http://YcMQnUQn.dqbpf.cn
http://G9jWXFsr.dqbpf.cn
http://9Us3TN4i.dqbpf.cn
http://07LZ6oiT.dqbpf.cn
http://Wrvp8je2.dqbpf.cn
http://dSljk7qU.dqbpf.cn
http://J0O8bVoR.dqbpf.cn
http://dapGMheZ.dqbpf.cn
http://1s7T2DXH.dqbpf.cn
http://OfUiGCNm.dqbpf.cn
http://aBDxd0uZ.dqbpf.cn
http://mhV4UUMy.dqbpf.cn
http://eT0lqA1Y.dqbpf.cn
http://CqX4s5cF.dqbpf.cn
http://31WHXKjl.dqbpf.cn
http://JyAa9u2i.dqbpf.cn
http://lzpt9Du2.dqbpf.cn
http://BJ8Ep3qJ.dqbpf.cn
http://www.dtcms.com/a/362685.html

相关文章:

  • C语言精选100道编程题(附有图解和源码)
  • 控制系统仿真之PID参数整定的Z-N法(弯曲切线法)(十)
  • K6 html压力测试报告中参数详解以及常见问题解析
  • 算法题打卡力扣第3题:无重复字符的最长子串(mid)
  • 在线拍卖|基于Springboot+vue的在线拍卖管理系统(源码+数据库+文档)
  • F5发布后量子API安全解决方案,以AI驱动全面防护应对量子计算威胁
  • 面阵 vs 线阵相机:怎么选不踩坑?选型公式直接套用
  • HTML第二课:块级元素
  • 【实时Linux实战系列】采用实时Linux构建无人机控制系统
  • Vue基础知识-Vue中v-cloak、v-text、v-html、v-once、v-pre指令详解
  • 【Doris入门】Doris数据表模型:聚合模型(Aggregate Key Model)详解
  • 数论常见公式定理大全
  • C++学习——继承
  • 无线通信网络是互联网边缘的重要组成,同时也是局域联网的主要方式
  • RT-Thread SMP相关问题分析
  • 01-html css
  • 【论文阅读】Jet-Nemotron: 高效语言模型与后神经网络架构搜索
  • 11.《简单的路由重分布基础知识探秘》
  • 解决完美主义的方法是,去追求不完美--辩证法
  • 《Stable Diffusion XL 1.0 实战:AI 绘画从 “能看” 到 “好看” 的升级技巧》
  • Android把源Bitmap中心缩放到固定宽高的尺寸,Kotlin
  • Kaia AMA 全回顾:如何让 Web3 无痕融入2.5 亿用户日常?9 月 7 日中国行揭秘!
  • WPF启动窗体的三种方式
  • 达梦:存储过程实现多个用户之间表的授权
  • 如何在本地环境中搭建 GitLab 服务器
  • 《IC验证必看|SV中Process控制》
  • ffmpeg 安装
  • 添加⽂件--场景⼆
  • JVM1.8与1.9的区别是什么?
  • 实验2-代理模式和观察者模式设计