金名的STM32F407单片机标准库开发(二)–点亮LED灯
在金名的STM32F407单片机标准库开发(一)
中我们编写了一段代码,相信即使是C语言大佬,初次看到这段代码也会很迷茫,无法理解这段代码的含义。确实,STM32单片机的代码,尤其是涉及到硬件操作的部分,对于初学者来说可能会显得有些复杂。这是因为它涉及到对硬件寄存器的直接或间接操作,这与普通的C语言编程有很大的不同。对于初学者来说,这确实是一个挑战。不过,随着学习的深入,你会逐渐熟悉这些操作,并能够更好地理解和编写代码。接下来我们将一起学习STM32单片机的第一个外设——GPIO(General Purpose Input/Output,通用输入输出)外设。
一、什么是外设?
在学习GPIO之前,首先需要澄清一个概念:什么是外设?
如果你有《计算机组成原理》的背景,对外设这个术语应该不会陌生。不过,在单片机领域,外设的定义与传统计算机外设有所不同。在计算机中,外设指的是那些与计算机主机相连的外部设备,比如键盘、鼠标、显示器和打印机等,它们是计算机与外界交换信息的重要工具。
而在单片机领域中,外设则指的是单片机内部集成的一系列功能模块。这些模块使得单片机能够与外部世界进行信息交互,并执行特定的任务。例如,ADC模块可以将模拟信号转换为数字信号,UART模块可以实现串行通信,而GPIO模块则提供了基本的输入输出功能。通过编程控制这些内部模块,单片机能够实现数据采集、信号处理、通信和用户交互等多种功能,从而在嵌入式系统和物联网设备中发挥关键作用。
二、什么是GPIO?
作为大多数人学习单片机时接触的第一个外设,GPIO(General Purpose Input/Output 通用输入输出)外设的重要性是不言而喻的。它是单片机开发最重要最基础的硬件资源之一,为单片机提供了与外部进行交互的数字接口。通过GPIO端口,开发者可以控制LED灯的亮灭、读取按钮的状态、驱动电机等,这些基本操作构成了单片机应用的基础。
我们开发板所使用的STM32F407VET6
芯片共有100个引脚,其中有82个引脚是GPIO端口,这些IO引脚分为五组,分别是GPIOA~GPIOE,每组包含16个引脚。这些引脚输入模式下通常能够承受的电压范围是0到3.3V,少数可以容忍5V;而输出模式最大只能输出3.3V。如图我们所使用的开发板引出了75个可用IO引脚。
三、GPIO 的工作模式
GPIO外设通常包含多个引脚,每个引脚都可以被配置为输入或输出模式,以适应不同的应用场景。在输入模式下,GPIO引脚可以作为数字信号的接收端,例如读取按钮的状态。而在输出模式下,GPIO引脚则可以作为控制信号的发送端,用来驱动LED灯或其他电子元件。
GPIO输入模式
- 浮空输入(Input Floating):
-
引脚不连接内部上拉或下拉电阻,输入信号由外部电路决定。
- 上拉输入(Input with Pull-up):
- 引脚内部连接一个上拉电阻到Vcc,适用于外部开关或按键接地的情况。
- 下拉输入(Input with Pull-down):
- 引脚内部连接一个下拉电阻到GND,适用于外部开关或按键接Vcc的情况。
-
模拟输入(Analog Mode):
- 引脚用作模拟信号输入,通常用于ADC(模拟数字转换器)。
GPIO输出模式
-
推挽输出(Push-Pull Output):
- 引脚可以输出高电平(连接到Vcc)和低电平(连接到GND),适用于驱动LED或一般的数字电路。
推挽输出之“挽”
-
开漏输出(Open-Drain Output):
- 引脚只能输出低电平(连接到GND),高电平由外部上拉电阻决定。这种模式常用于I2C等通信协议。
开漏输出之“开”
开漏输出之“漏”
- 复用推挽输出(Alternate Function Push-Pull):
- 引脚在复用功能(如USART、SPI、I2C等)和推挽输出之间切换。
-
复用开漏输出(Alternate Function Open-Drain):
- 引脚在复用功能(如USART、SPI、I2C等)和开漏输出之间切换。
复用开漏输出
本章点亮LED灯使用GPIO的推挽输出模式,输入模式将在以后进行讲解。
四、配置GPIO点亮LED
硬件准备
使用外接LED灯进行实验演示,使用GPIOC9引脚,LED灯引脚长正短负,我们使用母对母杜邦线将正极与开发板的C9连接,负极与GND连接。
端口配置
单片机的所有外设资源时钟默认都是关闭的,在使用之前我们需要进行相应的初始化。
配置STM32F407的GPIO为推挽输出模式:
1. 使能GPIO的端口时钟,为GPIO外设提供心脏
- 查阅芯片手册可知,所有GPIO外设的时钟都是由AHB1总线提供。
- 通过RCC(Reset and Clock Control)模块使能对应GPIO端口的时钟。
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
2. 配置 GPIO 点亮 LED
-
进行 GPIO 初始化需要先了解都要配置哪些东西,打开
STM32f4xx_gpio.h
头文件,查看 GPIO 初始化结构体声明:/** * @brief GPIO Init structure definition */ typedef struct { uint32_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOOType_TypeDef GPIO_OType; /*!< Specifies the operating output type for the selected pins. This parameter can be a value of @ref GPIOOType_TypeDef */ GPIOPuPd_TypeDef GPIO_PuPd; /*!< Specifies the operating Pull-up/Pull down for the selected pins. This parameter can be a value of @ref GPIOPuPd_TypeDef */ }GPIO_InitTypeDef;
由此
GPIO_InitTypeDef
结构体可知在初始化中需要五个结构体成员。 -
第一个
GPIO_Pin
选择要使用的引脚,从stm32f4xx_gpio.h
的头文件中可知:/** @defgroup GPIO_pins_define * @{ */ #define GPIO_Pin_0 ((uint16_t)0x0001) /* Pin 0 selected */ #define GPIO_Pin_1 ((uint16_t)0x0002) /* Pin 1 selected */ #define GPIO_Pin_2 ((uint16_t)0x0004) /* Pin 2 selected */ #define GPIO_Pin_3 ((uint16_t)0x0008) /* Pin 3 selected */ #define GPIO_Pin_4 ((uint16_t)0x0010) /* Pin 4 selected */ #define GPIO_Pin_5 ((uint16_t)0x0020) /* Pin 5 selected */ #define GPIO_Pin_6 ((uint16_t)0x0040) /* Pin 6 selected */ #define GPIO_Pin_7 ((uint16_t)0x0080) /* Pin 7 selected */ #define GPIO_Pin_8 ((uint16_t)0x0100) /* Pin 8 selected */ #define GPIO_Pin_9 ((uint16_t)0x0200) /* Pin 9 selected */ #define GPIO_Pin_10 ((uint16_t)0x0400) /* Pin 10 selected */ #define GPIO_Pin_11 ((uint16_t)0x0800) /* Pin 11 selected */ #define GPIO_Pin_12 ((uint16_t)0x1000) /* Pin 12 selected */ #define GPIO_Pin_13 ((uint16_t)0x2000) /* Pin 13 selected */ #define GPIO_Pin_14 ((uint16_t)0x4000) /* Pin 14 selected */ #define GPIO_Pin_15 ((uint16_t)0x8000) /* Pin 15 selected */ #define GPIO_Pin_All ((uint16_t)0xFFFF) /* All pins selected */
-
第二个
GPIO_Mode
选择引脚的工作模式,从stm32f4xx_gpio.h
的头文件中可知 STM32 的工作模式,在上文有所介绍:typedef enum { GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */ GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */ GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */ }GPIOMode_TypeDef;
-
第三个
GPIO_Speed
配置的是 GPIO 的频率,从stm32f4xx_gpio.h
的头文件中可知 STM32F4 提供了四种速度模式:typedef enum { GPIO_Low_Speed = 0x00, /*!< Low speed */ GPIO_Medium_Speed = 0x01, /*!< Medium speed */ GPIO_Fast_Speed = 0x02, /*!< Fast speed */ GPIO_High_Speed = 0x03 /*!< High speed */ }GPIOSpeed_TypeDef; /* Add legacy definition */ #define GPIO_Speed_2MHz GPIO_Low_Speed #define GPIO_Speed_25MHz GPIO_Medium_Speed #define GPIO_Speed_50MHz GPIO_Fast_Speed #define GPIO_Speed_100MHz GPIO_High_Speed
-
第四个是
GPIO_OType
配置输出类型:typedef enum { GPIO_OType_PP = 0x00, GPIO_OType_OD = 0x01 }GPIOOType_TypeDef;
-
第五个是
GPIO_PuPd
配置引脚有无上下拉:typedef enum { GPIO_PuPd_NOPULL = 0x00, GPIO_PuPd_UP = 0x01, GPIO_PuPd_DOWN = 0x02 }GPIOPuPd_TypeDef;
那么配置 PC9 为推挽输出,速度为 100MHZ,只需要传入对应的参数即可。转换为代码为:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // 选择引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 速度
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出类型
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 不使用上下拉
GPIO_Init(GPIOC, &GPIO_InitStructure);
3. 主函数中控制 LED 灯
- 使用标准库提供的函数读写 GPIO 引脚的状态。
// 配置PC9引脚输出高电平 GPIO_SetBits(GPIOC, GPIO_Pin_9); // 配置PC9引脚输出低电平 GPIO_ResetBits(GPIOC, GPIO_Pin_9); // 配置PC9引脚输出高电平 GPIO_WriteBit(GPIOC, GPIO_Pin_9, 1); // 配置PC9引脚输出高电平 GPIO_WriteBit(GPIOC, GPIO_Pin_9, 0);
以下是 main.c 完整代码:
#include "stm32f4xx.h"
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000; //自己定义
while(i--) ;
}
}
int main(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // 选择引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 速度
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出类型
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 不使用上下拉
GPIO_Init(GPIOC, &GPIO_InitStructure);
while (1)
{
// 配置PC9引脚输出高电平
GPIO_SetBits(GPIOC, GPIO_Pin_9);
delay_ms(200);
// 配置PC9引脚输出低电平
GPIO_ResetBits(GPIOC, GPIO_Pin_9);
delay_ms(200);
// 配置PC9引脚输出高电平
GPIO_WriteBit(GPIOC, GPIO_Pin_9, 1);
delay_ms(200);
// 配置PC9引脚输出高电平
GPIO_WriteBit(GPIOC, GPIO_Pin_9, 0);
delay_ms(200);
}
}
效果如图:
结语
在本教程中,我们深入探讨了STM32F407单片机的GPIO外设,并成功实现了点亮LED灯的基本操作。通过详细的步骤和代码示例,我们不仅学习了GPIO的基本概念和工作模式,还掌握了如何配置GPIO引脚以及如何通过软件控制硬件输出。这些技能是嵌入式系统开发中不可或缺的,它们为我们打开了探索更复杂功能的大门。
随着对STM32单片机编程的进一步学习,我们可以期待实现更多高级功能,如PWM控制、I2C通信、SPI通信等。这些功能将使我们能够构建更加复杂和强大的嵌入式系统,为各种应用提供支持。掌握GPIO的使用不仅是单片机学习的起点,也是成为一名优秀嵌入式系统开发者的基石。
在未来的学习旅程中,我们将继续探索STM32单片机的更多外设和功能,不断扩展我们的知识边界,提升我们的技能水平。让我们携手并进,共同在嵌入式开发的海洋中乘风破浪,创造出更多令人惊叹的作品。
标签:输出,LED,Pin,引脚,--,selected,GPIO,STM32F407,define From: https://blog.csdn.net/m0_57214536/article/details/144679336