news 2026/9/30 10:59:24

STM32F103 GPIO标准外设库四灯流水灯实验报告(任务二·Keil5版)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103 GPIO标准外设库四灯流水灯实验报告(任务二·Keil5版)

一、实验目的

1. 在实验一(HAL库四灯流水灯)的基础上,掌握使用STM32标准外设库(Standard Peripheral Library,SPL)控制GPIO端口实现LED流水灯的方法。

2. 掌握在Keil5(MDK-ARM)中手动建立工程、添加STM32标准外设库文件(.c、.h)的完整过程。

3. 理解软件循环延时实现LED亮灭周期的原理,并分析其准确周期。

4. 对比标准外设库与HAL库两种开发方式的异同。

二、实验器材

器材说明
STM32F103最小系统板Cortex-M3内核,72MHz主频,自带PC13板载LED
ST-Link下载器程序烧录与调试
LED发光二极管 × 3红、绿、蓝各一只(外部LED)
面包板及杜邦线电路连接
220Ω限流电阻 × 3保护外部LED和GPIO引脚
PC电脑 + Keil5(MDK-ARM)+ 标准外设库开发环境

三、实验原理

3.1 标准外设库概述

STM32标准外设库(SPL)是ST官方提供的一套底层固件库,将寄存器操作封装成函数,例如GPIO_Init()配置引脚、RCC_APB2PeriphClockCmd()使能时钟。相比HAL库,标准外设库更贴近寄存器、代码简洁,是Keil5下经典的STM32开发方式。

3.2 GPIO控制原理

标准外设库中,引脚配置通过GPIO_InitTypeDef结构体与GPIO_Init()完成;电平控制通过GPIO_SetBits()(高电平)和GPIO_ResetBits()(低电平)实现。本实验沿用实验一的四个LED及电平逻辑:PC13板载LED低电平点亮,PC14、PA4、PB1三个外部LED高电平点亮。

四、实验步骤

(一)在Keil5中创建工程并添加标准外设库文件

1. 下载STM32F10x标准外设库(如STM32F10x_StdPeriph_Lib_V3.5.0),解压后记录Libraries目录位置,其中包含CMSIS与STM32F10x_StdPeriph_Driver两个子目录。

2. 启动Keil5(μVision),点击菜单 Project → New μVision Project,选择工程保存路径并命名(如LEDflow_SPL),保存。

3. 在弹窗中选择芯片型号:ARM → STMicroelectronics → STM32F1xx → STM32F103 → 选择STM32F103RCT6(或C8T6),点击OK。

4. 系统提示"Copy STM32 Startup Code to Project Folder?(是否拷贝启动文件)“,选择"是”,工程自动添加启动文件startup_stm32f10x_hd.s。

5. 在左侧Project窗口右键Target1,选择Manage Project Items,建立如下分组并添加库文件:

LEDflow_SPL(工程) ├─ User/# main.c、stm32f10x_it.c ├─ StdPeriph_Driver/│ ├─ stm32f10x_gpio.c │ ├─ stm32f10x_rcc.c │ └─ stm32f10x_flash.c ├─ Startup/# startup_stm32f10x_hd.s └─ CMSIS/├─ core_cm3.c └─ system_stm32f10x.c

6. 添加头文件路径:点击工程按钮 Options for Target(或Alt+F7),切换到 C/C++ 选项卡,在 Include Paths 中依次添加:

CMSIS STM32F10x_StdPeriph_Driver/inc User

7. 在 C/C++ 选项卡的 Define 框填入宏定义:USE_STDPERIPH_DRIVER, STM32F10X_HD(大容量芯片用HD,中容量用MD)。

8. 配置下载调试器:切换到 Debug 选项卡,选择 ST-Link Debugger,再进入 Flash Download 勾选 Reset and Run,便于下载后自动运行。

9. 将编写好的main.c放入User分组,点击编译(F7),无误后点击下载(F8)烧录到开发板。

(二)编写主程序

main.c中使用标准外设库函数完成时钟使能、GPIO配置与四灯流水控制,代码如下:

#include"stm32f10x.h"voidRCC_Configuration(void);voidGPIO_Configuration(void);voidDelay(__IOuint32_tnCount);intmain(void){RCC_Configuration();GPIO_Configuration();while(1){// 1. PC13板载LED亮,其余灭GPIO_ResetBits(GPIOC,GPIO_Pin_13);GPIO_SetBits(GPIOC,GPIO_Pin_14);GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOB,GPIO_Pin_1);Delay(0x00100000);// 2. PC14蓝灯亮,其余灭GPIO_SetBits(GPIOC,GPIO_Pin_13);GPIO_SetBits(GPIOC,GPIO_Pin_14);GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOB,GPIO_Pin_1);Delay(0x00100000);// 3. PA4红灯亮,其余灭GPIO_SetBits(GPIOC,GPIO_Pin_13);GPIO_ResetBits(GPIOC,GPIO_Pin_14);GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOB,GPIO_Pin_1);Delay(0x00100000);// 4. PB1绿灯亮,其余灭GPIO_SetBits(GPIOC,GPIO_Pin_13);GPIO_ResetBits(GPIOC,GPIO_Pin_14);GPIO_ResetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOB,GPIO_Pin_1);Delay(0x00100000);}}voidRCC_Configuration(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);}voidGPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;GPIO_Init(GPIOC,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;GPIO_Init(GPIOC,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;GPIO_Init(GPIOB,&GPIO_InitStructure);// 上电全部熄灭GPIO_SetBits(GPIOC,GPIO_Pin_13);GPIO_ResetBits(GPIOC,GPIO_Pin_14);GPIO_ResetBits(GPIOA,GPIO_Pin_4);GPIO_ResetBits(GPIOB,GPIO_Pin_1);}voidDelay(__IOuint32_tnCount){for(;nCount!=0;nCount--);}

五、软件循环延时周期分析

LED的亮灭周期通过软件空循环Delay()实现:

voidDelay(__IOuint32_tnCount){for(;nCount!=0;nCount--);}

该函数的核心是一条空for循环,每一轮循环执行的耗时取决于以下三个因素:

因素说明
系统主频本实验为72MHz,一个CPU时钟周期约1/72MHz ≈ 13.9ns
编译优化等级Keil中默认-O0不优化时循环完整保留;优化等级高时可能被优化掉导致延时失效
汇编指令数-O0下每轮约3~4条指令(加载、减法、比较、跳转),共约4个CPU周期

因此在72MHz、Keil默认-O0条件下,每一轮循环耗时的近似值为:

单轮耗时 ≈4×13.9ns ≈55ns

由此可估算延时:延时 ≈ nCount × 55ns。例如Delay(0x00100000)(1048576次)约延时57ms;要接近1秒,nCount应约为18×10^6(约0x1100000)。

结论:软件循环延时周期的准确值不是固定常数,它依赖主频、编译优化等级和编译器版本,只能给出量级估算。若要获得精确、稳定的1秒延时,应改用SysTick定时器(调用SysTick_Config())或硬件定时器实现。

六、实验现象

上电后,四个LED按照以下顺序循环点亮,每一盏灯点亮约0.8~1秒(由Delay()循环次数决定):

PC13板载LED亮 → PC14蓝灯亮 → PA4红灯亮 → PB1绿灯亮 → 循环。

任意时刻只有一个LED点亮,实现亮灯依次流动的流水灯效果。

使用逻辑分析仪观测DBG_PA0、DBG_PA1、DBG_PA2三个LED引脚,得到如图1所示的时序波形:三个通道输出周期性方波,波形之间存在固定的时序偏移,印证了四灯按顺序依次点亮的流水灯时序。

七、实验中遇到的问题及解决方法

问题原因解决方法
编译报错找不到头文件未在Include Paths中添加头文件路径在Options for Target的C/C++中配置Include Paths
GPIO无效或时钟异常未使能GPIO端口时钟调用RCC_APB2PeriphClockCmd()使能对应端口时钟
条件编译报错缺少宏定义在C/C++的Define中添加USE_STDPERIPH_DRIVER与STM32F10X_HD
延时周期不准空循环延时依赖主频与优化等级改用SysTick或硬件定时器实现精确延时

八、实验总结

本次实验在实验一的基础上,改用STM32标准外设库,通过Keil5完成了四灯流水灯实验。通过手动添加标准外设库文件,掌握了Keil5工程的建立、分组管理、头文件路径配置与宏定义设置方法;理解了标准外设库与HAL库在GPIO配置和电平控制上的差异。同时通过软件循环延时实验,认识到空循环延时周期的估算方法及其不精确、依赖编译环境的特性,为后续使用定时器实现精确延时的学习打下基础。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 10:59:05

硅基流动+DeepSeek本地部署实战:从能跑到敢上线

简介:本资源是一份面向AI开发者与技术实践者的DeepSeek性能优化指南,聚焦解决官方平台因高并发请求导致的‘服务繁忙’问题,以及本地部署对硬件配置要求过高的痛点。文档详细阐述了如何借助硅基流动平台实现DeepSeek模型的稳定、高效调用&…

作者头像 李华
网站建设 2026/9/30 10:58:04

会议室大屏“自带投屏“不够用?外接投屏器的容量与分屏部署实测

先说结论 现在的会议一体机、智能电视基本都带投屏功能,一个人投个文档、放个视频,问题不大。但拿它扛会议室的真实负载——多人轮换上场、多设备同时在线、多组画面同屏、旧屏复用——大多数自带方案会陆续暴露短板。 结论一句话:自带投屏适…

作者头像 李华
网站建设 2026/9/30 10:57:54

社区康养数字化方案:社区养老服务小程序落地思路

社区康养数字化方案:社区养老服务小程序落地思路随着社区居家养老成为主流养老模式,传统线下台账登记、人工电话预约、网格员上门统计的服务模式,逐渐暴露出效率低、响应慢、数据不互通、服务无追溯、资源难统筹等问题。大量社区养老服务存在…

作者头像 李华
网站建设 2026/9/30 10:57:24

WT2003H在婴儿摇篮上的语音音乐播放应用

婴儿摇篮这类产品,工程师要解决的核心问题集中在三件事上,音乐能不能一直放下去、家长能不能自己换内容、电池能不能撑住。夜里两点孩子睡不踏实,家长一只手托着孩子,另一只手在机器上摸按键,这时候音乐断了、音量跳了…

作者头像 李华
网站建设 2026/9/30 10:55:46

社区康养平台搭建:康养服务商派单管理模块解析

社区康养平台搭建:康养服务商派单管理模块解析社区康养平台区别于普通同城接单系统,核心差异在于服务强专业性、人群高安全性、调度高严谨性。康养服务涵盖康复护理、助浴助餐、上门探视、慢病随访、陪护诊疗等特殊场景,服务对象多为老人、失…

作者头像 李华
网站建设 2026/9/30 10:54:02

社区康养系统开发:老人档案与上门服务预约设计

社区康养系统开发:老人档案与上门服务预约设计随着智慧社区、居家养老数字化落地,社区康养系统成为基层养老服务标准化、精细化管控的核心载体。区别于普通业务系统,康养系统具备数据合规性要求高、服务对象特殊、预约流程严谨、服务按需定制…

作者头像 李华