在配置好的模板工程中的`Project`中的`main`函数中写:

先进行初始化,自己定义一个初始化函数`void gpio_config()`,在这个函数中初始化时钟,配置GPIO为输出,配置输出为推挽。

图上的前三个为初始化函数,怎么用这几个函数:

1.初始化时钟

选中`rcu_periph_clock_enable`右键选择Go To Definition可以查看这个函数的用法,下图是GD32的外设时钟控制函数及说明文档,涉及到 MCU(微控制器)内部 RCU(Reset and Clock Unit,复位与时钟控制单元)的操作,说明了函数`rcu_periph_clock_enable`的用法

因为我用的是PB2引脚,所以:`rcu_periph_clock_enable(RCU_GPIOB);`

2.配置GPIO为输出

选中`gpio_mode_set`(配置GPIO引脚的工作模式)右键选择Go To Definition可以查看这个函数的用法,下图是该函数的语法:

(1)GPIO端口

没什么好说的,你用哪组端口就写哪组

(2)GPIO引脚模式

输入模式(GPIO_MODE_INPUT):引脚被配置为输入,只能读,不会驱动电平,外部电路决定引脚上的电平,MCU只采样。如果输入引脚没有外部电路拉高或拉低,它的电平会漂浮,读到的值不稳定,所以需要配置上拉或下拉电阻,或者在外部硬件接电阻。用途:读取按键状态、读取外部传感器信号、检测外部设备状态

输出模式(GPIO_MODE_OUTPUT):引脚被配置为推挽输出或者开漏输出,MCU可以主动输出高低电平。推挽输出:输出0或1都直接由MCU驱动,速度快,驱动能力强。开漏输出:MCU只能拉低,不能拉高,拉高需要外部上拉电阻,适合I2C总线、多设备共享信号线。用途:点亮LED、控制继电器、蜂鸣器、给其他芯片发送高低电平控制信号

操作 中文术语 英文术语 输出电平 描述
推 / 源出 Push / Source 1 (高电平) 从VCC向外推送电流,将电压推高
挽 / 灌入 Pull / Sink 0 (低电平) 将外部电流吸入到GND,将电压拉低

复用功能模式(GPIO_MODE_AF):当MCU的某个引脚除了GPIO功能之外,还可以作为外设接口的引脚使用,就需要配置为复用模式。MCU内部自动把该引脚连接到外设,不再当普通GPIO用,必须在代码中设置AF寄存器选中复用功能编号(AF0~AF15)。用途:UART的TX、RX引脚,SPI的MISO、MOSI、SCK、CS,I2C的SDA、SCL,TIM定时器的PWM输出,CAN总线引脚。

模拟模式(GPIO_MODE_ANALOG):引脚被配置为模拟输入/输出,MCU内部的数字输入电路被关闭,从而引脚电平不会被数字采样电路干扰,功耗更低,输入阻抗更高。用途:ADC模拟输入、DAC模式输出

(3)上拉/下拉配置

这实际上配置了 MCU 内部集成的上拉/下拉电阻,不用外接物理电阻。

悬空(GPIO_PUPD_NONE):MCU内部不上拉也不下拉,引脚完全悬空。

上拉(GPIO_PUPD_PULLUP):在引脚内部通过一个几十kΩ的电阻连接到VCC。用途:按键检测:如果按键一端接地,一端接 MCU 引脚 → 配置上拉,这样按下前电平是高,按下后电平是低。I²C 总线:SDA、SCL 都需要上拉电阻(一般外部电阻,内部上拉不够强)。防止输入悬空:当引脚没有外部驱动电平时,内部上拉保证引脚电平稳定为高。

下拉(GPIO_PUPD_PULLDOWN):在引脚内部通过一个几十kΩ的电阻连接到GND。用途:按键检测:如果按键一端接 VCC,一端接 MCU 引脚 → 配置下拉,这样按下前电平是低,按下后电平是高。防止输入悬空:当引脚没有外部驱动电平时,内部下拉保证引脚电平稳定为低。

场景 模式 上下拉配置 说明
读取按键 输入模式 上拉或下拉 防止悬空
点亮 LED 输出模式 无(通常不需要) MCU 主动控制电平
控制继电器 输出模式 驱动外部器件
UART 通信 复用模式 通常不上下拉 串口硬件会驱动电平
I²C 总线 复用模式(开漏) 上拉(外部更好) 总线需要高电平回弹
ADC 输入 模拟模式 无(或外部电路决定) 防止数字干扰
低功耗待机 模拟模式 降低输入电流

因为我用的PB2引脚,并且是点亮LED,所以:`gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);`

3.配置输出为推挽(输出中有推挽和开漏)

选择`gpio_output_options_set`右键选择Go To Definition可以查看这个函数的用法,下图是该函数的语法:

参数 作用 可选值 说明
gpio_periph 要配置的 GPIO 端口 GPIOA / GPIOB / … 指定操作哪个 GPIO 组
otype 输出类型 GPIO_OTYPE_PP(推挽) GPIO_OTYPE_OD(开漏) 决定输出驱动方式
speed 输出速度 GPIO_OSPEED_2MHZ / GPIO_OSPEED_25MHZ / GPIO_OSPEED_50MHZ / GPIO_OSPEED_MAX 决定上升/下降沿速度
pin 要配置的引脚 GPIO_PIN_x (x=0..15) 或 GPIO_PIN_ALL 可以配置单个或多个

场景 推荐输出类型 推荐速度 解释
点亮 LED 推挽 2MHz / 25MHz LED 频率低,不需要高速切换
按键输入 推挽/开漏 + 上拉/下拉 2MHz 通常用开漏 + 外部上拉,防止悬空
I²C 总线 开漏 50MHz 需要多个器件共享一根线,必须开漏
SPI 总线 推挽 50MHz / MAX SPI 速度快,需要高驱动能力
PWM 输出 推挽 50MHz / MAX 驱动能力强,减少延迟

至此,完成了三个初始化,代码:

void gpio_config(){
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_2);
}

4.输出高低电平状态

选择`gpio_bit_set`右键选择Go To Definition可以查看这个函数的用法,下图是该函数的语法:

同理按照上面操作也可以查看`gpio_bit_reset`函数的语法。

另外不管是什么操作都要用函数`systick_config();` 用于初始化系统滴答定时器,提供 1ms 时基。如果不写这个函数就无法调用延时函数delay_1ms

MCU 核心时钟频率不同:

  • 每个 MCU 的主频不同,比如:

    • GD32 或 STM32F103 → 72 MHz

    • STM32F407 → 168 MHz

  • SysTick 计数器每次计数的时间 = 1 / MCU 时钟频

MCU 时钟 = 72 MHz
SysTick 计数一次 = 1 / 72,000,000 s ≈ 13.88 ns

也就是说,SysTick 每计数一次,只经过 13.88 纳秒,不是我们想要的 1ms。

设置计数周期产生 1ms 中断:

  • 我们希望 SysTick 每 1ms 触发一次中断

  • 那么就需要让计数器 计数 1ms 的时钟数 后才触发一次中断。

重载值 = MCU 时钟频率 / 1000
  • 例如:72 MHz MCU

    • 重载值 = 72,000,000 / 1000 = 72,000

    • 这意味着 SysTick 计数 72,000 次 → 刚好 1ms → 触发中断

  • 不同 MCU 主频不同 → 重载值也不同
    → 所以要根据 SystemCoreClock 动态计算

只要重载值 ≤ 0xFFFFFF,直接 MCU 时钟 / 1000 就能得到 1ms 中断

主函数代码:

int main(void)
{
 
    systick_config(); // 系统滴答定时器
	gpio_config();  // 初始化

    while(1) {
			gpio_bit_set(GPIOB, GPIO_PIN_2); // PB2 = 高电平
			delay_1ms(500); // 500x1=500ms 延时0.5s
			gpio_bit_reset(GPIOB, GPIO_PIN_2);  // PB2 = 低电平
			delay_1ms(500);   // 延时0.5s
    }
}

5.完整代码:

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
//#include "gd32f450i_eval.h"


//³õʼ»¯GPIO_PB2

void gpio_config(){
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_2);
}

int main(void)
{

    systick_config(); 
		gpio_config();

    while(1) {
			gpio_bit_set(GPIOB, GPIO_PIN_2);
			delay_1ms(500);
			gpio_bit_reset(GPIOB, GPIO_PIN_2);
			delay_1ms(500);
    }
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐