第01章 STM32简介及开发环境搭建
01 STM32简介
1.1 STM32F103C8T6
系列:主流系列STM32F1
内核:ARM Cortex-M3
主频:72MHz
RAM:20K(SRAM)
ROM:64K(Flash)
供电:2.0~3.6V(标准3.3V)
51单片机是5V供电。USB输出的电压也是5V供电,不能直接给STM32供电,如果是5V电压,需要加一个稳压芯片,把电压降到3.3V,再给STM32供电。
封装:LQFP48,如下图所示。
1.2 STM32F1系列片上资源/外设
英文缩写 |
名称 |
英文缩写 |
名称 |
NVIC |
嵌套向量中断控制器 |
CAN |
CAN通信 |
SysTick |
系统滴答定时器 |
USB |
USB通信 |
RCC |
复位和时钟控制 |
RTC |
实时时钟 |
GPIO |
通用IO口 |
CRC |
CRC校验 |
AFIO |
复用IO口 |
PWR |
电源控制 |
EXTI |
外部中断 |
BKP |
备份寄存器 |
TIM |
定时器 |
IWDG |
独立看门狗 |
ADC |
模数转换器 |
WWDG |
窗口看门狗 |
DMA |
直接内存访问 |
DAC |
数模转换器 |
USART |
同步/异步串口通信 |
SDIO |
SD卡接口 |
I2C |
I2C通信 |
FSMC |
可变静态存储控制器 |
SPI |
SPI通信 |
USB OTG |
USB主机接口 |
NVIC/SysTick是位于Cortex-M3内核里面的外设,剩下的都是内核外的外设。
NVIC(嵌套向量中断控制器):内核里面用于管理中断的设备,比如配置中断优先级这些东西。
SysTick(系统滴答定时器):内核里面的一个定时器,主要用来给操作系统提供定时服务的。STM32是可以加入操作系统的,比如FreeRTOS、UCOS等。如果使用了这些操作系统,就需要SysTick提供定时来进行任务切换的功能。可以用这个定时器来完成Delay函数的功能。
RCC(复位和时钟控制):对系统的时钟进行配置,使能各模块的时钟。在STM32中,其它的外设在上电的情况下默认是没有时钟的,不给时钟的情况下,操作外设是无效的,外设也不会工作,这样的目的是降低功耗。所以在操作外设之前,必须要先使能它的时钟,这就需要我们用RCC来完成时钟的使能。
GPIO(通用IO口):通用IO口,可以用GPIO来点灯,读取按键等。
AFIO(复用IO口):完成复用端口的重定义,还有中断端口的配置。
EXTI(外部中断):外部中断,配置好外部中断后,当引脚有电平变化时,就可以触发中断,让CPU来处理任务。
TIM(定时器):也是STM32最常用、功能最多的外设;分为高级定时器、通用定时器、基本定时器三种类型,其中高级定时器最为复杂,常用的是通用定时器,这个定时器不仅可以完成定时中断的任务,还可以完成测频率、生成PWM波形、配置成专用的编码器接口等功能,像PWM波形,就是电机驱动、舵机驱动最基本的要求。
ADC(模数转换器):模数转换器,STM32内置了12位的AD转换器,可以直接读取IO口的模拟电压值,无需外部连接AD芯片,使用非常方便。
DMA(直接内存访问):可以帮助CPU完成搬运大量数据这样的繁杂任务。
USART(同步/异步串口通信):同步或异步串口,平常用的UART是异步串口的意思,USART即支持同步串口,也支持异步串口,当然实际使用还是异步串口比较多。
I2C和SPI:非常常用的两种通信协议,STM32内置了它们的控制器,可以用硬件来输出时序波形,使用起来更高效,当然用通用IO口来模拟时序波形也是没有问题的。
CAN和USB:也是通信协议,CAN通信一般用于汽车领域,生活中到处都是USB设备,利用STM32的USB外设,可以做模拟鼠标、模拟U盘等设备。
RTC(实时时钟):在STM32内部完成年月日、时分秒的计时功能,而且可以接外部备用电池,即使掉电也能正常进行。
CRC(CRC校验):数据校验方式,用于判断数据的正确性,有了在这个外设的支持,进行CRC校验会更加方便一些。
PWR(电源控制):可以让芯片进入睡眠模式等状态,来达到省电的目的。
BKP(备份寄存器):这是一段存储器,当系统掉电时,仍可由备用电池保持数据,这个根据需要,可以完成一些特殊功能。
IWDG和WWDG(独立看门狗和窗口看门狗):当单片机因为电磁干扰死机或者程序设计不合理出现死循环时,看门狗可以及时复位芯片,保证系统的稳定性。
DAC(数模转换器):可以在IO直接输出模拟电压,是ADC模数转换的逆过程。
SDIO(SD卡接口):可以用来读取SD卡。
FSMC(可变静态存储控制器):可以用于扩展内存或者配置成其他总线协议,用于某些硬件的操作。
USB OTG(USB主机接口):用OTG功能,可以让STM32作为USB主机去读取其他USB设备。
需要注意的是:以上是STM32F1整个系列的所有外设,并非所有型号都拥有全部的外设。比如STM32F103C8T6没有后面四个外设。具体芯片有哪些外设,需要查看相应数据手册。
1.3 芯片命名规则
1.4 芯片系统结构
可以分为以下四个部分:
(1)Cortex-M3内核引出了三条总线[ICode(指令总线)、DCode(数据总线)、System(系统总线)]。
(2)ICode(指令总线)和DCode(数据总线)主要用来连接Flash闪存,Flash里面存储的是我们编写的程序,ICode(指令总线)就是用来加载程序指令的;DCode数据总线就是用来加载数据的,比如常量和调试数据这些。
(3)System(系统总线)连到其它东西上面,比如SRAM,用于存储程序运行时的变量数据;还有FSMC,本课程不会用到;AHB系统总线,用于挂载主要的外设,AHB指的是先进高性能总线,挂载的一般是最基本的或者性能比较高的外设,比如复位和时钟控制这些最基本的电路,还有SDIO也是挂载在AHB上的;再后来是两个桥接,接到APB1和APB2两个外设总线上,这个APB的意思是先进外设总线,用于连接一般的外设;因为AHB和APB的总线协议、总线速度、还有数据传送格式的差异,所以中间需要加两个桥接,来完成数据的转换和缓存;AHB的整体性能比APB高一些,其中APB2的性能又比APB1高一些,APB2一般和AHB同频率,都是72MHz,APB1一般是36MHz,所以APB2连接的都是一般外设中稍微重要的部分,比如GPIO端口,还有一些外设的1号选手等(比如USART1、SPI1、TIM1、TIM8(TIM1和TIM8一样,也是高级定时器,所以也是重要的外设),还有ADC、EXTI、AFIO,也是接在APB2上面的),其它的像2、3、4、5号的外设,还有DAC、PWR、BKP等,这些次要一点的外设,都会分配到APB1上去。在使用的时候,个人一般感觉不到APB2和APB1的性能差异, 只需要知道这个外设是挂载到哪个总线上既可以。
(4)DMA可以当作内核CPU的小秘书,比如一些大量的数据搬运的活,让CPU来干太浪费时间。比如一个外设ADC模数转换,这个模数转换可以配置成连续模式,比如1ms转换一次,转换完的数据必须得转运出来,否则数据就会被覆盖丢失。如果直接让CPU来干这个工作,那么PCU每过1ms就得来转运一下数据,会费时费力,影响CPU的正常工作。但这个任务就是简单的数据搬运,没必要让CPU做,于是DMA就出现了,主要就是干数据搬运这样简单而反复要干的工作,那DMA通过DMA总线连接到总线矩阵上,它可以拥有和CPU总线一样的总线控制权,用于访问这些外设小弟,当需要DMA搬运数据时,外设小弟就会通过请求线发送DMA请求,然后DMA就会获得总线控制权,访问并转运数据,整个过程不需要CPU的参与,省下了CPU的时间来干其它的事情,这就是DMA的用途。
1.5 芯片引脚定义
下图标红色是电源相关的引脚,标蓝色的是最小系统相关的引脚,标绿色的是IO口、功能口这些引脚。
类型:S代表电源、I代表输入、O代表输出、IO代表输入输出 。
I/O口电平:代表IO口所能容忍的电压,有FT的,代表它能容忍5V的电压,没有FT的,只能容忍3.3V的电压。如果没有FT需要接5V的电平,就需要加装电平转换电路了。
主功能:上电后默认的功能,一般和引脚名称相同,如果不同的话,引脚的实际功能是主功能而不是引脚名称的功能。
默认复用功能:IO口上同时连接的外设功能引脚,这个配置IO口的时候可以选择是通用IO口还是复用功能。
重定义功能:作用是如果有两个功能同时复用在了一个IO口上,并且确实需要用到这两个功能,可以把其中一个复用功能映射到其它端口上,当然前提是重定义功能的表里有对应的端口。
推荐优先使用加粗的IO口,没有加粗的IO口可能需要配置或者兼具其它功能,使用时需要注意一下。
引脚定义:
1号引脚VBAT:备用电池供电的引脚,在这个引脚可以接一个3V的电池,当系统电源断电时,备用电池可以给内部得RTC时钟和备份寄存器提供电源。
2号引脚PC13-TAMPER-RTC(IO口/侵入检测/RTC):IO口可以根据程序输出或读取高低电平,是最基本也是最常用的功能;侵入检测可以用来做安全保障的功能(比如产品安全性比较高,可以在外壳加一些防拆的触点,然后街上电路到这个引脚,若有人强行拆开设备,那触点断开,这个引脚的电平变化,就会触发STM32的侵入信号,然后就会清空数据来保证安全);RTC引脚可以用来输出RTC校准时钟、STC闹钟脉冲或者秒脉冲。
3号4号引脚PC14-OSC32_IN和PC15-OSC32_OUT:IO口或者32.768KHz的RTC晶振。
5号6号引脚OSC_IN和OSC_OUT:接系统的主晶振,一般是8MHz的,然后芯片内有锁相环电路,可以对这个8MHz的频率进行倍频,最终产生72MHz的频率,作为系统的主时钟。
7号引脚NRST(系统复位引脚):N代表它是低电平复位的。
8号9号引脚VSSA和VDDA:内部模拟部分的电源,比如ADC、RC震荡器等,VSS是负极,接GND;VDD是正极,接3.3V。
10号-19号引脚:IO口,其中PA0兼具了WKUP的功能,这个可以用于唤醒处于待机模式的STM32。
20号引脚:IO口或者BOOT1引脚,BOOT引脚是用来配置启动模式的。
21号-22号引脚:IO口。
21号-22号引脚VSS_1和VDD_1:系统的主电源口,VSS是负极,VDD是正极。
35号-36号引脚VSS_2和VDD_2:系统的主电源口,VSS是负极,VDD是正极。
47号-48号引脚VSS_3和VDD_3:系统的主电源口,VSS是负极,VDD是正极。
STM32采用了分区供电的方式,所以供电口比较多,在使用时,把VSS都接GND,VDD都接3.3V即可。
25号-33号引脚:IO口。
34号和37号-40引脚:IO口或者调试端口,默认的主功能是调试端口,调试端口就是用来调试和下载程序的,这款STM32支持SWD和JTAG两种调试方式;SWD需要两根线,分别是SWIDO和SWCLK;JTAG需要5根线,分别是JTMS、JTCK、JTDI、JTDO、NJTRST。教程采用STLINK来下载调试程序,STLINK用的是SWD的方式,所以只需要占用PA13和PA14这两个端口,在使用SWD的调试方式时,剩下的PA15、PB3、PB4可以切换位普通的IO口来使用,但要在程序中进行配置,不配置的话默认是不会用作IO口的。
41号-43号引脚和45号-46号引脚:IO口。
44号引脚BOOT0:和BOOT1一样,是用来做启动配置的。
1.6 启动配置
这个启动配置的作用就是指定程序开始运行的位置,一般情况下,程序都是在Flash程序存储器开始执行,但是在某些情况下,也可以让程序在别的地方开始执行,用以完成特殊的功能。
BOOT0接0,BOOT1接1或者0时:采用主闪存存储器启动模式;
BOOT0接1,BOOT1接0时:采用系统存储器启动模式:
这个模式就是用来做串口下载用的,这个系统存储器寸的就是STM32中的一段BootLoader程序,BootLoader程序的作用就是接收串口的数据,然后刷新到主闪存中,这样就可以使用串口下载程序了,一般我们需要串口下载程序的时候会配置到这个模式上。
什么时候需要用到串口下载呢?34号和37号-40引脚,如果在程序中把这5各端口全部配置成IO口,那么这个芯片就没有调试端口了,也就不能下载程序了,所以配置端口的时候需要注意。
如果想使用串口下载,就需要配置BOOT1为0,BOOT0为1;如果没有STLINK,也没有JLINK,那就可以使用串口来进行下载程序。
BOOT0接1,BOOT1接1时:采用内置SRAM启动模式:
主要用来进行程序调试,现阶段使用比较少。
BOOT引脚的值是在上电复位后的一瞬间有效的,之后就随便了。BOOT1/和PB2是在同一个引脚上的,也就是在上电的瞬间是BOOT1的功能,当第4个时钟过后,就是PB2的功能。
根据引脚定义表。如果想要STM32正常工作,首先就需要把电源部分和最小系统部分的电路连接好,也就是表中标红色和蓝色部分。
1.7 STM32最小系统电路
一般来说,单片机只有一个芯片是无法工作的,需要为它连接最基本的电路。这些最基本的电路就叫做最小系统电路。
分区供电的主电源和模拟部分电源都接了供电引脚。VSS都连接了GND,VDD都连接了3V3,也就是3.3V。在3.3V和GND之间,一般会连接一个滤波电容,这个电容可以把保证供电电压的稳定,我们在设计电路的时候,一般只要遇到供电,都会习惯的加上几个滤波电容。
VBAT是接备用电池的,如果需要接备用电池,可以选择一个3V的纽扣电池,正极接VBAT,负极接GND就行了。备用电池是给RTC和备份寄存器服务的,如果不需要这些功能,就不用接备用电池。那这个VBAT直接接3.3V即可,或者悬空也是没问题的。
晶振电路:
接了一个8MHz的主时钟晶振,STM32的主晶振一般都是8MHz,8MHz经过内部锁相环倍频,得到72MHz的主频,这个晶振的两根引脚分别通过两个网络标号接到STM32的5、6号引脚;另外还需要接两个20pF的电容,作为启震电容,电容的另一端接地即可,这就是晶振电路,如果需要RTC功能的话,还需要再接一个32.768KHz的晶振,电路和在这个一样,接在3、4号引脚。
这个OSC32就是32.768KHz晶振的意思,为什么要用32.768KHz,因为32768是2的15次方,内部RTC电路经过2的15次方分频,就可以生成1s的时间信号了。
复位电路:
一个10K的电阻和一个0.1uF的电容组成的,用来给单片机提供复位信号,中间的NRST接在STM32的7号引脚,NRST是低电平复位的,当这个复位电路在上电的瞬间,电容是没有电的,电源通过电阻向电容充电,并且此时电容呈现的是短路状态,当电容逐渐充满电后,电容就相当于断路,此时NRST就会被R1上拉为高电平,那上电瞬间的波形就是先低电平,然后逐渐高电平,这个低电平就可以提供STM32的上电复位信号,让然电容充电是非常快的,所以在我们看来单片机在上电的一瞬间就复位了,这就是复位电路的作用;电容的左边还并联了一个按键,可以提供一个手动复位的功能,当我们按下按键时,电容被放电,并且NRST引脚也通过按键被直接接地了,这就相当于通过手动产生了低电平复位信号,按键松手后,NRST又回归高电平,此时单片机就从复位状态转换为工作状态,平时我们也可以见到这种复位按键,一般在设备上有个小孔,当设备死机并且还不方便断电重启时,我们使用针戳一下小孔里的按键,这样就会使设备复位了,这就是手动复位的功能,按下按键,程序就从头开始运行的意思。
启动配置电路:
H1相当于开干的作用,拨动这个开关,就可以让BOOT引脚选择接3.3V还是GND了。
下载端口电路:
使用STLINK下载程序的话,需要把SWDIO和SWCLK这两个引脚印出来方便接线,另外再把3.3V和GND引出来,这个GND是必须引出来的,3.3V如果板子自己有供电的话,可以不引,不过建议都引出来,方便一些。
02 软件安装
2.1 Keil5 MDK安装
略,微信公众号上破解版很多。
2.2 安装器件支持包
新建一个工程。
如果电脑上安装时是C51和MDK共存的情况,想要切换C51, 在下拉列表选择Legacy Device即可切换。
2.2.1 离线安装
找到我们需要安装的相应芯片支持包,双击进入安装程序,会默认选中keil安装目录,点击next,安装完后Finish。
2.2.2 在线安装
2.2.3 keil软件注册
(1)以管理员身份运行keil软件
(2)
(3)以管理员身份运行破解工具,注意关闭杀毒软件
(4)
出现以下窗口表示没有以管理员身份运行。
2.3 安装STLINK驱动
(1)将STLINK查到电脑上,打开设备管理器
(2) 安装驱动
2.4 安装USB转串口驱动
(1)将CH340插到电脑上
(2)安装驱动
03 新建工程
目前STM32的开发方式主要有基于寄存器的方式、基于标准库也就是库函数的方式和基于HAL库的方式。
(1)基于寄存器的方式与51单片机开发方式一样,是用程序直接配置寄存器,来达到我们想要的功能,这种方式最底层、最直接、效率会更高一些。但是由于STM32结构复杂、寄存器太多,所以基于寄存器的方式目前是不推荐的。
(2)基于库函数的方式是使用ST官方提供的封装好的函数,通过调用这些函数来间接的配置寄存器。由于ST对寄存器封装的比较好,所以这种方式既能满足对寄存器的配置,对开发人员比较友好,有利于提高开发效率,本课程就是使用库函数开发方式。
(3)基于HAL库的方式可以用图形化界面快速配置STM32,比较适合快速上手STM32的情况,但是这种方式隐藏了底层逻辑,如果对STM32不熟悉,基本只能停留在很浅的水平。建议学过标准准库以后,了解一下这种方式。
使用固件库的方式需要提前准备好固件库的资料。库函数文件夹目录如下:
Libraries:库函数的文件;
Project:官方提供的工程示例和模板 ;
Utilities:STM32官方评估板的相关例程,官方用STM32做的一个小电路板,用来评测STM32的,这个文件夹里面存放的就是这个小电路板的测评程序;
Release_Notes.html:库函数的发布文档,里面有一些版本说明;
stm32f10x_stdperiph_lib_um.chm:库函数的使用手册,使用手册里有教怎么使用这个库函数。
3.1 新建基于标准库的工程
3.1.1 新建工程
(1)先建一个存放工程的文件夹
(2)新建工程:
选择器件型号:
下图暂时不用,关闭。
工程创建完毕,如下图所示:
3.1.2 添加工程所需要的必要文件
3.1.2.1 添加STM32的启动文件
复制上图启动文件, 在工程文件夹下新建一个“Start”文件夹,将启动文件拷贝进去。
3.1.2.2 添加STM32外设寄存器文件
stm32f10x.h:STM32的外设寄存器描述文件,它的作用就跟51单片机的头文件“RGEX52.H”一样,是用来描述STM32有哪些寄存器和它对应的地址的;
system_stm32f10x.c和system_stm32f10x.h文件:主要是用来配置时钟的,STM32主频72MHz,就是system文件里的函数配置的。
将上述3个文件复制粘贴到“Start”文件夹下。
3.1.2.3 添加STM32内核寄存器文件
因为STM32是内核和内核外围的设备组成的,而且内核的寄存器描述和外围设备的描述文件不是在一起的,所以还需要添加内核寄存器文件。
将上述两个文件粘贴到 “Start”文件夹下。
3.1.2.4 将以上文件添加到工程中
将以下文件添加进去(md.s文件以及.c和.h文件):
以上文件都是STM32里最基本的文件,是不需要修改的,添加进来即可。 文件图标上带了个钥匙🔑,表示这些文件是只读文件,无法被修改。
3.1.2.5 在工程选项里添加Start文件夹头文件路径
3.1.3 添加源代码文件
创建“User”文件夹,用来存放main函数等文件 。
这个工程还没有添加STM32的库函数,还是一个基于寄存器开发的工程,如果想用寄存器开发STM32,那么工程建立到这里就可以了。
3.1.4 通过寄存器的方式完成点灯的操作
修改编辑器字体大小:
(1)连接电路:
3.1.4.1 配置调试器
接在PC13引脚的LED灯停止闪烁。
3.1.4.2 配置寄存器点灯
(1) 首先配置RCC的一个寄存器,来使能GPIOC的时钟,GPIO都是APB2的外设。
因为测试LED灯接在PC13引脚,参照STM32引脚定义 ,该引脚主功能为IO口,再参照STM32芯片系统结构,GPIO都是APB2的外设。
位4写1就是打开GPIOC的时钟,其它的无关项都给0, 那么将整个RCC时钟控制信号换成16进制便是0x0000 0010;
(2)配置GPIOC的模式
换算成16进制就是0x0030 0000。
(3)配置端口输出数据寄存器
main.c代码如下:
#include "stm32f10x.h" // Device header
int main(void) //main函数是一个int型返回值,void参数的函数
{
RCC->APB2ENR = 0x00000010; //打开GPIOC的时钟
GPIOC->CRH = 0x00300000; //配置GPIOC的输出模式
GPIOC->ODR = 0x00002000; //这个灯是低电平点亮,给0x00002000就是灭,给0x00000000就是亮
while(1)
{
}
}
3.2 通过库函数的方式点灯
在通过寄存器的基础上进行。
3.2.1 添加库函数
(1)工程文件夹下新建“Library”文件夹。
(2)将库函数复制到 “Library”文件夹下。
①复制库函数的源文件。
misc.c:内核的库函数,其它的都是内核外的外设库函数。misc就是混杂的意思。
将以上文件全部复制到 “Library”文件夹下。
②复制库函数的头文件粘贴到“Library”文件夹下。
(3)将库函数文件添加进工程
但是这个库函数还不能直接使用。
(4)添加库函数头文件包含文件
stm32f10x_conf.h :
用来配置库函数头文件的包含关系的,另外里面还有个用来参数检查的函数定义,这是所有库函数都需要的。
stm32f10x_it.h和stm32f10x_it.c :
用来存放中断函数。
将上述三个文件复制粘贴到“User”文件夹下。
将这三个文件添加进工程:
3.2.2 配置库函数
#ifdef USE_STDPERIPH_DRIVER //如果定义了USE_STDPERIPH_DRIVER这个字符串,下面的"stm32f10x_conf.h"才有效
#include "stm32f10x_conf.h"
#endif
复制“USE_STDPERIPH_DRIVER”
将 “Library”文件夹和“User”文件夹也添加到目录里。
这样,基于库函数的工程就建好了,“Library”里面的库函数也都带了钥匙🔑,不需要更改。位移需要更改的是“User”里面的文件。
点击上图所示按钮,挪一下文件组的位置。
3.2.3 通过库函数点灯
库函数也是间接的配置寄存器,所以步骤是一样的。
(1)配置RCC外设时钟
查看函数简介 :
/**
* @brief Enables or disables the High Speed APB (APB2) peripheral clock. //这个函数用来使能或失能APB2的外设时钟
* @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock.
* This parameter can be any combination of the following values://第一个参数可以是下面这些值
* @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
* RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
* RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
* RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
* RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
* RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
* RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
* @param NewState: new state of the specified peripheral clock.//第二个参数可以是ENABLE or DISABLE
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
/* Check the parameters */
/* 内部还是配置RCC_APB2ENR这个寄存器,但是经过函数的包装,我们不需要查手册,确认哪一位的作用
而且函数中已经使用"|="和"&="使得这个库函数的配置不会影响到寄存器的其它位*/
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2ENR |= RCC_APB2Periph;
}
else
{
RCC->APB2ENR &= ~RCC_APB2Periph;
}
}
(2)配置端口模式
查看函数简介:
/**
* @brief Initializes the GPIOx peripheral according to the specified
* parameters in the GPIO_InitStruct.//根据GPIO_Init结构体的参数来配置GPIO
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.//第一个参数GPIOx,其中x可以是A到G,来选择需要配置哪个GPIO
* @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that//第二个参数是一个GPIO_InitTypeDef的结构体,因此需要先定义一个GPIO_InitTypeDef结构体
* contains the configuration information for the specified GPIO peripheral.
* @retval None
*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
查看GPIO_Mode的定义:
通过查找可查看GPIO_Mode可以使用哪些参数,GPIO_Pin和GPIO_Speed同理。
查看GPIO_Pin的定义:
以上是通过库函数点亮PC13口LED的库函数方法,最终"main.c"文件如下:
#include "stm32f10x.h" // Device header
int main(void) //main函数是一个int型返回值,void参数的函数
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //配置GPIOC外部时钟
GPIO_InitTypeDef GPIO_InitStructure; //定义一个GPIO_InitTypeDef结构体,名字最好取为GPIO_InitStructure,然后配置其三个参数
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置GPIO模式是通用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure); //配置GPIOC端口的输出模式
// GPIO_SetBits(GPIOC,GPIO_Pin_13); //设置GPIO_Pin_13高电平,灯灭
GPIO_ResetBits(GPIOC,GPIO_Pin_13); //设置GPIO_Pin_13低电平,灯亮
while(1)
{
}
}
3.3 关于启动文件的注意事项
新建工程以后第一个加的就是启动文件,这个启动文件有很多类型,我们要根据芯片型号来选择。
下表是STM32F1系列中的型号分类
缩写 |
释义 |
Flash容量 |
型号 |
LD_VL |
小容量产品超值系列 |
16~32K |
STM32F100 |
MD_VL |
中容量产品超值系列 |
64~128K |
STM32F100 |
HD_VL |
大容量产品超值系列 |
256~512K |
STM32F100 |
LD |
小容量产品 |
16~32K |
STM32F101/102/103 |
MD |
中容量产品 |
64~128K |
STM32F101/102/103 |
HD |
大容量产品 |
256~512K |
STM32F101/102/103 |
XL |
加大容量产品 |
大于512K |
STM32F101/102/103 |
CL |
互联型产品 |
- |
STM32F105/107 |
如果使用的是STM32F100的型号,就选择带VL的启动文件,然后再根据Flash的大小选择LD、MD还是HD。
如果使用的是STM32F101/102/103的型号,就选择不带VL的启动文件,然后再根据Flash的大小选择LD、MD、HD还是XL。
如果使用的是STM32F105/107的型号,就选择CL的启动文件。
3.4 工程架构
startup启动文件,这个是程序执行最基本的文件,keil中启动文件是用汇编写的,启动文件内定义了中断向量表、中断服务函数等。中断服务函数中有个复位中断,这就是整个程序的入口,当STM
32上电复位或者按下复位键后,程序就会进入复位中断函数执行,复位中断函数主要做两件事情,第一个是调用SystemInit函数,第二个是调用main函数。
startup_xx.sStrt
sstartup_xx.startup_xx.sstartup_xx.s