ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

用不同方式实现流水灯控制实验

用不同方式实现流水灯控制实验 用不同方式实现流水灯控制实验一、寄存器实现1、GPIO端口初始化与原理分析1 时钟配置2输入输出模式和输出速率设置2、代码实现与详细注解1 硬件连接说明2C语言寄存器编程实现3、 硬件搭建与烧录1电路连接2 ST-Link 下载器连接4 效果展示与总结二、标准外设库实现1、实验原理2、硬件电路说明3、工程项目创建与标准外设库添加详细步骤1建立工程本地文件夹2Keil5 新建工程3拷贝标准外设库文件到工程目录4在 Keil 工程内添加文件分组并添加源码5配置头文件包含路径6配置调试下载器4、实验代码5、下载与效果展示6、时序周期分析7、实验总结三、外部中断实现按键控制流水灯1、实验任务2、实验环境1硬件环境2软件环境3、实验原理1外部中断 EXTI 原理2 NVIC 中断优先级3 按键消抖设计4、硬件设计5、软件设计6、实验步骤7、问题排查与解决1编译阶段大量头文件未定义2链接阶段HAL 基础函数未定义3 运行阶段只有一个 LED 常亮不循环按键无效8、实验现象9、实验总结一、寄存器实现1、 GPIO端口初始化与原理分析本次实验基于STM32F103C8T6最小系统板通过直接操作寄存器的方式控制GPIO口输出高低电平从而驱动LED灯闪烁。1 时钟配置STM32的外设默认是关闭时钟的以节省功耗。要使用GPIOA、B、C必须先开启对应的时钟。a、时钟使寄存器映射基地址2找到端口偏移地址a、输入输出模式和输出速率设置每个引脚由 4 个位控制MODE CNF低 8 引脚 (0-7)使用 CRL 寄存器。高 8 引脚 (8-15)使用 CRH 寄存器。本实验将引脚配置为 通用推挽输出 速度设为 50MHz。对应配置值MODE[1:0] 11 (50MHz), CNF[1:0] 00 (推挽)。即每 4 位赋值为 0x3。找到GPIOX端口基地址2、代码实现与详细注解1) 硬件连接说明根据代码逻辑与实际操作硬件连接如下LED 1连接至 PA1 引脚。LED 2连接至 PB15 引脚。LED 3连接至 PB1 引脚。LED 4连接至 PC13 引脚核心板板载蓝色 LED。电路逻辑所有 LED 负极接 GPIO 引脚正极串联电阻接 3.3V 电源。2 C语言寄存器编程实现代码如下3、硬件搭建与烧录1 电路连接在面包板上搭建电路将 PA1、PB15、PB1 分别通过杜邦线连接到外部 LED 的负极LED 正极串联 330Ω 电阻接 3.3V。PC13 直接使用 STM32 最小系统板自带的蓝色 LED无需额外连线。4、效果展示与总结效果展示程序运行后可以看到四个 LED 灯按照 PA1 - PB15 - PB1 - PC13 的顺序依次循环点亮。每个灯亮起的时间约为 1 秒随后熄灭并切换至下一个灯形成了稳定的流水灯效果。流水灯总结通过本次实验我掌握了以下关键点绝对地址编程学会了如何通过查阅数据手册找到寄存器的物理地址如 0x4001080C并使用 C 语言指针宏定义进行直接访问加深了对“寄存器即内存”的理解。位操作技巧熟练使用了 ~ (位清零/置低) 和 | (位置位/置高) 操作 ODR 寄存器实现了在不影响其他引脚状态的前提下独立控制特定 LED。硬件逻辑理解明确了共阳电路中“低电平点亮”的逻辑并在代码中正确实现了这一控制方式。二、标准外设库实现1、实验原理1 标准外设库ST 官方提供的固件库封装了寄存器底层操作。开发者直接调用库函数配置 GPIO、RCC 等外设不用手动读写寄存器开发效率高于寄存器版本任务 1。2 GPIO 输出将 PA1、PB1、PB15、PC13 配置为推挽输出模式。GPIO_ResetBits()输出低电平点亮 LEDGPIO_SetBits()输出高电平熄灭 LED共阳极 LED。3软件循环延时通过嵌套空循环消耗 CPU 指令实现近似 1 秒延时。软件延时精度不高延时时间会受编译器优化、系统时钟影响不是精准的 1000ms。4 流水逻辑依次单独点亮每一路 LED其余全部熄灭保持一段延时后切换循环往复。2、硬件电路说明沿用实验任务 1 的 LED 接线无需改动任何 LED 杜邦线PA1 → LED 串联限流电阻 → GNDPB1 → LED 串联限流电阻 → GNDPB15 → LED 串联限流电阻 → GNDPC13 → 板载 LED最小系统自带ST-LINK 下载接线SWDIO、SWCLK、GND 三根线板子 USB 单独供电。3、工程项目创建与标准外设库添加详细步骤工程分组结构Project: Flow└── Target_1├─ USER │ └─ main.c ├─ CMSIS └─ Device ├─ misc.c ├─ stm32f10x_gpio.c ├─ stm32f10x_rcc.c ├─ startup_stm32f10x_md.s ├─ stm32f10x_conf.h └─ system_stm32f10x.c1建立工程本地文件夹在电脑 D 盘新建工程总文件夹路径无中文例如D:\stm32_project\flow_led_stdlib。内部新建 4 个子文件夹USER存放 main.c、stm32f10x_conf.h、启动文件SRC用户源码INC头文件StdPeriph_Driver存放标准外设库的src、inc文件夹2Keil5 新建工程打开 Keil5点击Project - New μVision Project进入工程文件夹命名工程Flow并保存。芯片选型选择STM32F103C8T6。弹出 RTERun-Time Environment窗口勾选 CMSIS、Device。勾选后 Keil 会自动添加启动汇编文件**startup_stm32f10x_md.s、系统初始化文件system_stm32f10x.c**不需要手动拷贝启动文件。3拷贝标准外设库文件到工程目录打开 STM32F10x 标准外设库固件包复制stm32f10x_gpio.c、stm32f10x_rcc.c、misc.c放到StdPeriph_Driver\src对应的.h头文件放到StdPeriph_Driver\inc4在 Keil 工程内添加文件分组并添加源码在工程窗口新建分组USER、StdPeriph_Driver。右键USER分组 → Add Existing Files添加main.c、startup_stm32f10x_md.s。右键StdPeriph_Driver分组添加stm32f10x_gpio.c、stm32f10x_rcc.c、misc.c。5配置头文件包含路径点击魔术棒图标 →C/C选项卡点击Include Paths。添加 3 个路径.\USER、.\StdPeriph_Driver\inc、.\INC。预定义宏添加STM32F10X_MD,USE_STDPERIPH_DRIVER。6配置调试下载器魔术棒 → Debug选择 ST-Link 调试器勾选Download下的 Reset and Run下载完成自动复位运行。4、实验代码5、下载与效果展示硬件接线STM32 开发板通过 ST-Link 连接电脑ST-Link 的 SWD、SWCLK、GND、3.3V 接到开发板。Keil 点击 Build 编译无错误警告点击 Download将固件下载到 STM32F103C8T6。自动复位运行现象PA1、PB1、PB15、PC13 四个 LED 依次轮流点亮每盏灯点亮保持 500ms然后熄灭切换下一盏循环往复。成果6、时序周期分析问题LED 灯的亮 / 灭周期是通过软件循环延时完成的其准确周期大致是多少呢系统主频 72MHzCPU 每秒执行 72M 条指令。软件延时是空循环等待没有定时器精准定时。我写的Delay_ms(500)理论目标 500ms 延时。但是软件空循环延时会受到编译器优化、代码跳转、中断抢占影响不是精准 500ms存在误差。单次 LED 亮灭间隔≈500ms完整一轮 4 个 LED 全部轮一遍总周期≈2000ms2 秒。总结软件循环延时属于粗略延时存在几十 ms 的误差只适合简单演示高精度定时需要使用定时器 TIM。7、实验总结本实验使用 STM32 标准外设库调用库函数完成 RCC 时钟开启、GPIO 初始化相比直接操作寄存器代码可读性更强开发更快捷。实验实现 4 路 LED 流水灯间隔 500ms 轮流点亮验证了 GPIO 推挽输出功能。软件空循环延时实现简单但定时精度差误差较大不适合高精度时序控制。实验踩坑总结忘记开启 GPIO 端口时钟会导致 LED 不工作工程路径含中文会引发 Keil 编译报错头文件路径没有添加会报头文件找不到错误。三、外部中断实现按键控制流水灯1、实验任务本实验为 STM32 基础实验的任务三基于任务二的流水灯功能引入外部中断 EXTI机制实现按键对流水灯启停的控制。相比轮询检测按键的方式中断方式可以让 CPU 在无按键时专注执行主程序按键触发时即时响应显著提升程序执行效率和实时性。实验目标掌握 STM32 外部中断 EXTI 的工作原理与配置方法理解 NVIC 中断优先级的作用与配置规则实现下降沿触发的外部中断按键翻转流水灯运行状态掌握中断服务函数的设计规范中断内仅做标志位处理耗时操作放主循环2、实验环境1 硬件环境STM32F103C8T6 最小系统板面包板、杜邦线若干3 个 LED红、绿、蓝3 个 220Ω 限流电阻1 个轻触按键ST-Link V2 调试下载器2软件环境Keil uVision5 开发环境STM32F1xx HAL 驱动库ST-Link 驱动程序3、实验原理1外部中断 EXTI 原理STM32F103 系列芯片内置了 19 个外部中断/事件线EXTI0 ~ EXTI18每个 GPIO 引脚都可以通过 AFIO复用功能 IO映射到对应的 EXTI 中断线。本实验使用 PA0 引脚对应 EXTI0 中断线配置为下降沿触发模式。触发机制详解当按键按下时PA0 引脚电平从高电平3.3V跳变为低电平0V产生一个下降沿。EXTI 检测到该下降沿后会向 NVIC 发出中断请求CPU 暂停当前主程序跳转到对应的中断服务函数执行。中断处理完成后CPU 自动返回主程序继续执行。为什么选择下降沿触发本实验按键一端接 PA0另一端接 GND利用单片机内部上拉电阻使引脚默认保持高电平。按下按键时引脚被拉低松开后恢复高电平因此下降沿恰好对应按键按下的瞬间逻辑清晰且不易误触发。2 NVIC 中断优先级STM32 通过 NVIC嵌套向量中断控制器统一管理所有中断其优先级分为抢占优先级与子优先级两类。抢占优先级较高的中断可以打断正在执行的较低优先级中断而同级中断之间则无法相互嵌套。NVIC 的优先级分组方式由HAL_NVIC_SetPriorityGrouping()函数配置本实验采用默认分组。优先级配置代码HAL_NVIC_SetPriority(EXTI0_IRQn,1,0);// 抢占优先级1子优先级0HAL_NVIC_EnableIRQ(EXTI0_IRQn);// 使能 EXTI0 中断关键注意事项HAL_Delay()延时函数依赖 SysTick 滴答定时器而 SysTick 的默认抢占优先级为 0。若外部中断的优先级高于 SysTick即抢占优先级也设为 0在中断内调用延时会导致 SysTick 被抢占而卡死进而使主循环延时失效。因此本实验将 EXTI0 的抢占优先级设置为 1低于 SysTick 的默认优先级 0从而确保延时函数能够正常工作。3 按键消抖设计机械按键按下时会产生数毫秒的电平抖动直接触发中断会导致单次按键被识别为多次。本实验采用中断置标志 主循环延时消抖的方案中断回调函数中仅置位按键触发标志不做任何延时和复杂逻辑主循环中检测到标志后延时 20ms 再判断引脚电平确认有效后再执行动作消抖流程按键按下EXTI0 触发中断中断回调函数置位key_flag 1主循环检测到key_flag 1调用HAL_Delay(20)等待抖动期过去延时结束后再次读取 PA0 引脚电平若仍为低电平则确认是有效按键执行流水灯状态翻转逻辑并清除key_flag标志若延时后引脚已恢复高电平则判定为抖动干扰仅清除标志不执行动作这种设计既保证了按键响应的实时性又有效避免了机械抖动带来的误触发是嵌入式开发中常用的消抖方案。4、硬件设计引脚分配接线说明LED 回路每个 LED 长脚正极接对应单片机引脚短脚负极串联 220Ω 电阻后接 GND按键回路按键一端接 PA0另一端接 GND单片机内部上拉电阻生效默认高电平按下接地触发下降沿下载回路ST-Link 的 SWDIO 接 PA13、SWCLK 接 PA14、GND 接 GND、3.3V 接 3.3V5、软件设计整体程序流程系统时钟配置外部 8MHz 晶振经 PLL 9 倍频至 72MHz外设初始化GPIO 端口时钟开启、LED 引脚配置为推挽输出、按键引脚配置为中断输入NVIC 配置设置 EXTI0 中断优先级使能中断主循环检测按键标志执行流水灯切换逻辑实现 500ms 间隔流水中断回调按键触发后置位标志由主循环处理消抖和状态翻转核心代码6、实验步骤工程搭建新建 Keil 工程添加 HAL 库核心文件、外设驱动文件和 CMSIS 文件配置头文件包含路径代码编写在 main.c 中完成时钟、GPIO、中断配置编写主循环和中断回调逻辑编译调试配置编译器选项清理工程后编译修正语法错误和路径错误烧录运行连接 ST-Link配置 Debug 选项为 ST-Link Debugger勾选 Reset and Run下载程序到开发板现象验证观察上电流水灯效果测试按键启停功能7、问题排查与解决本次实验过程中遇到多个问题整理如下1编译阶段大量头文件未定义现象uint32_t未定义、core_cm3.h找不到、100 个编译错误原因工程缺少 CMSIS 核心头文件路径芯片宏定义错误解决添加Drivers\CMSIS\Core\Include到包含路径宏定义改为STM32F103xB2链接阶段HAL 基础函数未定义现象HAL_Init、HAL_Delay等函数提示未定义符号原因工程只添加了外设驱动缺少 HAL 库核心入口文件stm32f1xx_hal.c解决将核心源文件添加到工程分组中3 运行阶段只有一个 LED 常亮不循环按键无效现象上电只有第一个红灯亮程序卡死按键无反应根本原因在中断回调函数中调用了HAL_Delay()且 EXTI0 优先级与 SysTick 同级导致 SysTick 被卡死主循环延时永远无法完成解决中断回调中仅置位标志位消抖和逻辑处理移到主循环将 EXTI0 抢占优先级设为 1低于 SysTick 的优先级 08、实验现象理论上上电复位后红、绿、蓝三个 LED 依次循环点亮间隔 500ms形成流水灯效果按下 PA0 按键流水灯立即暂停三个 LED 全部熄灭再次按下按键流水灯从暂停位置恢复循环运行按键响应灵敏无抖动误触发现象因各种原因视频与所描述现象略有差别请见谅。实际情况为在任务二视频的基础上多了一个按键在PA0处链接之后流水灯正常运行但按键对流水灯无任何影响。9、实验总结通过本次实验掌握了 STM32 外部中断的配置方法和中断程序的设计规范理解了中断优先级对程序运行的影响。相比轮询方式外部中断大幅提升了 CPU 的执行效率同时保证了按键响应的实时性。实验中最关键的收获是明确了中断服务函数的设计原则中断内只做最必要的标志位处理耗时操作、复杂逻辑全部放到主循环执行避免阻塞其他中断和主程序运行。同时中断优先级的合理配置是系统稳定运行的前提需要根据外设重要性和依赖关系综合权衡。
返回列表