文章目录
- 一、 STM32F4 IO 口简介
- 二、硬件设计
- 三、软件设计
- 1.位带操作(F7除外)
- 四、实验现象
- 五、STM32CubeMX 配置 IO 口输入
在本章中,我们将通过代码控制
ALIENTEK
阿波罗
STM32
开发板上的两个
LED
灯
DS0
和
DS1
交替闪烁,实现类似跑马灯的效果。
一、 STM32F4 IO 口简介
这部分内容可参考STM32F4 | GPIO工作原理和配置。
二、硬件设计
本章用到的硬件只有 LED
(DS0
和 DS1
)。其电路在 ALIENTEK
阿波罗 STM32
开发板上默认是已经连接好了的。DS0
接 PB1
,DS1
接 PB0
。所以在硬件上不需要动任何东西。其连接原理图如下:
三、软件设计
我们直接复制前面创建好的工程模板——库函数版本,将复制过来的模板文件夹重新命名为“1-跑马灯实验”。在模板里面的 HALLIB
分组下面,我们引入了所有的 HAL
库源文件和对应的头文件,如下图所示:
实际上,这些大家可以根据工程需要添加。跑马灯实验我们一共使用到 HAL
库中 9 个源文件,其他不用的源文件大家可以直接在工程中删除。这样可以大大减少工程编译时间。
在工程根目录文件夹下面新建一个 HARDWARE
的文件夹,用来存储与硬件相关的代码。然后在 HARDWARE
文件夹下新建一个 LED
文件夹,用来存放与 LED
相关的代码。
接下来, 我们回到我们的工程,新建一个文件,然后保存在HARDWARE->LED
文件夹下面,保存为 led.c
,
在led.c
文件中输入以下代码:
#include "led.h"
/*
函数名称:LED_Init
函数作用:LED初始化配置
输 入:无
输 出:无
*/
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Initure; //定义结构体变量,结构体成员为GPIO的相关模式和状态
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启 GPIOB 时钟
//设置多个IO口,并且在同一个分组下,并且每个IO的配置都是一样的,就可以通过“|”来设置
GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //指定IO口:PB1,0
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //模式设置:推挽输出;GPIO_MODE_OUTPUT_OD是开漏输出
GPIO_Initure.Pull=GPIO_PULLUP; //上下拉设置:上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //速度设置:高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
//设置一组 IO 口中的一个或者多个 IO 口的电平状态
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //PB0 置 1 ,默认灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); //PB1 置 1 ,默认灯灭
}
其头文件为led.h
:
#ifndef _LED_H
#define _LED_H
#include "sys.h"
//宏定义LED控制管脚
#define LED0 PBout(1) //LED0 PB1
#define LED1 PBout(0) //LED1 PB0
//声明函数
void LED_Init(void);
#endif
我们在 Manage Project Itmes
管理里面新建一个 HARDWARE
的组,并把 led.c
加入到这个组里面。
再将 led.h
头文件的路径加入到工程里面
打开main.c
文件,编写如下:
/*
实验:跑马灯实验
实验现象:LED0 和 LED1 循环闪烁
*/
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180MHz
delay_init(180);
LED_Init();
while (1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); //LED0 亮
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //LED1 灭
delay_ms(500); //延时 500ms
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); //LED0 灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //LED1 亮
delay_ms(500);
}
}
至此,整个程序就编写完成,我们编译一下,如下图所示:
1.位带操作(F7除外)
位操作原理: 把每个比特膨胀为一个32位的字,当访问这些字的时候就达到了访问比特的目的,比如说BSRR
寄存器有32个位,那么可以映射到32个地址上,我们去访问(读-改-写)这32个地址就达到访问32个比特的目的。
位带操作的优越性:
修改 main()
函数,直接通过位带操作达到同样的效果,位带操作的代码如下:
int main(void)
{
HAL_Init(); //初始化 HAL 库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
LED_Init(); //初始化 LED
while(1)
{
LED0=0; //LED0 亮
LED1=1; //LED1 灭
delay_ms(500);
LED0=1; //LED0 灭
LED1=0; //LED1 亮
delay_ms(500);
}
}
当然,我们也可以通过直接操作相关寄存器的方法来设置 IO
,我们只需要将主函数main.c
修改为如下内容:
int main(void)
{
HAL_Init(); //初始化 HAL 库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
LED_Init(); //初始化 LED
while(1)
{
GPIOB->BSRR=GPIO_PIN_1; //LED0 亮
GPIOB->BSRR=GPIO_PIN_0<<16; //LED1 灭
delay_ms(500); //延时 500ms
GPIOB->BSRR=GPIO_PIN_1<<16; //LED0 灭
GPIOB->BSRR=GPIO_PIN_0; //LED1 亮
delay_ms(500); //延时 500ms
}
}
四、实验现象
使用 USB
线将开发板和电脑连接成功后(电脑能识别开发板上 CH340
串口),把编译后产生的.hex
文件烧入到芯片内。实验现象:LED0
和 LED1
循环闪烁。
五、STM32CubeMX 配置 IO 口输入
使用STM32CubeMX
配置 GPIO
口的步骤如下:
-
第一步,打开
STM32CubeMX
工具,在引脚图中选择要配置的IO
口。这里我们选择PB0
为例,在弹出的下拉菜单中选择要配置的IO
口模式,如下图所示:
从上图可以看出,这里我们除了配置IO
口为输入输出之外,还可以选择IO
口的复用功能或者作为外部中断引脚功能,比如我们要选择IO
口复用为ADC1
的通道 8 引脚,那么我们只需要选选项ADC1_IN8
即可。对于本章跑马灯实验,PB0
是作为输出,所以我们选GPIO_Output
即可。 -
第二步,进入
Configuration->GPIO
,在弹出的界面配置IO
口的详细参数。如下图所示:
在IO
口详细参数配置界面,点击我们要配置的IO
口,会在窗口下方显示该IO
口配置的详细参数表,下面我们依次来解释这些配置项的含义:- 选项
GPIO output level
用来设置IO
口初始化电平状态为High
(高电平)还是Low
(低电平)。本实验我们设置为默认输出高High
。 - 选项
GPIO mode
用来设置输出模式为Output Push Pull
(推挽)还是Output Open Drain
(开漏)。本实验我们设置为推挽输出Output Push Pull
。 - 选项
GPIO Pull-up/Pull-down
用来设置IO
口是上拉/下拉/没有上下拉。本实验我们设置为上拉(Pull-up
)。 - 选项
Mzximum ouput speed
用来设置输出速度为高速(Hign
)/快速(Fast
)/中速(Medium
)/低速(Low
)。本实验我们设置为高速High
。 - 选项
User Label
是用来设置初始化的IO
口Pin
值为我们自定义的宏,一般情况我们可以不用设置。
- 选项
-
生成工程源码。接下来打开工程的 main.c 文件可以看到,该文件内部由
STM32CubeMX
生成了函数MX_GPIO_Init
,内容如下:void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ // __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_SET); /*Configure GPIO pins : PB0 PB1 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); }
该函数的作用跟前面讲解的跑马灯实验中 LED_Init
函数作用一模一样,有兴趣的同学可以直接修改跑马灯实验工程源码,把 LED_Init
函数内容修改为 MX_GPIO_Init
内容,大家会发现实验效果一模一样。
一般情况下,STM32CubeMX
的主要作用是配置时钟系统和外设初始化函数。所以我们对外设进行配置之后,生成外设初始化代码,然后把该代码应用到我们工程即可。