文章目录
STM32简介
简介参考自:小马哥STM32四轴学习平台–DragonFly四轴STM32单片机软件入门级飞控算法课程git
单片微型计算机简称单片机(MCU(MicrbControl Unit)),咱们本身的我的计算机中,CPU、RAM、ROM、I/O这些都是单独的芯片,而后这些芯片被安装在一个主板上,这样就构成了咱们的PC主板,进而组装成电脑,而单片机只是将这全部的集中在了一个芯片上而已。单片机又有8位的如51单片机、16位的如MSP430、32位的如STM32,一般咱们说的多少位一般指的是内核(CPU)一次处理的数据宽度。也就是说内核一次处理的位数越多单片机的计算速度就越快,性能也就越强悍。github
STM32是意法半导体(ST)推出一款32位的单片机。STM32具备超低的价格、超多的外设、丰富的型号、优异的实时性、极低的开发成本等优点。STM32凭借其产品线的多样化、极高的性价比、简单易用的库开发方式,迅速在众多32位单片机中脱颖而出。算法
STM32芯片内部能够粗略划分两部分:内核+片上外设。若是与电脑类比,内核与片上外设就如同电脑的CPU与主板、内存、显卡、硬盘的关系。
ARM公司只设计内核不生产芯片,他会将有关内核的技术受权给各半导体厂商例如ST、TI、Atme一、NXP等厂商。这些厂商都是基于这个内核本身设计片上外设如SRAM、ROM、FLASH、USART、GPIO等,而后集成到一个硅片上,这就是咱们如今用的芯片。
芯片内部架构见图:
微信
芯片内部内核和外设分别是两个公司设计的,那他们该怎么联系到一块儿协同高效的工做呢?答案就是总线,学过计算机组成原理的同窗都应该知道计算机五大组成部分运算器、控制器、存储器、输入设备、输出设备他们之间的通讯就是经过总线。咱们上面也说了单片机就是一个集成在硅片上的计算机,因此他内部的链接关系也是靠总线。
STM32内部一共有11条总线:
架构

咱们知道,在嵌入式开发中,好比51和Arduino,咱们写程序烧入芯片就能够实现控制。那么咱们写的程序怎么就能控制咱们的单片机工做呢或者程序在控制什么东西呢?
那个东西就是寄存器,其实无论咱们用库开发仍是寄存器开发咱们本质上就是在控制寄存器上的每一个位的通断,而且这些寄存器都有其特定的功能。换句话说每一个外设(如GPI0、USART、I2C、SPI.…)都对应有寄存器来对他控制。
ide
因此STM32能够用寄存器开发也能够用库开发。函数
STM的选型
STM32是ST的全部产品的统称,ST有两你们族STM8和STM32。STM8主要针对于低成本,对主频要求比较低、运算速度要求不是很高的低端市场。STM32主要应用于项目对主频要求较高、运算速度比较快、实时性好的中高端市场。STM32有不少产品大体划分可分为主流MCU、高性能MCU、低功耗MCU。其中主流MCU如STM32F1系列、高性能MCU如STM32F四、STM32F7系列、低功耗MCU如STM32L0系列。而且每一个系列产品下面还会根据闪存容量、外设数量、封装大小分为不少种类而且价格也是差异很大。工具

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开发板。学习
用的是STM32F103ZET6,芯片说明书以下:

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

编写程序
先下载keil软件(官网下载MDK5的安装包):
注意:

因此要开发C51就得下载C51的Keil,要开发STM32就得下载MDK-Arm。
若是要设置C51和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型号为 STM32F103ZET6,还须要安装开发所须要的器件支持包(Device Family Pack, i.e. DFP),因此展开STM系列产品的菜单栏,找到芯片设备,点击左边Packs中的三个组件,Pack Installer 会自动从网上下载最新版本的组件,下载进度在 Pack Installer 底部状态栏显示。(因为我已经经过双击安装好了,因此是Up to date)
直接用Keil5新建工程(只能用Keil5快速新建工程)。
Project-> New,以后选择本身的开发板芯片:

肯定以后又跳到运行环境的界面:

必选CMSIS的Core还有Device的Startup。
若是要链接外设必须勾选外设的时钟RCC,通常再勾选上Framework、GPIO、和USART串口。
点击OK肯定建立项目。项目建立完成后就是这样的:

能够看到已经包含了咱们选择的库文件。若是还须要什么能够再点击图上的按钮再次打开运行环境配置页面。

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

而后添加main.c文件:

以后就能够在main文件中写代码了。

写完能够编译一下,若是输出正确就表示环境配置没问题。

这里默认是不会建立Hex文件的,因此还须要进入设置里面去设置一下。

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

烧写程序
参考这个:如何使用串口来给STM32下载程序
不过具体还得看官方的开发板说明书。
STLink 上 LED 指示灯用于提示当前的工做状态,具体状况以下:
- LED 闪烁红色:STLink 已经链接至计算机。
- LED 保持红色:计算机已经成功与 STLink 创建通讯链接。
- LED 交替闪烁红色和绿色:数据正在传输。
- LED 保持绿色:最后一次通讯是成功的。
- LED 为橘黄色:最后一次通讯失败。
说白了就是3步:
1.链接芯片:
Tarage -> connect或直接点击链接快捷按钮:

2.打开程序
打开hex文件能够从菜单栏(File -> Open File)打开,也能够直接讲hex文件拖动到FLASH区域:

3.下载程序
点击“下载”(能够Taraget -> Program,也能够直接点击下载快捷按钮,以下图):

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

出现“Verification…OK”,说明下载成功。
点亮LED灯
GPIO简介
GPI0是通用输入输出端口的简称,从名字上也可看出GPIO最基本的功能就输入和输出。它也是芯片内部与外部电路链接的惟一的接口,换句话说只要咱们使用片上外设几乎都会与GPIO打交道。
GPI0基本功能是输入和输出,可是STM32自己就是一个很复杂的系统,内部外设繁多,那么GPIO的基本功能是确定知足不了这么多外设的需求,芯片厂商为了解决此问题,将GPI0分为八种模式(输入4种+输出4种)。八种模式分别为:
-
输入浮空 GPIO_Mode_IN_FLOATING
-
输入上拉 GPIO_Mode_IPU
-
输入下拉 GPIO_Mode_IPD
-
模拟输入 GPIO_Mode_AIN
-
具备上拉或下拉功能的开漏输出 GPIO_Mode_Out_OD
-
具备上拉或下拉功能的推挽输出 GPIO_Mode_Out_PP
-
具备上拉或下拉功能的复用功能推挽 GPIO_Mode_AF_PP
-
具备上拉或下拉功能的复用功能开漏 GPIO_Mode_AF_OD
个人STM32开发板板载两个LED小灯,电路图以下:

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取反 } }
结构目录如图:

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