一、实验目的
在嵌入式开发中,GPIO(通用输入输出)和UART(串口通信)是最基础的两个外设。本次实验通过点亮一个LED灯,同时用串口打印LED的开关状态,完成从硬件控制到信息反馈的完整流程。
主要目标:
-
掌握STM32的GPIO输出控制
-
掌握USART串口的基本配置与使用
-
理解
printf重定向到串口的实现原理 -
体会"嵌入式系统的Hello World"
二、硬件准备
| 序号 | 元件/模块 | 数量 | 说明 |
|---|---|---|---|
| 1 | STM32最小系统板 | 1 | 我使用的是GD32F103VET6 |
| 2 | LED发光二极管 | 1 | 若使用板载LED则不需要(我的是板载LED) |
| 3 | 限流电阻 | 1 | 220Ω~1kΩ均可,板载LED不需要 |
| 4 | USB转TTL模块 | 1 | CH340/CP2102等(我的板载) |
| 5 | ST-Link下载器 | 1 | 烧录程序用(我的是DAP-Link) |
| 6 | 杜邦线 | 若干 |
💡 提示 :很多开发板(如常见的Blue Pill板)板载LED连接在 PC13 引脚,低电平点亮。你可以根据自己的板子实际情况修改引脚,后面代码处会标注修改位置。
三、软件环境
-
开发环境: Keil MDK
-
HAL库版本:GigaDevice.GD32F10x_DFP.2.0.3 固件包
-
串口调试工具:SSCOM、MobaXterm、Putty 任意一款均可
四、硬件连接
4.1 LED连接
-
使用板载LED:无需额外接线,板载LED通常接PC13,注意该引脚低电平点亮。
-
使用外接LED:LED正极串联限流电阻后接GPIO引脚,负极接GND。
本文示例:LED接PC13引脚,低电平点亮(你可以改为自己的引脚)。
4.2 串口连接
使用USART0,引脚对应如下:
| GD32引脚 | USB转TTL模块 | 说明 |
|---|---|---|
| PA9 | RXD | GD32的TX→模块的RX |
| PA10 | TXD | GD32的RX→模块的TX |
| GND | GND | 务必共地 |
五、工程配置
-
新建工程 ,选择芯片型号
GD32F103VET6。 -
配置调试接口 :
SYS→Debug选择CMSIS-DAP Debugger(SWD下载,根据自己情况选择)。
-
配置时钟 :
RCC→HSE选择Crystal/Ceramic Resonator(使用外部晶振),Clock Configuration中设置主频为72MHz。 -
配置GPIO :将你的LED引脚(本示例为
PC13)设置为GPIO_Output,初始电平根据点亮逻辑设置。低电平点亮则初始给高电平让LED灭。 -
配置串口 :
USART0→Mode选择Asynchronous,波特率115200,数据位8,停止位1,无校验。其他保持默认。 -
生成代码:Project Manager中设置工程名和路径,Toolchain选择你的IDE,勾选"Generate peripheral initialization as a pair of '.c/.h' files",点击GENERATE CODE。
六、代码实现
6.1 串口重定向(printf支持)
在 main.c,添加以下代码,让 uart_send_string()和UART0WriteData()直接通过串口输出:
bash
//串口0数据接收buff大小
#define UART0_RX_BUFF_SIZE (512)
//串口0接收到的数据长度
#define UART0_RX_DATA_LEN ((gUart0RxData.tail + UART0_RX_BUFF_SIZE - gUart0RxData.head) % UART0_RX_BUFF_SIZE)
//删除串口0已读取的数据,len为删除数据长度
#define UART0_RX_DATA_DELETE(len) (gUart0RxData.head = (gUart0RxData.head + (len)) % UART0_RX_BUFF_SIZE)
//判断串口0接收buff是否已满
#define UART0_RX_BUFF_IS_FULL() (((gUart0RxData.tail + 1) % UART0_RX_BUFF_SIZE == gUart0RxData.head) ? TRUE : FALSE)
void UART0Init(void)
{
// 打开GPIOA和串口0时钟
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_USART0);
//串口0引脚配置
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, 0U, GPIO_PIN_10);
//初始化配置
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200U);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
/* enable USART0 receive interrupt */
usart_interrupt_enable(USART0, USART_INT_RBNE);
nvic_irq_enable(USART0_IRQn, 1U, 3U);
/* enable USART0 */
usart_enable(USART0);
}
//方式1
//1para
void uart_send_string(char *str) {
while (*str) {
usart_data_transmit(USART0, *str);
while (RESET == usart_flag_get(USART0, USART_FLAG_TBE));
str++;
}
}
方式2
//2 para
int UART0WriteData(char *pBuff, int len)
{
int i;
if (pBuff == NULL || len == 0)
{
return 0;
}
for (i = 0; i < len; i++)
{
usart_data_transmit(USART0, pBuff[i]);
while (RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
return len;
}
6.2 主循环逻辑
在 main.c 的 main() 函数中,while(1)循环部分编写如下:
bash
int main(void)
{
systick_config(); // 初始化计时器
/* 初始化中断向量 */
//NVIC_Init();
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
//nvic_vector_table_set(NVIC_VECTTAB_FLASH, FLASH_APP_ADDR);
__enable_irq();
rcu_periph_clock_enable(RCU_GPIOC); //打开GPIOA时钟
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); //将PA0配置为浮空输入,最高支持50MHZ
UART0Init();
uart_send_string("System started\r\n"); //
while(1)
{
gpio_bit_reset(GPIOC, GPIO_PIN_13); //将PC13置低电平,点亮LED
UART0WriteData("LED ON\r\n",6);
delay_1ms(3000);
gpio_bit_set(GPIOC, GPIO_PIN_13); //½<<PC13ÖÃ¸ßµçÆ½£¬Ï¨ÃðLED
UART0WriteData("LED OFF\r\n",7);
delay_1ms(1000);
}
return 0;
}
七、编译烧录与串口验证
-
编译工程,确认0错误0警告。
-
通过DAP-Link将程序烧录到开发板。
-
将USB转TTL模块插入电脑,打开串口调试助手。
-
设置参数:波特率115200、8数据位、1停止位、无校验 。

-
给开发板上电或按复位键。
此时应看到LED灯亮3秒,灭1秒,串口输出类似以下内容:

八、实验总结
本次实验成功实现了两个核心功能:
-
GPIO输出控制:通过对引脚写高/低电平来控制LED的亮灭,这是嵌入式系统中最基础的"数字输出"操作。
-
串口通信 :通过USART将MCU内部信息发送到PC端显示,实现了人机交互的最简单形式。
printf重定向是嵌入式调试中非常实用的技巧。
这个实验打通了"写代码 → 控制硬件 → 获取反馈"的完整链路,是后续学习定时器、中断、I2C/SPI等外设的坚实基础。