【朱老师课程总结】
第一部分、章节目录
第二部分、章节介绍
3.5.1.STM32的GPIO模块数据手册详解1
本节讲解STM32数据手册中GPIO模块相关的部分,主要是GPIO的各种模式及其配置方法。
3.5.2.STM32的GPIO模块数据手册详解2
本节继续讲解STM32的数据手册中GPIO部分,主要是GPIO配置的寄存器列表及寄存器位详解。
3.5.3.原理图分析与MDK工程建立
本节分析ARM3.0的GPIO控制LED相关的原理图,并且建立MDK工程,简单讲一下启动文件。
3.5.4.写代码控制GPIO点亮熄灭LED1
本节编写代码控制GPIO以点亮熄灭LED,主要内容是寄存器地址的确定以及使用C语言操作寄存器的编程技巧。
3.5.5.写代码控制GPIO点亮熄灭LED2
本节解决了时钟模块没打开的问题,并且定义了宏来访问寄存器,使我们的代码更加规范。
3.5.6.STM32时钟设置函数移植与讲解1
本节移植STM32时钟设置函数,并且结合前面课程讲过的时钟框图对时钟设置函数进行讲解
3.5.7.STM32时钟设置函数移植与讲解2
本节接上节继续移植时钟部分的设置代码,到了HSE时钟稳定阶段
3.5.8.STM32时钟设置函数移植与讲解3
本节完成时钟设置的源码移植并且进行测试。
3.5.9.STM32时钟设置函数移植与讲解4
本节使用调试的方式寻找代码中的问题,解决了超时计算的bug和if判断中的bug,但是时钟还是有问题不能工作
3.5.10.STM32时钟设置函数移植与讲解5
本节添加了FLASH ACR寄存器相关的操作代码后,时钟终于正常工作了。并且通过flash函数的闪烁速度对比可以明显看出PLL启动后主频发生了改变。
3.5.11.在PZ6806L开发板上实现GPIO和时钟编程控制
本节在PZ6806L开发板上移植实现GPIO的控制和时钟模块的编程,这种移植可以让大家学会在不同硬件差异下编程的相同点和不同点。
3.5.12.在PZ6808L开发板上实现GPIO和时钟编程控制1
本节在PZ6808L开发板上移植实现GPIO的控制和时钟模块的编程,让大家看看在F4上编程和F1上有什么差异
3.5.13.在PZ6808L开发板上实现GPIO和时钟编程控制2
本节接上节在PZ6808L开发板上移植实现GPIO的控制和时钟模块的编程.
3.5.14.STM32外设编程经验总结
本节对整个课程进行总结,并对比了51单片机和stm32单片机外设编程的差别,告诉大家stm32学习的关键点和思路方法。
第三部分、随堂记录
3.5.1.STM32的GPIO模块数据手册详解1
数据手册第8章:通用和复用功能I/O(GPIO 和AFIO)
3.5.1.1、GPIO功能描述
(1)每个I/O端口(GPIOx)包含的寄存器
- 两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)
- 两个32位数据输入/输出寄存器(GPIOx_IDR和GPIOx_ODR)
- 一个32位端口位置位/复位寄存器(GPIOx_BSRR) 置位:写1,复位:写0
- 一个16位端口位复位寄存器(GPIOx_BRR) 也是32位寄存器,只不过高16位保留不用!
- 一个32位端口配置锁定寄存器(GPIOx_LCKR)
PS:BRR和BSRR复位功能相似、在STM32F103C8中每个GPIO端口包括16个引脚
(2)每个端口的每个位可以由软件分别配置成多种输入输出模式。
- 输入浮空
- 输入上拉
- 输入下拉
- 模拟输入
- 开漏输出
- 推挽式输出
- 推挽式复用功能
- 开漏复用功能
详细了解可以看这个文件:GPIO输入输出模式详解
(3)每个端口都可以配置三种最大输出翻转速度
在配置寄存器里设置即可
后面都是关于硬件设计的,只要做了解即可!
(4)外设的GPIO配置
3.5.2.STM32的GPIO模块数据手册详解2
(1)GPIO寄存器描述
GPIO的寄存器基地址是0x40010800
- 端口配置低寄存器 端口配置低寄存器(GPIOx_CRL) (x=A..E)
- 端口配置高寄存器 端口配置高寄存器(GPIOx_CRH) (x=A..E)
为什么会有两个端口配置寄存器呢?因为一个端口配置寄存器只能配置8个引脚,两个就可以配置一个端口!CNFx位和MODE位关联 - 端口输入数据寄存器 端口输入数据寄存器(GPIOx_IDR) (x=A..E)
- 端口输出数据寄存器 端口输出数据寄存器(GPIOx_ODR) (x=A..E)
- 端口位设置 端口位设置/ 清除寄存器(GPIOx_BSRR) (x=A..E)
是对ODR位置位/复位
如果BRy和BSy同时被置位,BSy有优先权。 -
端口位清除寄存器 端口位清除寄存器(GPIOx_BRR) (x=A..E)
-
端口配置锁定寄存器 端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)
(2)复用
AFIO的起始地址:0x4001 0000
3.5.3.原理图分析与MDK工程建立
3.5.3.1、硬件接线
(1)杜邦现连接P0端口到LED接口J19,这样相当于8个LED分别对应PB8-PB15
- PB8—LED0,PB9—LED1...
(2)LED是共阴,所以GPIO输出0就亮,输出1就灭!
3.5.3.2、MDK工程建立
(1)提取ST标准外设库文件
ST标准外设库里面源代码文件我们只需要使用部分文件。因此,提取需要使用的文件及文件夹到我们的工程中。
解压“STM32F10x_StdPeriph_Lib”,可以看到在主目录下面有四个文件夹:
- _htmresc:图片文件夹(不提取)
- Libraries:库文件夹(提取大部分)
- Project: 示例工程(提取少部分)
- Utilities: 公共代码、评估板代码(不提取)
(2)新建文件和文件夹
除了上面提取的文件之外,我们需要建立存放自己代码的文件和文件夹。我这里主要新建三个文件夹:
- App: 应用部分代码
- Bsp: 底层部分代码
- Doc: 说明文档
在新建的文件夹下面还需要新建自己的源文件,源文件里面添加源代码。
(3)新建工程
建立工程的步骤是基础,也比较简单,下面一步一步教大家新建一个空的工程。
A.打开软件,新建立工程(Project -> New uVision Project)
B.选择保存路径,保存名称
C.选择芯片型号
D.基础工程
一个基础的工程就完成了,但还不够,还需要下面的步骤。
3.2 添加文件
准确的来说,应该是添加组(文件夹)和添加文件。直接的说,就是将你自己的源代码(前面提取的库、新建的文件等)添加到工程中。
这里的工程项目管理可根据自己的想法来定义(类似于自己分类、命名文件夹和文件),我这里按照常规的方式进行管理项目。
点击“项目管理”快捷按钮,或者Project -> Manage -> Project Items 进入“项目管理”界面。
一步一步添加,直到最后完成
3.3 配置工程
配置工程对于初学者来说,大部分内容只需要默认即可,这里只讲述几个常见的配置,能满足基本的功能。
A.点击“工程目标选项”进入配置(或Project -> Options for Target)
B.输出Hex文件
很多朋友初学的朋友都会问怎么输出Hex,只需要勾选上【Project -> Options for Target -> Output】“Create HEX File”即可。
C.C/C++配置
这个选项的配置参数比较多,对于大型项目来说比较重要,但对于初学者来说,只需要简单配置两项就行。
第一处配置---预定义:
【这里以STM32F103大容量芯片为例】
预定义STM32F10X_HD,等同于#define STM32F10X_HD.
有些工程还预定义USE_STDPERIPH_DRIVER。由于都是使用“标准外设库”,我个人习惯把USE_STDPERIPH_DRIVER,定义在stm32f10x.h文件里面,所以在这里就看不到我定义的这一项了。
第二处配置---包含路径:
由于我们前面工程中有很多文件夹,因此需要添加对应的路径,这样编译器才能找得到。
一步一步添加,直到最后完成
D.选择下载调试工具
这个选项根据自己的下载调试器来选择(比如:ST-Link)
E.下载复位并运行设置
有些初学的朋友说“为什么我下载程序之后,需要按一下复位键才能运行?”,只需要在工程中勾选上“Reset and Run”就可实现,下载完程序马上运行了。
至此,一个新建立的工程就算完成了(当然,我新建的文件是添加了正确的源代码),只需要编译,接上下载器就可以下载运行了。
3.5.4_5.写代码控制GPIO点亮熄灭LED1_2
3.5.4.1、寄存器信息确认
(1)STM32 PortB的起始地址是:0x40010C00
(2)有可能涉及到的GPIO的地址:
寄存器名 偏移量 寄存器地址
GPIOB_CRL 0x00 0x40010C00
GPIOB_CRH 0x04 0x40010C04 *
GPIOB_IDR 0x08 0x40010C08
GPIOB_ODR 0x0C 0x40010C0C *
GPIOB_BSRR 0x10 0x40010C10 ?
GPIOB_BRR 0x14 0x40010C14 ?
3.5.4.2、C语言操作寄存器
(1)ARM是内存与IO统一编址的,所以ARM中的所有外设都是通过寄存器的方式来操作的
(2)每个寄存器都有地址,C语言通过这些地址来操作这些寄存器位,用到的C语言技巧主要是C语言的位操作和C语言指针。
(3)常见面试题:用C语言向内存地址0x30000004写入16
*(unsigned int *)0x30000004 = 16; 或者:
unsigned int *p = (unsigned int *)0x30000004; *p = 16;
(4)向CRH寄存器写内容,将GPIO8-GPIO15配置为输出模式
通用推挽输出
CRH = 0x33333333
3.5.6_7.STM32时钟设置函数移植与讲解1_2
3.5.6.1、时钟模块回顾
(1)一个疑惑:前面代码并没有设置时钟为什么能够运行
(2)时钟框图
3.5.6.2、时钟设置示例代码分析
(1)相关寄存器及定义
(2)代码详解
RCC->CR 就相当于是rRCC_APB2ENR
3.5.6.3、时钟代码移植
3.5.8_9_10.STM32时钟设置函数移植与讲解3_4_5
3.5.11.STM32外设编程经验总结
3.5.14.1、STM32和51或其他简单单片机的相同
(1)开关环境都是Keil
(2)都是看原理图和数据手册
(3)都是用C语言
3.5.14.2、STM32和51或其他简单单片机的不同
(1)工程会更复杂,会用到Keil的一些高级设置
(2)原理图和数据手册比简单单片机更复杂(复杂不是难)
(3)STM32会用到C语言的更多高级特性
3.5.14.3、外设编程思路
(1)都是套路
(2)会出现问题,这时候就需要调试能力(不一定非要调试器)
(3)注意熟悉和体会这种套路,后面引入库函数就是从这里讲起的