一、实验目的

在嵌入式开发中,GPIO(通用输入输出)和UART(串口通信)是最基础的两个外设。本次实验通过点亮一个LED灯,同时用串口打印LED的开关状态,完成从硬件控制到信息反馈的完整流程。

主要目标:

  • 掌握STM32的GPIO输出控制

  • 掌握USART串口的基本配置与使用

  • 理解printf重定向到串口的实现原理

  • 体会“嵌入式系统的Hello World”

二、硬件准备

序号元件/模块数量说明
1STM32最小系统板1我使用的是GD32F103VET6
2LED发光二极管1若使用板载LED则不需要(我的是板载LED)
3限流电阻1220Ω~1kΩ均可,板载LED不需要
4USB转TTL模块1CH340/CP2102等(我的板载)
5ST-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模块说明
PA9RXDGD32的TX→模块的RX
PA10TXDGD32的RX→模块的TX
GNDGND务必共地

五、工程配置

  1. 新建工程,选择芯片型号 GD32F103VET6

  2. 配置调试接口SYS → Debug 选择 CMSIS-DAP Debugger(SWD下载,根据自己情况选择)。

  3. 配置时钟RCC → HSE 选择 Crystal/Ceramic Resonator(使用外部晶振),Clock Configuration中设置主频为72MHz。

  4. 配置GPIO:将你的LED引脚(本示例为PC13)设置为 GPIO_Output,初始电平根据点亮逻辑设置。低电平点亮则初始给高电平让LED灭。

  5. 配置串口USART0→ Mode 选择 Asynchronous,波特率 115200,数据位8,停止位1,无校验。其他保持默认。

  6. 生成代码: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()直接通过串口输出:

//串口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)循环部分编写如下:

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;
}

七、编译烧录与串口验证

  1. 编译工程,确认0错误0警告。

  2. 通过DAP-Link将程序烧录到开发板。

  3. 将USB转TTL模块插入电脑,打开串口调试助手。

  4. 设置参数:波特率115200、8数据位、1停止位、无校验

  5. 给开发板上电或按复位键。

此时应看到LED灯亮3秒,灭1秒,串口输出类似以下内容:

八、实验总结

本次实验成功实现了两个核心功能:

  1. GPIO输出控制:通过对引脚写高/低电平来控制LED的亮灭,这是嵌入式系统中最基础的“数字输出”操作。

  2. 串口通信:通过USART将MCU内部信息发送到PC端显示,实现了人机交互的最简单形式。printf重定向是嵌入式调试中非常实用的技巧。

这个实验打通了“写代码 → 控制硬件 → 获取反馈”的完整链路,是后续学习定时器、中断、I2C/SPI等外设的坚实基础。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐