一灯大师-点亮LED灯

基础篇

哔哩哔哩视频地址

选择开发板

开发板

可以看到主控芯片是STM32F412RET6

第一步:学习并使用CubeMX建立Keil5工程

选择芯片

输入STM32F412RET6后双击STM32F412RET6打开芯片配置界面

学习并配置时钟树

将Disable下拉选择第三个开启外部高速时钟

打开时钟树学习了解时钟树

配置时钟树,直接将性能拉满,注意一个小细节我选择的开发板上外部焊接的晶振是12MHz,需要进行修改

学习并配置IO口

先查看原理图,选择LED所在的引脚,可以看到红色LED灯是PA13,绿色是PA14,黄色是PA15,可以看出LED的阴极接了地,电流流向是从左到右的,所以引脚如果输出高电平相应的LED就会亮,反之输出低电平就会灭

选择引脚,学习引脚配置,引脚命名为LED_R用来告诉自己这个引脚是给红色LED用的,配置默认电压为低电平所以程序烧入的开发板运行灯是不会亮的,除非默认为高电平烧录进去运行就会亮

配置其他选项并创建工程

配置工程名字和生成路径,将工程选择为Keil5工程

勾选C文件和头文件分离然后点击生成工程

生成工程后会弹出这个,右边按键的打开工程文件夹,中间是用Keil5打开工程,右边是关闭这个弹窗

先打开文件夹了解一下工程文件结构

第二部:打开工程并学习烧写程序

学习Keil5工程基本信息

然后我们尝试编译一遍,一般按编译那里三个按键的中间那个按键或者按键盘F7也可以,一般是不会有错误或者警告的如果有就说明生成工程出了问题,建议重新生成一遍工程,确保生成流程没有一个警告

第一次编译和重构都会慢很多工程越大编译越慢,可以尝试下面的方法

什么是函数跳转功能,就是我们不知道这个函数干了什么就可以跳转到这个函数的本体位置,直接查看函数的代码写了什么,我们拿GPIO的初始化函数举例,选中这个函数然后右键点去到定义这个函数的地方,也可以按键盘F12跳转

跳转过去正好看看引脚初始化干了什么,有没有CubeMX配置的东西

简单的学习了工程之后就可以尝试直接将生成好的工程编译烧录到单片机中,需要先连接好烧录器与单片机,需要连接好以下接口,然后插上电脑

3.3V --> 3.3V 给单片机供电

CLK --> CLK 给烧录的时钟信号

DIO --> DIO 给单片机供电

3.3V --> 3.3V 给单片机供电

烧录程序前一定要编译且没有错误,尽量不要有警告,实在无法避免的警告最好屏蔽掉,然后打开魔法棒配置烧录器

打开Settings可以看到框的内容,表示已经识别到芯片,就可以直接点下载烧录了,如果配置的是低电平则红灯应该是灭的,其他引脚的灯状态就无法确定,可能是亮可能是灭可能是微亮,因为引脚是没有配置的实际运行是无法确定引脚的状态的,小伙伴可以尝试把红灯引脚配置为默认高电平,这样下载进去板子默认就亮红灯,如果下载程序后没有反应需要手动按一下RST键,也可以勾选下图里面的Flash Download里面的Reset and Run,然后重新下载程序

正常来说默认配置就可以识别到芯片,但是如果无法识别到芯片可以尝试以下几种办法:

  • 修改这几个框里面的选项有可能也可以识别到芯片,然后正常下载程序
  • 按住单片机上RST按键再点Settings,如果可以看到的话再试试按住RST点下载然后迅速松手,有可能可以成功烧录程序,一般这样的情况成功烧录一次之后就正常了
  • 还可以按住单片机的BOOT0键再按一下RST键然后都松手进入IAP模式,再查看是否识别芯片,再同样的手法下载程序

使用到的HAL库函数说明

[点击跳转F4的GPIO手册](STM32F479xx HAL User Manual: stm32f4xx_hal_gpio.c File Reference (wisemcu.cn))

1
2
3
4
5
6
7
8
/* 作用为延时函数,单位为1ms */
void HAL_Delay(uint32_t Delay);
/* 反转引脚状态 */
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
/* 读引脚状态 */
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
/* 写引脚状态 */
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);

以下是手册内的函数解释

学习如何点灯

尝试将灯点亮,在GPIO初始化后通过写引脚状态函数将引脚输出状态改为高电平,其实这里 LED_R_GPIO_Port 就是GPIOA,LED_R_Pin 就是 GPIO_PIN_13,GPIO_PIN_SET就是设置为1的意思,这里高电平表示1低电平表示0,通过这种方法就可以让写函数知道要将PA13引脚改成高电平输出

1
2
3
4
5
6
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* 将代码写在BEGIN和END之间 */
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
/* USER CODE END 2 */

然后再编译下载到板子上然后按下复位就可以看到红灯亮起

然后我多尝试一下,CubeMX配置一下绿灯和黄灯引脚为默认低电平然后重新生成工程,再编译下载程序按下复位查看灯的情况

因为配置了绿黄的引脚为低电平,所以确定了引脚状态绿黄都灭掉了,只有红灯亮着,因为我将写红色引脚的函数写在了BEGIN和END之间,将红色引脚写成高电平的函数还在所以程序会将红色灯点亮

到此我已经完成了点灯功能并学习了如何用CubeMX配置时钟和GPIO创建工程,如何配置工程编译程序下载到板子上,其他类型的板子都是同理的,只要有原理图就可以。

练习部分

如何让红灯一闪一闪的?下面这样写有用吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* 将代码写在BEGIN和END之间 */
if(HAL_GPIO_ReadPin(LED_R_GPIO_Port, LED_R_Pin) == GPIO_PIN_SET) // 读引脚状态,判断是不是是高电平
{
/* 引脚是高电平 */
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); // 将引脚置为低电平
}else{
/* 引脚不是高电平 */
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET); // 将引脚置为高电平
}
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

是不是发现红灯常亮了?

这是因为亮灭切换速度太快了,灭的时间太短了,人的肉眼无法观测到,但是亮的时候会发光可以观测到,所以解决办法是加上延时,让亮灭的时间变慢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* 将代码写在BEGIN和END之间 */
if(HAL_GPIO_ReadPin(LED_R_GPIO_Port, LED_R_Pin) == GPIO_PIN_SET) // 读引脚状态,判断是不是是高电平
{
/* 引脚是高电平 */
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET); // 将引脚置为低电平
}else{
/* 引脚不是高电平 */
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET); // 将引脚置为高电平
}
HAL_Delay(500); // 延时500ms,也就是0.5s,这样亮灭一个周期就是一秒
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

这样就实现了一个灯周期为一秒的亮灭,那我再提几个小问题,答案下一篇博客结尾答复

  • 请问还有更加简洁代码的办法实现吗?

提示可以看看反转函数

  • 可以实现三个灯的流水灯吗?

就是 红灯灭 -> 红灯亮 -> 红灯灭 -> 绿灯亮 -> 绿灯灭 -> 黄灯亮 -> 黄灯灭 -> 红灯亮 这样的循环

  • 可以实现三个灯的往返流水灯吗?

就是 红灯灭 -> 红灯亮 -> 红灯灭 -> 绿灯亮 -> 绿灯灭 -> 黄灯亮 -> 黄灯灭 -> 黄灯亮 -> 黄灯灭 -> 绿灯亮 -> 绿灯灭 -> 红灯亮 这样的循环

  • 有什么办法可以实现通过按键来点LED灯,按键按下LED灯亮起,松开按键LED灭?

提示:因为按键需要将引脚配置为输入模式,所以如果没有硬件上下拉电阻而且按键又没有按下的情况下就会无法确定按键的电压状态,所以软件需要配置上下拉电阻来确保默认状态,上拉就是引脚通过电阻接到了高电平上,下拉就是通过电阻接到地上,因为我们要检测按键所以我们希望按键没按下引脚是一种稳定状态,按键按下就变成另一个稳定状态,实际情况需要结合原理图

前面的区域以后再来探索吧

  • 有没有办法只开GPIO外设实现手机的呼吸灯的感觉?

呼吸灯就是灯由暗缓慢变亮,再又亮缓慢的变暗,提示了解PWM波原理和实现微妙级的延时

进阶篇

先预告,等基础部分搞得差不多的时候开工