STM32 教程: 02 点亮 LED 灯
date
Feb 6, 2024
slug
stm32-02
status
Published
tags
STM32
嵌入式
summary
(篇 02)STM32 菜鸟教程:通过 GPIO 高低电平点亮 C 板 LED 灯,实现流水灯
type
Post
导入
GPIO (General Purpose Input Output) 通用输入/输出:一种通用的输入输出接口,可以用于数字信号的输出与输入,也可用于复用的其他功能。它可以通过软件配置为输入或输出模式,并且可以读取或写入数字信号。
输入模式:在输入模式下,GPIO 引脚可以读取外部设备发送的信号。可以使用相应的程序接口来读取引脚的状态,通常是高电平(1)或低电平(0)。例如,将一个按钮连接在 GPIO 引脚上,并通过读取引脚状态来检测按钮是否被按下。RoboMaster 开发板 C 型上预置的 KEY 按键就可以通过 GPIO 引脚读取是否按下。
输出模式:在输出模式下,GPIO 引脚可以发送信号给外部设备。可以使用相应的程序接口来设置引脚的状态,通常是将引脚设置为高电平(1)或低电平(0)。例如,将一个 LED 连接到 GPIO 引脚上,并通过设置引脚状态来控制 LED 的亮灭。本项目的变色灯就是通过设置 GPIO 输出实现的。
在本项目中将会实现基于 GPIO 的变色灯效果,RoboMaster 开发板 C 型使用一颗共阳极的 RGB LED 灯珠,其本质是将三个独立的 LED 封装在同一个灯珠上,并将所有 LED 的阳极连接在一起。在本项目中可以认为 GPIO 是可以控制高低电压的针脚。
配置 CubeMX
首先按照 篇 1 的教程在 CubeMX 中新建一个工程。
任何配置引脚都应该先看原理图。没有板子是能完全照抄的,即使是板子出品方的教程也可能存在疏漏(点名批评 DJI)。我们应该看开发板的原理图,找对应引脚,再进入 CubeMX 配置!
打开大疆 RoboMaster 开发板 C 型原理图搜索关键字
LED
找到结果如下:![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F4b7ca86c-d5bb-4419-83a3-89ebf0bb191f%2F5b5044c4-3c4c-47b0-9578-54fdbf18b78a%2FUntitled.png?table=block&id=0261f5ee-c93a-4cd7-bb09-244632577326&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F4b7ca86c-d5bb-4419-83a3-89ebf0bb191f%2F67c3e632-54f4-4b41-8c03-4f0b4d3dcc78%2FUntitled.png?table=block&id=8e477daf-f1c0-4ee6-82d4-9fb1b31d55c9&cache=v2)
读到对应信息 ——
LED_B
对应引脚 PH10
;LED_G
对应引脚 PH11
;LED_R
对应引脚 PH12
。![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F4b7ca86c-d5bb-4419-83a3-89ebf0bb191f%2Fbf00ce28-2f8c-4aab-aed8-edfb6d1d7e7d%2FUntitled.png?table=block&id=4711eca6-d22d-4ff5-9d90-5ca69d8d65c3&cache=v2)
这是 LED 的电路图,VCC_5V 表示一个 5V 电压源,下面由四道红线构成的三角符号表示 GND(电源负极)。LED_B,LED_G,LED_R 分别与上图中的相同标签对应。Q7,Q8,Q9 为三个 NMOS,可以理解为,由电压控制的开关。GPIO 输出高电平,NMOS 导通,可视为开关闭合,电流流经 LED 使其发光。
我们在 STM32CubeMX 中的 Pinout View 引脚视图中找到 PH10、PH11、PH12 引脚,左键单击设置其为
GPIO_Output
:![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F4b7ca86c-d5bb-4419-83a3-89ebf0bb191f%2Fe730cc99-c6ea-4f65-a5c5-8078e25c5e2c%2FUntitled.png?table=block&id=a1b98a79-b13f-43f1-88f2-df3fea4519d2&cache=v2)
全部设置完成后,点击左侧的 System Core 选项卡,进入 GPIO 设置。
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F4b7ca86c-d5bb-4419-83a3-89ebf0bb191f%2Fbddbd19a-4cce-4c1e-83f2-95099ab175b6%2FUntitled.png?table=block&id=70a44401-b8e3-42dd-88db-354c68dde13f&cache=v2)
Output Push Pull 推挽输出,这是一种可以负载较大电流的输出方式,一般由两个互补的三极管或 MOS 管构成,可以简单理解为,上下各一个开关,两个开关状态互补,一个导通则另一个一定关闭。如图是一个基于 MOS 管的结构,当上管导通,下管不导通,则输出端连接 VDD 输出高电平,反之连接 VSS 输出低电平。
按如图所示设置好每个引脚,然后点击 GENERATE CODE 生成代码。
编码规范入门
打开 Keil。如果提示代码被修改,一律选择是即可,这是 CubeMX 修改代码后的结果。
在项目中默认包含四个文件夹:
- Application/MDK-ARM 中包含的是一个汇编文件,用于启动单片机
- Application/User/Core 包含用户核心文件,包括 main.c 和其他外设配置文件
- Drivers/STM32F4xx_HAL_Driver 包含用到的所有用到的 HAL 库文件
- Drivers/CMSIS 包含内核相关的文件。
【教程点此】工程中,我们通过新建文件夹管理源码,以提高代码的可移植性和可读性。
在这里我们打开 main.c 文件,main 函数就位于这个文件中,实际上这里的 main 函数并不是整个程序的开始,链接器会将启动程序添加在 main 函数前,但它是 C 语言编写程序的开始,我们在工程上一般不关心进入 main 函数之前发生的事情。
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F4b7ca86c-d5bb-4419-83a3-89ebf0bb191f%2Fd65dbbde-876f-4018-b96b-45f0a66965a5%2FUntitled.png?table=block&id=ba7b7b17-8cd1-4e66-947c-14dffa838c80&cache=v2)
我们开始写程序,
main
函数中的 while(1){}
称为主循环,主循环前的部分称为初始化。在这里我们可以看到不同的初始化函数,包括 HAL 初始化、系统时钟初始化、通过 STM32CubeMX 配置的外设初始化(这里只有 GPIO)。在由 STM32CubeMX 生成的文件中,我们的代码应该写在
/* USER CODE BEGIN X */
和/* USER CODE END X */
等类似的注释之间,只有在这些区域的代码才不会在下一次 CubeMX 生成代码时被覆盖。省流:不写在注释里面代码就没了。编程
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
这个函数用于写引脚状态。GPIO_TypeDef* GPIOx
:GPIO 的分组,例如本案例中为 GPIOH;
uint16_t GPIO_Pin
:GPIO 引脚号,GPIO_PIN_X
这种写法实际上是一个对uint16_t
数的宏定义,所以可以使用位运算 “|” 一次设置多个引脚。
GPIO_PinState PinState
:引脚状态,GPIO_PIN_SET 表示置位,即高电平,GPIO_PIN_RESET 表 示复位,即低电平。这实际是 enum 类型,因此也有用 1 表示置位,0 表示复位的写法。
void HAL_Delay(uint32_t Delay);
这个函数用于延时,使程序等待一定时间,单位为 ms。实验
初始化部分:将三个引脚置位,此时 LED 灯珠显示白色;延时 1000ms;将三个引脚复位,理论上此时熄灭,但实际上因为进入主循环后有引脚被置位,因此观察不到熄灭的现象。
主循环部分:本段程序依次置位 LED_B,LED_G,LED_R 对应的引脚,在延迟 1000ms 后复位,并置位下一个引脚。
代码下载之后在开发板上按 RST 按键重置单片机,程序开始执行。本案例最终效果为,LED 显示白色 1 秒后,按蓝色,绿色,红色的顺序每 1 秒切换一次。