STM32入门教程:新建工程

news2024/11/24 3:16:58

本博文是基于建立好STM32的keil5软件后建立工程,如果还没下载软件建议先下载好该软件,在

B站江科大32教学有,并把相关文件下好。

STM32的开发方式有:基于寄存器的方式,基于标准库也就是库函数的方式,基于HAL库的方式,基于寄存器的方式与使用51单片机一样,是程序直接配置寄存器。来达到我们想要的功能,最底层,也最高效,但是由于STM32的结构复杂,寄存器太多,所以基于寄存器的方式不推荐。

基于库函数的方式是使用ST官方提供封装好的函数,通过调用这些函数来间接配置寄存器,由于ST对寄存器封装的比较好,所以这种方式既能满足对寄存器的配置,对开发人员也比较友好,提高了开发效率。所以我们大多都是使用这种方式。

基于HAL库的方式可以用图形化界面快速配置STM32,这个适合快速上手STM32的情况,但是这种方式隐藏了底层逻辑,如果你对STM32不熟悉,基本只能停留在很浅的水平,所以这种方式不太推荐,建议了解标准库这种方式后,再去好好了解一下这种方式,毕竟HAL库是非常方便的。

使用库函数的方式,我们需要准备一个STM32库函数的压缩包。

打开下载好的文件夹 打开固件库:有如下文件

1.

 这个文件里面就是库函数的文件了,我们之后建立工程会用到

2. 

project是官方提供的·工程示例和模版,以后使用库函数可以参考一下

3. 

 Utilities是STM32官方评估板的相关例程,

这个评估板就是官方用STM32做的一个小电路板,用来评测STM32的。

所以这个文件夹里面存的就是这个小电路板的测评程序。

4. 

 一个是库函数的发布文档,一个是使用手册。

使用手册有教如何使用这个库函数的。

好,我们接下来就正式开始新建一个基于标准库的工程。

我们先先建一个存放工程的文件夹,这里我在桌面建立了一个文件夹。

打开Keil5,选择如下:

在自己建立的文件夹中再新建一个文件: 

 点击上图文件夹2-2STM工程模版1,起一个工程的名字,一般通用project,点击OK,

进入选择芯片环节。(前提是已经安装好32的软件)选择如下芯片

 选择自己要操作的芯片,我这里是

点击ok,出现如下界面:这里弹出的是keil软件的一个新建工程小助手,这个可以帮助我们快速新建工程,我们暂时不用这个小助手,可以叉掉。 

 下面工程就是建好了,但是这里工程文件空空如也,这个工程还是不能直接用的。我们需要给他添加一些工程的必要文件,

打开上面 固件库的文件夹,打开

 依次打开如下文件:

最后见到如下界面:这些就是STM32的启动文件,STM32的程序就是从启动文件开始执行的, 

 我们把这些文件全部复制下来,回到工程模版文件夹里,也就是我之前建立工程的文件夹中。如下图,如果把启动文件全部复制在里面,会显得太乱了,

我们在这里再新建一个文件夹,名字自己起:我这里新建一个Start文件夹,把刚刚粘贴的文件复制在这个文件夹里面。

 接着回到   固件库里面STM32F10x这个文件夹。即如下图所示。

会看到如下界面:有stm32f10x.h和两个system开头的文件。

 这个stm32f10x.h,就是STM32的外设寄存器描述文件。他的作用与51单片机头文件REGX52.h一样,是用来描述STM32有哪些寄存器和他对应的地址的,两个system文件是用来配置时钟的,STM32主频72Mhz,就是system文件里的函数配置的。

所以我们把这三个文件复制下来,粘贴到Start这个文件夹里面

接下来,因为这个STM32是内核和内核外围的设备组成的,而且这个内核的寄存器描述和外围设备的描述文件不是在一起的,所以我们还需要添加一个内核寄存器的描述文件。

打开如下文件夹:

 看到如下界面:

这两个cm3文件就是内核的寄存器描述。当然,他还带了一些内核的配置函数所以多了个.c文件,我们把这两个一起复制下来。粘贴到Start文件夹下。

start文件夹有如下文件

到此,我们工程的必要文件就复制完成了。

回到keil5软件。 接着如下操作,把Source Group 1 改名字为Start,单击一下就好了

点击如下操作:右键点击Start. 

 

 选择我们之前建好的Start文件,

 我们首先添加一下启动文件,这个启动文件有很多分类,我们只能添加其中一种。

我们所用的型号需要选择这个后缀为md.s的启动文件,启动文件如何选择,后面我会讲、

然后把带有文件.c和.h文件都添加进来,下图是所要的文件总和。

 好,到这里,我们Start文件夹里面的文件就添加好了。

这里的文件都是STM32里最基本的文件,是不需要我们修改的,我们添加进来即可。

我们看上图文件图标上带了个小钥匙,这个意思是他只是个只读文件。不能修改的。

最后我们还需要在工程选项里添加上这个文件夹的头文件路径

要不然软件是找不到.h文件的。按如下操作进行:

选择Start文件夹,点击OK,后会出现如下图所示

点击ok,这样我们就把这个文件夹的头文件路径添加进来了。

最后,在建立的文件夹里再先建一个User文件,用来存放我们的main函数

 再继续如下操作。右键Target,

把新建的文件夹改名为User 

到这里,这个工程目前还没有添加STM32的库函数,所以还是基于寄存器开发的工程。 

如果你想用寄存器开发STM32,那工程建到这就可以了,

下面用寄存器完成点灯操作。在操作之前,可以完成如下设置。

 

打开STM32参考手册,首先是RCC的一个寄存器,来使能GPIOC的时钟 ,GPIO都是APB2的外设,所以在这个APB2外设时钟使能寄存器RCC_APB2ENR里面配置

 如图所示,这一位就是使能GPIOC的时钟的,

 接下来我们找到端口配置高寄存器GPIOx_CRH,这个x可以是A到E的任意一个字母,

然后下图的CNF13和MODE13就是用来配置13号口的,

这个CNF我们需要配置为通用推挽输出模式,

 MODE要配置为输出模式,最大速度可以给50MHZ

 接下来我们就可以给PC13口输出数据了。找到下图输出寄存器。

 因为灯是低电平点亮的,所以我们给ODR全为0就是亮。

给ODR 0x00002000就是灭。下图所示代码,就是点亮灯,

下图所示代码,灯就灭了。 

上面就是配置寄存器的方式进行点灯操作。可以看出这种方式需要不断查手册来了解每一个寄存器的每一位是用来干啥的,而且这个操作方式也有一个弊端,就是我们除了PC13之外的位都配置了0,这样就会影响到其他端口的原有配置,如果我们要做到只配置PC13而不影响其他位,需要&=和|=的操作,所以寄存器的操作方式,代码简单,不太方便操作。

接下来我们位这个工添加库函数,看看库函数与寄存器的操作方式有哪些区别。

新建一个文件夹,叫做library,用来存放库函数。

 打开下列文件夹

 出现

misc.c就是内核的库函数,其他的是内核外的外设库函数,CTRL+A全选

粘贴到新建的文件夹Library中

打开如下图文件,

下图是库函数的头文件:全选,复制,粘贴到新建的文件夹Library中 

同理,在keil5中新建一个组,改名字为Library,然后把刚刚所有 文件放进来。如图所示

 

 但是对于这个库函数来说,现在还不能使用,我们需要再添加一个文件。

打开如图文件夹

 把箭头指向的三个文件复制下来粘贴到User的文件夹里面

 在keil5里面把三个文件添加进来。

最后需要一个宏定义,我们可以右键如图的头文件,打开文件 

找到下图所示,在上面的文件最下面,这是一个条件编译。意思是如果你定义了USE_STDPERIPH_DRIVER这个字符串,下面这个#include "stm32f10x_conf.h"才有效 

我们复制 USE_STDPERIPH_DRIVER这个字符串,点击魔术棒,在下面图示粘贴。

这样才能包含标准外设库,也就是库函数。 

按之前的操作,把User和Library路径也添加上

这样,基于库函数的工程所有操作就完成了,

下面我们用库函数实现点灯操作。

库函数 也是间接配置寄存器,所以操作步骤差不多。

首先是使能时钟,那库函数就有这样一个函数来开启时钟

RCC_APB1PeriphClockCmd()这个函数有两个提示。第一个是选择外设,第二个是选择新的状态。

外设,状态选择下图所示, 

GPIO_Init()也有两个参数,一个是选择哪个GPIO,第二个是参数的结构体。

第一个是GPIOx,其中x可以是A到G,来选择你要配置哪个GPIO,

我们是PC13口的LED,所以我们第一个参数就写GPIOC,

第二个参数是一个GPIO_InitTypeDef的结构体,我们需要先定义一个结构体

我们先把结构体的类型写上,先给结构体起一个名字,官方建议起GPIO_InitStructure

然后我们用.来引出结构体的参数,可以看到这个结构体有三个参数,分别是GPIO模式,GPIO端口,GPIO速度,

我们转到GPIOmode的定义,

 右边介绍说,这个参数可以是GPIOMode_TypeDef里面的一个值。

我们选中这个GPIOMode_TypeDef字符,按一下Ctrl+F,搜索一下定义的位置。

可以看出,这是个枚举,GPIOMode就是这里的其中一个值。 

然后我们选择out-pp,复制,这一个就是通用推挽输出。 

同理,我们转到GPIO_pin的定义,这时出现下面这个框,这是说他定义有很多个,

我们选择下图所示,跳转。

 下图可知,它说,这个参数在GPIO_pins_define里面定义了

 同理,选择GPIO_pins_define,按一下Ctrl+F,搜索一下定义的位置。可以看到下图宏定义列表

 我们选择GPIO_pin_13,复制。

最后一个同理,找到他最原始的定义,复制,最后是下图的代码所示。

OK,结构体变量就有了,我们就可以填这个GPIO_Init 第二个参数了

这里说明了,第二个参数是一个指向结构体的指针。所以我们需要传递结构体的地址。

&GPIO_InitStructure 就是结构体的地址,

上面就是GPIO模式配置就完成了。

这个配置的操作方式看上去十分难理解,但是STM32的这种方式都是固定的, 大家多打几次就会用了,

最后设置高低电平来进行点灯。

GPIO_SetBits这个函数就可以把指定端口设置为高电平。

    GPIO_SetBits(GPIOC,GPIO_Pin_13);这样就可以把PC13号口设置为高电平。

置低电平也有函数,GPIO_ResetBits

GPIO_ResetBits(GPIOC,GPIO_Pin_13);这样就可以把PC13号口设置为低电平。

OK,上面就是使用库函数的基本操作了,

至于STM32 GPIO口的结构,结构体和库函数的操作那些,下一篇博客会详细介绍。

下面是一些注意事项:

首先是新建工程里的启动文件选择,我们新建工程第一个加的是启动文件。

这个启动文件有很多类型。至于选择哪一个,我们要根据芯片型号来选择。

下图是STM32F1系列中的型号分类,其中根据flash的大小,分为下图所示

最下面CL不是根据flash大小来分。根据不同型号,再根据flash大小,选择启动文件。

总结一下先建工程的步骤:

 工程的架构:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1457654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案

项目场景 有时候,遇到数据库重复数据,需要将数据进行分组,并取出其中一条来展示,这时就需要用到group by语句。 但是,如果mysql是高版本,当执行group by时,select的字段不属于group by的字段的…

NLP_BERT与GPT争锋

文章目录 介绍小结 介绍 在开始训练GPT之前,我们先比较一下BERT和 GPT 这两种基于 Transformer 的预训练模型结构,找出它们的异同。 Transformer架构被提出后不久,一大批基于这个架构的预训练模型就如雨后春笋般地出现了。其中最重要、影响…

【PHP】web服务器支持PHP_环境配置

一、PHP运行目前为止主要有4方式 (1)以模块加载的方式运行,初学者可能不容易理解,其实就是将PHP集成到Apache服务器, 以同一个进程运行。 (2)以CGI的方式运行,CGI英文叫…

【MATLAB】BiGRU神经网络回归预测算法

有意向获取代码,请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 BiGRU神经网络回归预测算法是一种基于双向门控循环单元(GRU)的多变量时间序列预测方法。该方法结合了双向模型和门控机制,旨在有效地捕捉时间序列数据中…

两个发散级数的和是否发散?

1、两个发散级数的和可能是收敛的也可能是发散的。 例子: 发散级数 ∑ 1 n \sum\frac{1}{n} ∑n1​和发散级数 ∑ ( 1 n 2 − 1 n ) \sum(\frac{1}{n^{2}}-\frac{1}{n}) ∑(n21​−n1​)的和是收敛级数; 发散级数∑(1/n) 和发散级数 ∑(1/n1/n) 的和是…

HarmonyOS 鸿蒙应用开发(十一、面向鸿蒙开发的JavaScript基础)

ArkTS 是HarmonyOS(鸿蒙操作系统)原生应用开发的首选语言。它是用于构建用户界面的一种TypeScript方言,扩展了TypeScript以适应HarmonyOS生态系统的UI开发需求。ArkTS 融合了TypeScript的静态类型系统和现代UI框架的设计理念,为开…

Redis 缓存(Cache)

什么是缓存 缓存(cache)是计算机中的一个经典的概念在很多场景中都会涉及到。 核心思路就是把一些常用的数据放到触手可及(访问速度更快)的地方,方便随时读取。 这里所说的“触手可及”是个相对的概念 我们知道,对于硬件的访问速度来说,通常…

通过VSCode开发Python项目

一、插件准备 Python 插件,必须 autoDocstring 生成注释,和Pycharm一样输入三个引号"""会生产注释结构 Todo Tree 高亮显示 TODO/FIXME 二、python相关设置 一)设置python环境 按"F1"打开命令面板(…

19. 【Linux教程】nano 编辑器

前面小节介绍了如何使用 vim 编辑器,相比于 vim 编辑器,nano 编辑器就比较简单了。nano 是 UNIX 系统中的一个文本编辑器,大部分 Linux 发行版本默认都安装了 nano 文本编辑器。 和 vim 编辑器相比,nano 编辑器就没有那么强大&am…

centos7 arm服务器编译安装onnxruntime-gpu

前言 ONNX Runtime是适用于Linux,Windows和Mac上ONNX格式的机器学习模型的高性能推理引擎,但在arm服务器上,onnxruntime只有CPU版的,GPU版的没有,因此需要自行去编译GPU版本的才可以。 环境准备 1、python3.8 2、cmake:2.26.0版本以上,可以直接下载aarch64版本的进行…

LeetCode42.接雨水(单调栈)

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 : 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,…

​中国手游发行商收入TOP30!

SensorTower 数据 2024年1月中国手游发行商,全球多款游戏在收入和用户增长方面取得的显著成绩。 1. 中国手游发行商全球表现:2024年1月,共有38个中国厂商入围全球手游发行商收入榜TOP100,合计收入达到19.6亿美元,占榜单…

PDF控件Spire.PDF for .NET【安全】演示:如何在 PDF 中添加签名字段

Spire.PDF for .NET 是一款独立 PDF 控件,用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 Spire.PDF 类库,开发人员可以新建一个 PDF 文档或者对现有的 PDF 文档进行处理,且无需安装 Adobe Acrobat。 E-iceblue 功能类库Spire 系列文档处…

mysql mgr集群部署

一、前言 mysql mgr集群是为了实现mysql高可用,分为单主集群和多主集群,单主集群只有一个主节点可写,节点发生故障时,自动进行主从的故障切换,多主集群所有节点都可写,当节点发生故障时,将故障节…

【RPG Maker MV 仿新仙剑 战斗场景UI (二)】

RPG Maker MV 仿新仙剑 战斗场景UI 二 战斗指令菜单原仙剑战斗指令图RMMV战斗指令对应代码战斗指令菜单代码效果 战斗指令菜单 原仙剑战斗指令菜单是使用方向键控制,同时按照使用情况正好对应四个指令和四个方向,同时没有选中的菜单用黑色透明图片覆盖&…

层级关联,审批人功能

一个需求要求选择一级&#xff0c;下方展示一级的效果 后端给了审批人数据&#xff0c;但是数据需要单独处理 <template><div class"box"><el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"…

【鸿蒙系统学习笔记】ArkTS开发语言

一、背景 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 二、基本语法 2.1、基本语法介绍 ArkTS的基本组成&#xff0c;资料来自…

【洛谷题解】P8627 [蓝桥杯 2015 省 A] 饮料换购

题目链接&#xff1a;[蓝桥杯 2015 省 A] 饮料换购 - 洛谷 题目难度&#xff1a;普及- 涉及知识点&#xff1a;换购 题意&#xff1a; 分析&#xff1a;一直换购直至瓶盖数<3为只 AC代码&#xff1a; #include<bits/stdc.h> using namespace std; int main() {i…

极其抽象的SpringSecurity理解

原始&#xff1a;A → B Security&#xff1a;A → S → B 太抽象了&#xff0c;看不懂啊T_T 抽象故事 故事大概&#xff1a;C是一个大区&#xff0c;拥有巨大的火力&#xff08;C准备联合B吞并掉A&#xff09;&#xff0c;A得到了这个消息&#xff0c;…

java:Java中的逻辑控制

顺序结构 在Java中&#xff0c;顺序结构是指代码按照从上到下的顺序依次执行。以下是一个简单的Java程序示例&#xff0c;展示了顺序结构的使用&#xff1a; public class SequenceStructureExample {public static void main(String[] args) {// 声明和初始化变量int num1 10…