文章目录
前言
关于这个系列
本人学习STM32是从标准库开始学习的,大学期间一直也都使用的是标准库,毕竟正点原子亦或者网上的标准库例程资源很是丰富,学习使用起来很是方便。关于使用HAL库的契机,是因为此前有一次备战蓝桥杯的嵌入式比赛,比赛要求使用STM32G4系列的开发板,大赛官方提供了开发板的HAL库的例程,而且在正式比赛的时候也只能使用CubeMX生成初始化代码,在一段时间学习与适应之后,体会到使用HAL库在开发过程中的一些相较于标准库的便利之处。而且我们不可能一直使用某一种系列的单片机,STM32有很多别的系列单片机可能没有那么多的标准库资源,因此在今后的学习使用中开始向HAL库进行倾斜。马上就要开始电赛了,打算趁这段时间整理一下思路,从最简单的跑马灯开始,复现一下不管是正点原子还是野火等教学的各种实战应用。本系列就以正点原子的实战篇内容为顺序,使用HAL库进行复现,可能实现的效果与其有所不同,但主要是把流程都过一遍,理清一下思路。
- 内容讲述不是很详细,适合有标准库或寄存器开发经验的读者,主要是理清思路过程,如有问题可以交流沟通 peace~
关于本人
菜鸡一个,分享经验,互相学习~
系列目录
(–陆续更新–)
项目内容
- 跑马灯实现(利用延时函数)
- 按键输入实现(按键扫描)
内容分析
这两个部分比较简单,而且所需要的知识点也比较相近,都是关于IO口的基础配置,因此将两部分放在了一起。简单来说:
- 跑马灯使用了IO口的输出功能;
- 按键输入(按键扫描)利用了IO口的输入功能;
关于IO口
我们只需要简单了解一下IO口的几种工作模式,如下表
功能 | 分类 |
---|---|
通用输出 | 推挽式(Push-Pull) |
开漏(Open-Drain) | |
复用功能输出 | 推挽式(Push-Pull) |
开漏(Open-Drain) | |
输入 | 模拟输入 |
浮空输入 | |
上拉输入 | |
下拉输入 |
简单来说
- 两种输出模式
- 四种输入模式
项目实现
CubeMX配置
1. 打开STM32CubeMX新建工程
根据所用单片机的型号新建工程(我所用的是正点原子的精英板,即STM32F103ZET6),双击所选型号即可进入配置页面。
2. 配置控制LED的IO
-
根据开发板原理图,得知控制两个LED灯的IO口分别为PB5和PE5,且均为低电平工作
-
在配置页面中找到PB5和PE5均配置为输出模式(GPIO_Output)
-
在左边的选项栏中可以进一步配置GPIO
-
比较关键的两个配置是:工作模式(GPIO_mode)、拉高/拉低(GPIO Pull-up/Pull-down),我们就使用默认的推挽输出(Push-Pull),并将GPIO拉高(Pull-up),因此在初始化之后,默认情况下LED应该是不工作的。
3. 配置控制按键的IO
-
按键的配置方式与LED类似,只是功能需要配置为输入模式
-
根据原理图
- 控制按键KEY0和KEY1的IO口分别为PE4和PE3
- 按键按下时输入低电平(GND)
-
配置PE3和PE4为输入模式(GPIO_Input),且IO口拉高
4.保存工程,生成代码
需要关注的部分已经标注了,分别为
- 工程名称
- 工程保存路径
- 使用的IDE(视自身情况嗷,Keil选择MDK,版本号无所谓)
- 生成.c与.h文件
- 右上角生成代码
代码实现
软件层面就比较简单了,对于GPIO的操作记住下面儿三个关键的函数,分别为
- 读操作
- 写操作
- 翻转操作(库函数中没有的神技)
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
/* ↑返回值为
GPIO的状态
包括: //GPIO读操作
* GPIO_PIN_SET
* GPIO_PIN_RESET
*/
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
//GPIO写操作
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
//GPIO状态翻转
HAL库中的延时函数与库函数中的类似
__weak void HAL_Delay(uint32_t Delay) //延时函数(ms)
综上我们可以实现我们所需的功能了
注意! 在使用CubeMX生成的代码进行开发时,不要修改其中的自动生成的注释,而且我们自己修改的代码要写在/* ------ BEGIN------ * /与/* ------ END------ * /之间,这样是为了使用CubeMX再次进行配置时,不会对我们自己写的代码产生影响。如下所示
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//代码从这里开始写!
}
/* USER CODE END 3 */
跑马灯
通过延时函数实现两个灯交替闪烁
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_WritePin ( GPIOB , GPIO_PIN_5 , GPIO_PIN_SET );
HAL_GPIO_WritePin ( GPIOE , GPIO_PIN_5 , GPIO_PIN_RESET );
HAL_Delay( 500 );
HAL_GPIO_WritePin ( GPIOB , GPIO_PIN_5 , GPIO_PIN_RESET );
HAL_GPIO_WritePin ( GPIOE , GPIO_PIN_5 , GPIO_PIN_SET );
HAL_Delay( 500 );
}
/* USER CODE END 3 */
按键扫描
按键控制LED亮灭
uint8_t key_scan(void)
{
uint8_t key = 0;
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3) == GPIO_PIN_RESET)
{
key = 1;
}
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4) == GPIO_PIN_RESET)
{
key = 2;
}
return key;
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
key = key_scan();
switch (key)
{
case 1: HAL_GPIO_TogglePin ( GPIOB, GPIO_PIN_5 ); break;
case 2: HAL_GPIO_TogglePin ( GPIOE, GPIO_PIN_5 ); break;
}
}
/* USER CODE END 3 */
两个功能我是分开来写的,按键和LED的配合的功能和玩法还有很多,就不再拓展了。其中还有很多的细节没有展示,包括函数的声明定义啊之类的,这些基础知识是与库函数开发相同的点。
系列目录
(–陆续更新–)