文章目录
- 前言
- 一、GPIO介绍
- 1.GPIO是什么
- 2.GPIO命名规则
- 三、LED灯本质及原理图
- 1.LED本质
- 2.LED原理图分析
- 四、实验代码编写
- 1.配置GPIO为输出模式的步骤
- 2.设置GPIO电平状态函数
- 3.具体代码编写
- 总结
前言
本篇文章将带大家开始学习国产芯片GD32,这套文章将涵盖基础篇,进阶篇,高级篇,项目篇,本套教程将使用GD32F407VET6开发板。(开发板采用光子物联开发板)
一、GPIO介绍
1.GPIO是什么
GPIO是"General Purpose Input/Output"(通用输入/输出)的缩写,它是数字电路中常见的一个概念,也是嵌入式系统中常用的一个功能模块。
GPIO允许嵌入式系统与外部世界进行通信,它通过将数字信号转换为电压或电流的形式与外部设备进行交互。GPIO引脚可以被配置为输入或输出,这意味着它们可以被用来读取外部设备的状态(如传感器、开关等)或控制外部设备的行为(如LED灯、电机、继电器等)。
在嵌入式系统中,GPIO通常由微控制器或微处理器的引脚提供支持。通过软件配置和控制GPIO,嵌入式系统可以实现各种输入和输出功能,从而实现与外部环境的交互和控制。
2.GPIO命名规则
字母表示端口:字母通常代表了GPIO引脚所在的端口。端口是一组相连的引脚,它们通常由相同的硬件模块或者功能单元控制。例如,一个芯片可能有多个端口,每个端口负责不同的功能或者连接到不同的外部设备。字母可以是A、B、C等,每个字母代表一个端口。
数字表示引脚编号:数字部分表示了具体的GPIO引脚在其所在端口内的编号。通常,这些编号是从0开始的,依次递增。例如,GPIOA0表示端口A中的第一个引脚,GPIOA1表示端口A中的第二个引脚,依此类推。
三、LED灯本质及原理图
1.LED本质
LED是“Light Emitting Diode”的缩写,翻译为发光二极管。
LED的工作原理:LED是一种特殊类型的二极管。它的N型区域富含自由电子,P型区域富含空穴。当正向电压施加在LED的两端时,电子和空穴会在PN结处重组,这个过程释放出能量,而这部分能量会以光的形式发射出来,形成光线。这就是LED发光的原理。
这里我们需要知道LED灯其实就是一个发光二极管,当发光二极管被导通时LED灯就会被点亮,发光二极管截止时,LED灯被熄灭。
2.LED原理图分析
通过观察LED灯的原理图可以知道,我们只需要去控制PB4端口的电平状态就可以控制LED灯的状态,当PB4输出高电平时,发光二极管截止,LED灯熄灭,当PB4输出低电平时,发光二极管导通,LED灯被点亮。
四、实验代码编写
1.配置GPIO为输出模式的步骤
1.使能GPIO引脚
使能外设的时钟函数如下:
periph:这是一个枚举类型的参数,用于指定要启用时钟的外设。rcu_periph_enum 是一个枚举类型,包含了所有可能的外设。具体来说,它包括了处理器上的各种外设,比如GPIO、USART、SPI、I2C等等。通过传递相应的外设枚举值,函数可以识别并启用指定外设的时钟。
void rcu_periph_clock_enable(rcu_periph_enum periph);
rcu_periph_enum枚举类型:
typedef enum
{
/* AHB1 peripherals */
RCU_GPIOA = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 0U), /*!< GPIOA clock */
RCU_GPIOB = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 1U), /*!< GPIOB clock */
RCU_GPIOC = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 2U), /*!< GPIOC clock */
RCU_GPIOD = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 3U), /*!< GPIOD clock */
RCU_GPIOE = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 4U), /*!< GPIOE clock */
RCU_GPIOF = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 5U), /*!< GPIOF clock */
RCU_GPIOG = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 6U), /*!< GPIOG clock */
RCU_GPIOH = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 7U), /*!< GPIOH clock */
RCU_GPIOI = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 8U), /*!< GPIOI clock */
RCU_CRC = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 12U), /*!< CRC clock */
RCU_BKPSRAM = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 18U), /*!< BKPSRAM clock */
RCU_TCMSRAM = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 20U), /*!< TCMSRAM clock */
RCU_DMA0 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 21U), /*!< DMA0 clock */
RCU_DMA1 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 22U), /*!< DMA1 clock */
RCU_IPA = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 23U), /*!< IPA clock */
RCU_ENET = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 25U), /*!< ENET clock */
RCU_ENETTX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 26U), /*!< ENETTX clock */
RCU_ENETRX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 27U), /*!< ENETRX clock */
RCU_ENETPTP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 28U), /*!< ENETPTP clock */
RCU_USBHS = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 29U), /*!< USBHS clock */
RCU_USBHSULPI = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 30U), /*!< USBHSULPI clock */
/* AHB2 peripherals */
RCU_DCI = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 0U), /*!< DCI clock */
RCU_TRNG = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 6U), /*!< TRNG clock */
RCU_USBFS = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 7U), /*!< USBFS clock */
/* AHB3 peripherals */
RCU_EXMC = RCU_REGIDX_BIT(AHB3EN_REG_OFFSET, 0U), /*!< EXMC clock */
/* APB1 peripherals */
RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */
RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */
RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */
RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */
RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */
RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */
RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */
RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */
RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */
RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */
RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */
RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */
RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */
RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */
RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */
RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */
RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */
RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */
RCU_I2C2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< I2C2 clock */
RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */
RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */
RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */
RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */
RCU_UART6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 30U), /*!< UART6 clock */
RCU_UART7 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 31U), /*!< UART7 clock */
RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */
/* APB2 peripherals */
RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< TIMER0 clock */
RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 1U), /*!< TIMER7 clock */
RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< USART0 clock */
RCU_USART5 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< USART5 clock */
RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< ADC0 clock */
RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC1 clock */
RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC2 clock */
RCU_SDIO = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< SDIO clock */
RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */
RCU_SPI3 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< SPI3 clock */
RCU_SYSCFG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< SYSCFG clock */
RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 16U), /*!< TIMER8 clock */
RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 17U), /*!< TIMER9 clock */
RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 18U), /*!< TIMER10 clock */
RCU_SPI4 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< SPI4 clock */
RCU_SPI5 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< SPI5 clock */
RCU_TLI = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 26U), /*!< TLI clock */
/* APB1 additional peripherals */
RCU_CTC = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 27U), /*!< CTC clock */
RCU_IREF = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 31U), /*!< IREF clock */
}rcu_periph_enum;
2.配置GPIO的引脚模式
配置GPIO的引脚模式如下:
void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin)
gpio_periph:这是一个无符号32位整数,用于指定要配置的 GPIO 外设。通常,嵌入式系统中的每个 GPIO 外设都会有一个对应的寄存器,用于配置和控制该外设的 GPIO 引脚。通过传递相应的 GPIO 外设参数,函数可以识别并配置特定的 GPIO 外设。
这个参数一般传入GPIOA、GPIOB这种类型的参数
mode:这也是一个无符号32位整数,用于指定要设置的 GPIO 引脚的工作模式。GPIO 引脚可以配置为输入模式、输出模式或其他特定模式,比如复用模式。通过传递相应的模式参数,函数可以将 GPIO 引脚设置为所需的工作模式。
GPIO的模式就是使用的一些宏来表示的:
pull_up_down:同样是一个无符号32位整数,用于指定 GPIO 引脚的上拉或下拉电阻状态。在某些情况下,需要在 GPIO 引脚上启用上拉或下拉电阻,以确保稳定的信号传输。通过传递相应的参数,函数可以控制 GPIO 引脚上拉或下拉电阻的状态。
GPIO引脚可以设置为上拉、下拉、无上拉和下拉电阻等几个选项。
pin:最后一个参数是一个无符号32位整数,用于指定要配置的 GPIO 引脚的编号。在大多数嵌入式系统中,每个 GPIO 外设都有多个引脚可供选择,通过传递相应的引脚编号参数,函数可以指定要配置的特定 GPIO 引脚。
3.配置GPIO输出类型和速度
void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin)
gpio_periph:这是一个无符号32位整数,用于指定要配置的 GPIO 外设。类似于 gpio_mode_set 函数,通过传递相应的 GPIO 外设参数,函数可以识别并配置特定的 GPIO 外设。
otype:这是一个无符号8位整数,用于指定 GPIO 引脚的输出类型。GPIO 引脚可以配置为推挽输出或开漏输出两种类型。推挽输出可以提供高电平和低电平输出,而开漏输出通常用于构建开关电路或连接到开漏输出的器件。通过传递相应的参数,函数可以设置 GPIO 引脚的输出类型。
speed:这也是一个无符号32位整数,用于指定 GPIO 引脚的输出速度。GPIO 引脚的输出速度通常以 MHz 为单位进行定义,表示引脚可以支持的最大输出频率。通过传递相应的速度参数,函数可以设置 GPIO 引脚的输出速度。
pin:最后一个参数是一个无符号32位整数,用于指定要配置的 GPIO 引脚的编号。类似于 gpio_mode_set 函数,通过传递相应的引脚编号参数,函数可以指定要配置的特定 GPIO 引脚。
2.设置GPIO电平状态函数
设置GPIO引脚为高电平函数:
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
gpio_periph:这是一个无符号32位整数,用于指定要操作的 GPIO 外设。类似于其他 GPIO 相关函数,通过传递相应的 GPIO 外设参数,函数可以识别并操作特定的 GPIO 外设。
pin:这是一个无符号32位整数,用于指定要设置的 GPIO 引脚的编号。通过传递相应的引脚编号参数,函数可以指定要设置输出状态为高电平的特定 GPIO 引脚。
设置GPIO引脚为低电平函数:
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
这个函数的参数和上面这个函数的参数是一样的,这里就不多解释了。
3.具体代码编写
这里我们来使用上面的函数首先初始化GPIO引脚,并且设置为输出引脚,然后使用设置GPIO电平状态函数来让LED灯闪烁。
#include "gd32f4xx.h"//包含了该系列芯片的寄存器定义、常量定义和函数声明等信息
#include "gd32f4xx_libopt.h"//GD32F4 系列芯片的外设库选项配置文件
#include "systick.h"//配置和使用 SysTick 定时器的功能文件
int main(void)
{
systick_config();//配置系统主频168M,外部8M晶振,配置在#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL (uint32_t)(168000000)
rcu_periph_clock_enable(RCU_GPIOB);//使能GPIOB时钟
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4);//PB4配置成输出
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);//PB4配置成推挽输出,50M速度
while(1)
{
gpio_bit_set(GPIOB, GPIO_PIN_4);//PB4输出高电平
delay_1ms(100);//等待100ms
gpio_bit_reset(GPIOB, GPIO_PIN_4);//PB4输出低电平
delay_1ms(100);
}
}
总结
本篇文章主要讲解了GPIO是什么,以及将GPIO配置为输出模式点亮一个LED灯的实验。
源码链接:
链接:https://pan.baidu.com/s/1-YMOZS_QVGSDkUC0oIbEWg
提取码:tji2