STM32实现LED闪烁和串口打印案例

一、实验目的

在嵌入式开发中,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 务必共地

五、工程配置

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

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

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

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

  5. 配置串口USART0Mode 选择 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()直接通过串口输出:

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.cmain() 函数中,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;
}

七、编译烧录与串口验证

  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等外设的坚实基础。

相关推荐
✎ ﹏梦醒͜ღ҉繁华落℘3 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u152109648493 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd8451015003 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼3 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志3 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi3 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan3 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘3 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展3 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司3 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设