STM32新手入门教程

Wesley13
• 阅读 1215

文章目录

        • STM32简介
        • STM的选型
        • 编写程序
          • Keil安装
        • 烧写程序
          • USB转串口烧写
          • ST-Link烧写
        • 点亮LED灯
          • GPIO简介
          • GPIO配置
          • GPIO电平输出
          • 程序编写
        • 闪烁LED灯
          • 程序编写
          • 实验结果

STM32简介

简介参考自:小马哥STM32四轴学习平台–DragonFly四轴STM32单片机软件入门级飞控算法课程

单片微型计算机简称单片机(MCU(MicrbControl Unit)),我们自己的个人计算机中,CPU、RAM、ROM、I/O这些都是单独的芯片,然后这些芯片被安装在一个主板上,这样就构成了我们的PC主板,进而组装成电脑,而单片机只是将这所有的集中在了一个芯片上而已。单片机又有8位的如51单片机、16位的如MSP430、32位的如STM32,通常我们说的多少位通常指的是内核(CPU)一次处理的数据宽度。也就是说内核一次处理的位数越多单片机的计算速度就越快,性能也就越强悍。

STM32是意法半导体(ST)推出一款32位的单片机。STM32具有超低的价格、超多的外设、丰富的型号、优异的实时性、极低的开发成本等优势。STM32凭借其产品线的多样化、极高的性价比、简单易用的库开发方式,迅速在众多32位单片机中脱颖而出。

STM32芯片内部可以粗略划分两部分:内核+片上外设。如果与电脑类比,内核与片上外设就如同电脑的CPU与主板、内存、显卡、硬盘的关系。
ARM公司只设计内核不生产芯片,他会将有关内核的技术授权给各半导体厂商例如ST、TI、Atme1、NXP等厂商。这些厂商都是基于这个内核自己设计片上外设如SRAM、ROM、FLASH、USART、GPIO等,然后集成到一个硅片上,这就是我们现在用的芯片。
芯片内部架构见图:

STM32新手入门教程

芯片内部内核和外设分别是两个公司设计的,那他们该怎么联系到一起协同高效的工作呢?答案就是总线,学过计算机组成原理的同学都应该知道计算机五大组成部分运算器、控制器、存储器、输入设备、输出设备他们之间的通信就是通过总线。我们上面也说了单片机就是一个集成在硅片上的计算机,所以他内部的连接关系也是靠总线。
STM32内部一共有11条总线:

STM32新手入门教程

我们知道,在嵌入式开发中,比如51和Arduino,我们写程序烧入芯片就可以实现控制。那么我们写的程序怎么就能控制我们的单片机工作呢或者程序在控制什么东西呢?
那个东西就是寄存器,其实不管我们用库开发还是寄存器开发我们本质上就是在控制寄存器上的每个位的通断,并且这些寄存器都有其特定的功能。换句话说每个外设(如GPI0、USART、I2C、SPI.…)都对应有寄存器来对他控制。

所以STM32可以用寄存器开发也可以用库开发

STM的选型

STM32是ST的所有产品的统称,ST有两大家族STM8和STM32。STM8主要针对于低成本,对主频要求比较低、运算速度要求不是很高的低端市场。STM32主要应用于项目对主频要求较高、运算速度比较快、实时性好的中高端市场。STM32有很多产品大致划分可分为主流MCU、高性能MCU、低功耗MCU。其中主流MCU如STM32F1系列、高性能MCU如STM32F4、STM32F7系列、低功耗MCU如STM32L0系列。并且每个系列产品下面还会根据闪存容量、外设数量、封装大小分为很多种类并且价格也是差别很大。

STM32新手入门教程

STM32型号的说明:以STM32F103RBT6这个型号的芯片为例,该型号的组成为7个部分,其命名规则如下:

1

STM32

STM32代表ARM Cortex-M内核的32位微控制器。

2

F

F代表芯片子系列。

3

103

103代表增强型系列。

4

R

R这一项代表引脚数,其中T代表36脚,C代表48脚,R代表64脚,V代表100脚,Z代表144脚,I代表176脚。

5

B

B这一项代表内嵌Flash容量,其中6代表32K字节Flash,8代表64K字节Flash,B代表128K字节Flash,C代表256K字节Flash,D代表384K字节Flash,E代表512K字节Flash,G代表1M字节Flash。

6

T

T这一项代表封装,其中H代表BGA封装,T代表LQFP封装,U代表VFQFPN封装。

7

6

6这一项代表工作温度范围,其中6代表-40——85℃,7代表-40——105℃。

我手上是一款德飞莱尼莫M3S V2.3开发板

STM32新手入门教程

用的是STM32F103ZET6,芯片说明书如下:

STM32新手入门教程

之后还购置了一款最小系统板,搭载STM32103C8T6

STM32新手入门教程

编写程序

先下载keil软件(官网下载MDK5的安装包):

STM32新手入门教程

注意:

STM32新手入门教程

所以要开发C51就得下载C51的Keil要开发STM32就得下载MDK-Arm

如果要设置C51和STM32的开发环境,一般需要准备如下文件:

STM32新手入门教程

资源链接: 百度网盘密码:d1cs

安装可以参考这个:STM32开发环境搭建(Keil)

MDK5安装破解以及安装stm32与C51支持包(附安装包)

其中pack文件是STM32的芯片包,可以在安装完keil后下载(KEIL公司的软件包托管网站)双击安装,也可以去keil的pack Installer安装。

Keil安装

选择安装路径时包括选择MDK核心组件(Core)的安装路径和外设包(Pack)的安装路径,一般只用选择 Core 的安装路径,Pack 的路径会自动设置为 Core 路径下的ARM/PACK

安装完成后,会自动弹出 Pack Installer 界面,如果没有的话可以打开安装好的 Keil uVision5 软件,在工具栏上找到 Pack Installer 的图标,然后点击进入:

STM32新手入门教程

由于我们使用的STM32型号为 STM32F103ZET6,还需要安装开发所需要的器件支持包(Device Family Pack, i.e. DFP),所以展开STM系列产品的菜单栏,找到芯片设备,点击左边Packs中的三个组件,Pack Installer 会自动从网上下载最新版本的组件,下载进度在 Pack Installer 底部状态栏显示。(由于我已经通过双击安装好了,所以是Up to date)

STM32新手入门教程

直接用Keil5新建工程(只能用Keil5快速新建工程)。

Project-> New,之后选择自己的开发板芯片:

STM32新手入门教程

确定之后又跳到运行环境的界面:

STM32新手入门教程

必选CMSIS的Core还有Device的Startup

如果要连接外设必须勾选外设的时钟RCC,一般再勾选上FrameworkGPIO、和USART串口。

点击OK确定创建项目。项目创建完成后就是这样的:

STM32新手入门教程

可以看到已经包含了我们选择的库文件。如果还需要什么可以再点击图上的按钮再次打开运行环境配置页面。

STM32新手入门教程

之后可以管理一下项目目录,自定义一下名字。

STM32新手入门教程

然后添加main.c文件:

STM32新手入门教程

之后就可以在main文件中写代码了。

STM32新手入门教程

写完可以编译一下,如果输出正确就表示环境配置没问题。

STM32新手入门教程

这里默认是不会创建Hex文件的,所以还需要进入设置里面去设置一下。

STM32新手入门教程

之后再编译就可以在Objects文件夹下面看到Hex文件。

STM32新手入门教程

烧写程序

  1. USB转串口烧写

参考这个:如何使用串口来给STM32下载程序

不过具体还得看官方的开发板说明书。

  1. ST-Link烧写

    STM32 ST-LINK Utility介绍、下载、安装、使用方法

STLink 上 LED 指示灯用于提示当前的工作状态,具体情况如下:

  • LED 闪烁红色:STLink 已经连接至计算机。
  • LED 保持红色:计算机已经成功与 STLink 建立通信连接。
  • LED 交替闪烁红色绿色:数据正在传输。
  • LED 保持绿色:最后一次通信是成功的。
  • LED 为橘黄色:最后一次通信失败。

说白了就是3步:

1.连接芯片:

Tarage -> connect或直接点击连接快捷按钮:

STM32新手入门教程

2.打开程序

打开hex文件可以从菜单栏(File -> Open File)打开,也可以直接讲hex文件拖动到FLASH区域:

STM32新手入门教程

3.下载程序

点击“下载”(可以Taraget -> Program,也可以直接点击下载快捷按钮,如下图):

STM32新手入门教程

弹出信息确认窗口,如hex文件路径、验证方式等,确认信息无误后点击“Start”开始下载程序。

STM32新手入门教程

出现“Verification…OK”,说明下载成功。

点亮LED灯

GPIO简介

参考自:【STM32开发】STM32 GPIO配置

GPI0是通用输入输出端口的简称,从名字上也可看出GPIO最基本的功能就输入和输出。它也是芯片内部与外部电路连接的唯一的接口,换句话说只要我们使用片上外设几乎都会与GPIO打交道。
GPI0基本功能是输入和输出,但是STM32本身就是一个很复杂的系统,内部外设繁多,那么GPIO的基本功能是肯定满足不了这么多外设的需求,芯片厂商为了解决此问题,将GPI0分为八种模式(输入4种+输出4种)。八种模式分别为:

  1. 输入浮空 GPIO_Mode_IN_FLOATING

  2. 输入上拉 GPIO_Mode_IPU

  3. 输入下拉 GPIO_Mode_IPD

  4. 模拟输入 GPIO_Mode_AIN

  5. 具有上拉或下拉功能的开漏输出 GPIO_Mode_Out_OD

  6. 具有上拉或下拉功能的推挽输出 GPIO_Mode_Out_PP

  7. 具有上拉或下拉功能的复用功能推挽 GPIO_Mode_AF_PP

  8. 具有上拉或下拉功能的复用功能开漏 GPIO_Mode_AF_OD

我的STM32开发板板载两个LED小灯,电路图如下:

STM32新手入门教程

GPIO配置

由于STM32的GPIO工作模式有8种,所以在GPIO输出之前要先对要操作的GPIO进行配置:

  • 定义GPIO的初始化结构体类型

  • 使能GPIO的时钟

  • 配置GPIO的引脚

  • 配置GPIO口的输出类型为推挽

  • 配置GPIO口的输出速度

  • 初始化GPIO(初始化相应的寄存器)

    GPIO_InitTypeDef GPIO_InitStructure; // 定义结构体变量 //打开PB口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开PE口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //PB5,PE5引脚设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //设置输出速率50MHz GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //推挽输出模式 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //初始化外设GPIOx寄存器 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure);

解释:

1.定义GPIO的初始化类型结构体:

GPIO_InitTypeDef GPIO_InitStructure;

此结构体的定义是在stm32f10x_gpio.h文件中,其中包括3个成员。

typedef struct
{
   
                       
  uint16_t GPIO_Pin;       
  GPIOSpeed_TypeDef GPIO_Speed;  
  GPIOMode_TypeDef GPIO_Mode;   
}GPIO_InitTypeDef;

(1)uint16_t GPIO_Pin;来指定GPIO的哪个或哪些引脚,取值参见stm32f10x_gpio.h头文件的宏定义。

(2)GPIOSpeed_TypeDef GPIO_Speed;GPIO的速度配置,此项的取值参见stm32f10x_gpio.h头文件GPIOSpeed_TypeDef枚举的定义,其中对应3个速度:10MHz、2MHz、50MHz;

(3)GPIOMode_TypeDef GPIO_Mode;为GPIO的工作模式配置,其取值参见stm32f10x_gpio头文件GPIOMode_TypeDef枚举的定义,即GPIO的8种工作模式。

2.使能GPIO时钟

ARM与C51单片机不同的是,不用外设的时候,如IO口、ADC、定时器等等,都是禁止时钟的,以达到节能的目的,只有要用到的外设,才开启它的时钟。

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

此函数是在stm32f10x_rcc.c文件中定义的。其中第一个参数指要打开哪一组GPIO的时钟,取值参见stm32f10x_rcc.h文件中的宏定义,第二个参数为打开或关闭使能,取值参见stm32f10x.h文件中的定义,其中ENABLE代表开启使能,DISABLE代表关闭使能。

3.设置GPIO_InitTypeDef结构体三个成员的值

这里包括引脚、速度和工作模式,取值可参考第一部分。

4.初始化GPIO

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef*  GPIO_InitStruct);

函数配置GPIO,此函数是在stm32f10x_gpio.c文件中定义的,其中第一个参数代表要配置哪组GPIO,取值参见stm32f10x.h文件中的定义,第二个参数是第1步定义的GPIO的初始化类型结构体。

GPIO电平输出

官方让GPIO输出高低电平的函数:

GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

函数就是置位GPIO,即让相应的GPIO输出高电平;

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

函数是让GPIO复位的,即让相应的GPIO输出低电平。

程序编写
# include "stm32f10x.h"

#define LED3_OFF GPIO_SetBits(GPIOB,GPIO_Pin_5)
#define LED3_ON GPIO_ResetBits(GPIOB,GPIO_Pin_5)

void LED_Init(void)
{
   
                       
    GPIO_InitTypeDef GPIO_InitStructure;  // 定义结构体变量
    //打开PB口时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    //PB5引脚设置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    //端口速度
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //端口模式,此为输出推挽模式
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    //初始化对应的端口
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}
int main()
{
   
                       
    LED_Init();
    while(1)
    {
   
                       
        LED3_ON;
    }
}

闪烁LED灯

这个实验室做的两个led流水灯。

程序编写

首先新建一个文件夹MY

在该文件夹下新建一个led.h头文件:

#ifndef __LED_H
#define __LED_H

#include "stm32f10x.h"

#define LED2_OFF GPIO_SetBits(GPIOE,GPIO_Pin_5)
#define LED2_ON GPIO_ResetBits(GPIOE,GPIO_Pin_5)
#define LED2_REV GPIO_WriteBit(GPIOE, GPIO_Pin_5,(BitAction)(1-(GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_5))))

#define LED3_OFF GPIO_SetBits(GPIOB,GPIO_Pin_5)
#define LED3_ON GPIO_ResetBits(GPIOB,GPIO_Pin_5)
#define LED3_REV GPIO_WriteBit(GPIOB, GPIO_Pin_5,(BitAction)(1-(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_5))))

void LED_Init(void);

#endif

之后新建一个led.c文件:

#include "led.h"

void LED_Init(void)
{
   
                       
    GPIO_InitTypeDef GPIO_InitStructure;  // 定义结构体变量
    //打开PB口时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    //打开PE口时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
    //PB5,PE5引脚设置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    //端口速度
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    //端口模式,此为输出推挽模式
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    //初始化对应的端口
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_Init(GPIOE, &GPIO_InitStructure);
}

最后编写main文件:

# include "stm32f10x.h"
# include "led.h"

int main()
{
   
                       
    uint32_t i; 
    LED_Init(); //初始化LED

    LED2_ON;
    LED3_OFF;
    for(i=0; i<0xffffff; i++); //for循环不精确延时
    while(1)
    {
   
                       
        for(i=0; i<0xfffff; i++); //for循环不精确延时
        LED2_REV;//LED2取反
        LED3_REV;//LED3取反
    }
}

结构目录如图:

STM32新手入门教程

.h文件默认是不显示的。编译通过后,在左侧的.C文件上会出现一个“+”号,点开就是该C文件使用到的h文件。

实验结果

STM32新手入门教程

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这