STM32应用开发实践教程:可控 LED 流水灯的设计与实现

任务 2.1 LED 流水灯的应用开发
2.1.1 任务分析
本任务要求设计一个 LED 流水灯系统,具体要求如下。
系统通电时,两个 LED 以 2s 为周期(亮 1s,灭 1s)交替闪烁,并逐渐缩短周期(每次递
减 0.1s),直至周期变为 0.1s 后,再恢复为 2s,并以此循环往复。
分析本任务的要求,若要控制 LED 以一定的周期进行闪烁,开发者须在应用程序中加入延
时功能。在 STM32 应用开发的过程中,经常会用到延时操作,如控制 LED 亮 1s 后熄灭、每隔
2s 采集一次环境温湿度值等。在实际应用中,编程实现延时一般有 3 种方法。
一是用软件实现延时,这种方法通过让 MCU 执行空指令实现,缺点是延时不准确。
二是用定时器实现延时,这种方法通过控制 MCU 内部的定时器外设实现,缺点是需要占用
一个定时器资源,优点是延时准确。
三是用 MCU 内核的 SysTick 实现延时,这种方法通过控制 SysTick 进行倒计数实现,不需
要占用额外的定时器资源,而且能实现精确延时。
综上所述,使用 SysTick 实现延时的方法具有一定的优势,因此在实际应用中一般选用这种
方法实现最基本的延时操作。
本任务涉及的知识点有:
STM32F4 系列微控制器 SysTick 的工作原理和编程配置方法;
STM32F4 系列微控制器通用 I/O 的工作原理和编程配置方法。
2.1.2 知识链接
1.使用 SysTick 实现延时
SysTick 是 Cortex-M4 内核的外设,所以不单是 ST 公司的 STM32F4 系列微控制器内部有
SysTick,只要是使用了 Cortex-M4 内核的微控制器,它们的内部都有 SysTick。SysTick 是一
个 24 位的倒计数定时器,当计数到 0 时,SysTick 将从重载值寄存器(STK_LOAD)中自动
重新加载计数初值。只要不将 SysTick 的控制与状态寄存器(STK_CTRL)中的使能位清除,
它就可以持续运行。
STM32F4 系列微控制器的 SysTick 时钟源来自 AHB,我们可将其配置为“AHB 时钟频率
的 1/8”或者直接使用“AHB 时钟频率”,实际应用中一般使用前者,如图 2-1-1 中的阴影部
分所示。
接下来介绍与 SysTick 编程配置相关的 4 个寄存器:控制与状态寄存器、重载值寄存器、当
前值寄存器和校准数值寄存器。
控制与状态寄存器(SysTick Control And Status Register,STK_CTRL)的位段定义与功能
描述见表 2-1-1。

STM32应用开发实践教程:可控 LED 流水灯的设计与实现

 2.STM32F4 系列微控制器的 GPIO 及其工作模式
通用 I/O 的全名是通用输入/输出(General Purpose Input Output,GPIO)。微控制器的 GPIO 引脚数量随着片内资源的变化而变化。微控制器通过 GPIO 引脚与外部设
备相连,进而实现相应的控制操作与通信功能。STM32 全系列芯片的 GPIO 被分成多组,每组
有 16 个引脚。以 STM32F407ZGT6 型号微控制器为例,它的 GPIO 引脚被分成 GPIOA、
GPIOB、…、GPIOG 共 7 组,共有 144 个引脚。GPIOA 组(也称之为 GPIOA 端口)含有 GPIOA.0
(也称为 PA0)、GPIOA.1、…、GPIOA.15 共 16 个引脚,其他 GPIO 组亦然。
STM32F4 系列微控制器的 GPIO 引脚可以配置成以下 8 种工作模式中的一种:输入浮空、
输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、复用推挽输出和复用开漏输出。
实际应用中,应根据应用需求选择 GPIO 的工作模式。例如:配置 GPIO 引脚用于 LED 的
亮灭控制时,一般选择“推挽输出”工作模式。
3.与 GPIO 工作模式配置相关的寄存器和函数 API
(1)与 GPIO 工作模式配置相关的寄存器
与GPIO工作模式配置相关的寄存器主要有GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR
和 GPIOx_PUPDR(x=A,B,C…),下面分别对它们进行介绍。
GPIO 端口模式控制寄存器(GPIO Port Mode Register,GPIOx_MODER)用于控制 GPIOx
的工作模式,其位段定义如图 2-1-2 所示。

STM32应用开发实践教程:可控 LED 流水灯的设计与实现

GPIO 端口输出类型寄存器(GPIO Port Output Type Register,GPIOx_OTYPER)用于控
制 GPIOx 的输出类型,在 GPIOx_MODER 相应位段被配置为“01”(即通用输出模式)时适用。
该寄存器低 16 位有效,每一位控制一个 GPIO 引脚,其位段定义如图 2-1-3 所示。

STM32应用开发实践教程:可控 LED 流水灯的设计与实现 

 GPIO 端口输出速度寄存器(GPIO Port Output Speed Register,GPIOx_OSPEEDR)用于
控制 GPIOx 端口的输出速度,相应的输出频率有 2 MHz、25 MHz、50 MHz 和 100 MHz 这 4
种。GPIOx_OSPEEDR 的位段定义如图 2-1-4 所示。

STM32应用开发实践教程:可控 LED 流水灯的设计与实现

(2)与 GPIO 工作模式配置相关的函数 API
与 GPIO 工作模式配置相关的函数 API 主要位于“stm32f4xx_gpio.c”和“stm32f4xx_gpio.h”
文件中。利用 STM32F4 的标准外设库进行应用开发时,各种外设的初始化一般通过对初始化
结构体的成员赋值来完成,GPIO 工作模式的配置也是如此。某个 GPIO 端口的初始化函数原
型如下。
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) ;
第一个参数是需要初始化的 GPIO 端口,对于 STM32F407ZGT6 型号而言,取值范围是
GPIOA~GPIOG。第二个参数是初始化参数的结构体指针,结构体类型为 GPIO_InitTypeDef,
其原型定义如下。 

上述结构体定义中,第一个成员 GPIO_Pin 用于配置要初始化的 GPIO 引脚编号。如配置选项
“GPIO_Pin_9”代表对GPIOx 端口中的9 号引脚进行配置,即GPIOx.9(x=A,B,C,D,E…)。
第二个成员 GPIO_Mode 用于配置 GPIO 端口的工作模式,它的类型为枚举,实际配置
GPIOx_MODER 的值。其类型定义如下:

第三个成员 GPIO_Speed 用于配置 GPIO 端口的输出速度,它的类型为枚举,实际配置
GPIOx_OSPEEDR 的值。其类型定义如下:

第四个成员 GPIO_Otype 用于配置 GPIO 端口的输出类型,它的类型为枚举,实际配置
GPIOx_OTYPER 的值。其类型定义如下:

第五个成员 GPIO_PuPd 用于配置 GPIO 端口的上拉/下拉形式,它的类型为枚举,实际配置
GPIOx_PUPDR 的值。其类型定义如下:

下面是一段 GPIO 端口初始化的程序实例:

4.与 GPIO 电平控制相关的寄存器和函数 API
介绍完与 GPIO 工作模式配置相关的寄存器和函数 API 后,接下来介绍与 GPIO 电平控制相
关的寄存器,并讲解如何调用相应的函数 API 以实现 GPIO 电平的控制。
与 GPIO 电平控制相关的寄存器有 GPIOx_IDR、GPIOx_ODR 和 GPIOx_BSRR,下面分别
对它们进行介绍。
(1)GPIOx_IDR 及其相关函数 API
GPIO 端口输入数据寄存器(GPIO Port Input Data Register,GPIOx_IDR)用于读取某个
GPIOx 端口的输入电平,低 16 位有效,分别对应 16 个引脚的电平值。若某位的值为 0(如
GPIOA_IDR9=0),则说明该引脚(PA9)输入低电平;反之,输入高电平。GPIOx_IDR 的位段
定义如图 2-1-6 所示。

STM32应用开发实践教程:可控 LED 流水灯的设计与实现

STM32F4标准外设库提供了GPIO_ReadInputData()函数和GPIO_ReadInputDataBit()函数
用于读取输入的电平,前者用于一次性读取某 GPIOx 端口中所有引脚的输入电平,后者用于读
取若干 GPIO 引脚的输入电平。它们的原型定义如下:
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
使用实例 1:
GPIO_ReadInputData(GPIOB);
上述实例一次性读取 GPIOB 端口中所有 GPIO 引脚的输入电平,返回 16 位二进制数据。
使用实例 2:
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8);
上述实例读取 GPIOA.8 引脚(PA8)的输入电平,返回 8 位二进制数据。
(2)GPIOx_ODR 及其相关函数 API
GPIO 端口输出数据寄存器(GPIO Port Output Data Register,GPIOx_ODR)用于设置某
个 GPIOx 端口的输出电平,当某个 ODRy 位段被写入 0 时,相应的引脚输出低电平;否则,输
出高电平。GPIOx_ODR 的位段定义如图 2-1-7 所示。
STM32F4 标准外设库提供了 GPIO_Write()函数来实现对 GPIOx 端口输出电平的控制,其原
型定义如下:
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

STM32应用开发实践教程:可控 LED 流水灯的设计与实现 

GPIO_Write()函数的第一个参数是 GPIOx 端口,第二个参数是需要输出的值(16 位二进制
数据),其使用实例如下:
GPIO_Write(GPIOF, 0xFFB7);
上述实例控制 GPIOF 端口的 16 位输出为 0xFFB7。
若要一次性读取某GPIOx 端口中所有GPIO引脚的输出电平,则可使用GPIO_ReadOutputData()
函数,其函数原型定义如下:
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
也可使用GPIO_ReadOutputDataBit()函数读取某GPIOx端口中的一个或若干个GPIO引脚
的输出电平,其函数原型定义如下:
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
(3)GPIOx_BSRR 及其相关函数 API
GPIO 端口置位/复位寄存器(GPIO Port Bit Set/Reset Register,GPIOx_BSRR)用于设置
某 GPIOx 端口中的一个或若干个 GPIO 引脚的输出电平,高 16 位对应输出低电平,低 16 位对
应输出高电平。
对于 GPIOx_BSRR 的高 16 位(16~31)而言,往相应的位写入 1,则对应的 GPIO 引脚输出低
电平;若写入0,则不起作用。同理,对于GPIOx_BSRR 的低16 位(0~15)而言,往相应的位写入
1,则对应的 GPIO 引脚输出高电平;若写入 0,则不起作用。GPIOx_BSRR 的位段定义如图 2-1-8
所示。

STM32应用开发实践教程:可控 LED 流水灯的设计与实现 

STM32F4 标准外设库提供了两个设置GPIO 端口输出电平的函数,它们通过操作GPIOx_BSRR

来实现,其函数原型定义如下:
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
使用实例 1:
GPIO_SetBits(GPIOA, GPIO_Pin_4);
上述实例设置 PA4 引脚输出高电平。
使用实例 2:
GPIO_ResetBits(GPIOC, GPIO_Pin_1 | GPIO_Pin_12);
上述实例设置 PC1 和 PC12 两个引脚输出低电平。

2.1.3 任务实施
1.配置 SysTick 以实现延时
复制一份任务 1.3 的工程,并将其重命名为“task2.1_WaterFlow_LED”。在“SYSTEM”目
录下新建子文件夹“delay”,新建“delay.c”和“delay.h”文件,将它们加入工程中,并配置
头文件包含路径。在“delay.c”文件中输入以下代码:

来源:谷哥-Mr.Gu

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年6月9日
下一篇 2022年6月9日

相关推荐