当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]本实验/项目的目标是在基于STM32F407ZGT6的RT-Spark开发板上实现硬件定时器中断以及前台/后台任务调度系统。通过配置两个硬件定时器TIM2和TIM3,以不同速率切换两个内置LED灯;同时在KEY_UP按钮(PC5)上设置外部中断,按下时可立即切换两个LED灯的状态。系统采用循环执行架构:中断服务例程(ISRs)负责处理紧急的后台任务并设置标志位,而主循环则处理前台的实际任务。

本实验/项目的目标是在基于STM32F407ZGT6的RT-Spark开发板上实现硬件定时器中断以及前台/后台任务调度系统。通过配置两个硬件定时器TIM2和TIM3,以不同速率切换两个内置LED灯;同时在KEY_UP按钮(PC5)上设置外部中断,按下时可立即切换两个LED灯的状态。系统采用循环执行架构:中断服务例程(ISRs)负责处理紧急的后台任务并设置标志位,而主循环则处理前台的实际任务。

注意:原始的资料/文件中建议使用PA0进行按钮中断。经过测试和检查,RT-Spark板上并没有将物理按钮连接到PA0上。

设计与测试

第一部分 — — — 硬件描述

所使用的硬件是基于STM32F407ZGT6微控制器的RT-Spark开发板。由于该板已内置两个LED和方向按钮,因此无需额外的外部元件。引脚分配如下:

第一部分 1.1 — — — 软件设置

•打开 STM32CubeMX

•转到“文件”→“新建”→“STM32 项目”

•在芯片选择器中,搜索 STM32F407ZGT66 并选中它

•点击下一步

•前往项目管理器,设置您偏好的项目名称

•将工具链/IDE设置为STM32CubeIDE

•在左上角的“文件”中保存项目,或直接按 Ctrl + S

第1.2部分 — — 配置GPIO引脚以连接LED

•在引脚分配与配置选项卡中,找到引脚 PF11

•点击并将其设置为 GPIO 输出

•进入系统核心 → GPIO,点击 PF11,并将用户标签设置为 LED_RED

•找到引脚 PF12,将其设置为 GPIO 输出

•将用户标签设置为LED_BLUE

•保存项目并生成代码

第1.3部分 — — 配置系统时钟

在设置定时器之前,系统时钟必须以84 MHz运行。默认情况下,CubeMX生成的代码在16 MHz的原始HSI上运行,这会导致定时器计算完全错误。这是本次实验/项目中遇到的第一个问题:由于ARR被设置为最大值4,294,967,295,而不是9999,LED持续亮着。

•转到时钟配置选项卡

•找到 HCLKCLKCLK 框,输入 84,然后按回车键

•CubeMXMX 将自动配置 PLL 以达到 84 MHz

•保存并重新生成代码

第1.4节 — — 配置TIM2和TIM3

TIM222 每 11 秒(1 Hz)触发一次,TIM333 每 0.55 秒(2 Hz)触发一次。根据第 222 节的定时器周期公式:f_timer = f_APB / (PSC + 1) / (ARR + 1)

对于TIM2:84,000,000 / (8399+1) / (9999+1) = 1 Hz

对于TIM3:84,000,000 / (8399+1) / (4999+1) = 2 Hz

CubeMX 的步骤:

•进入定时器 → TIM2,将时钟源设置为内部时钟

•将预分频器设置为8399,计数周期设置为9999

•在 NVIC 设置中,启用 TIM22 全局中断。

•将优先级设置为0

•进入定时器 → TIM3,将时钟源设置为内部时钟

•将预分频器设置为8399,计数周期设置为4999

•在 NVIC 设置中,启用 TIM33 全局中断。

•将优先级设置为1

•进入系统核心 → NVIC NVIC 并确认优先级

•保存并重新生成代码

第1.5部分 — — 配置调试引脚

•PE000 被配置为 DEBUG_PIN 用于定时测量。

•该引脚在TIM2中断服务程序的开始和结束时被切换。

•以及任务A,允许使用TISR和TTask进行测量

•DWTWT 循环计数器。

•找到引脚 PE0 → 设置为 GPIO 输出

•进入系统核心 → GPIO,点击 PE00 并设置

•用户标签到DEBUG_PIN

•保存并重新生成代码

第1.6部分 — — 配置按钮

实验室最初要求使用PA0,但RT-Spark板上并没有物理按键。在查阅RT-Thread文档后发现,KEY_UP引脚位于PC5,因此改用PC5。实验室还要求使用上升沿+下拉电阻,但该板上的KEY_UP按钮为低电平激活,按下时会连接到GND,而正确的配置应为下降沿+上拉电阻。

•找到引脚 PC5 → 设置为 GPIO_EXTI5

•进入系统核心 → GPIO,点击 PC55 并设置:

•GPIOGPIO 模式:外部中断模式(下降沿)

•GPIO 上拉/下拉:上拉

•进入系统核心 → NVIC,启用 EXTI EXTI EXTI 线[9:5]中断,将优先级设置为 2

第二部分 — — — 软件架构与实现

第二部分 1 — — — 前景/背景架构

系统使用带有中断的循环执行机制。有两个优先级层次:后台(中断服务例程,ISRs)——在被触发时运行,处理紧急任务,并设置标志以通知前台。

前台(主循环)——持续运行,检查标志位并执行实际任务。这比使用 HAL_Delay()() 进行轮询更高效,因为在定时器事件之间,CPUCPU 可以自由进行其他工作。

第2.2部分 — — 全局标志变量

三个标志变量被声明为 volatile,因此编译器不会优化掉主循环中的读取操作:

volatile uint8_t task_adc_ready = 0;

volatile uint8_t task_display_ready = 0;

volatile uint32_t tick_count = 0;

第2.3部分 — — 定时器回调(后台任务)

HAL定时器回调函数在一个函数中处理TIM2和TIM3。htim->Instance字段用于标识是哪个定时器触发了该事件:

第2.4部分 — 主循环(前台任务)

第2.5部分 — — — 按钮中断(事件触发)

第三部分 — 结果

第3.1部分 — LED闪烁输出

刷写代码后,观察到以下情况:

•红色LED每1秒通过TIM2中断闪烁一次

•绿色LED每0.5秒闪烁一次,通过TIM3中断实现

•按下 KEY_UP(PC5)会立即切换两个LED灯。

•前景/背景调度正常工作

第3.2部分 — — 序列图

下方的时序图展示了系统运行3秒的过程,包括TIM2和TIM3以各自的速度触发,标志位传递至主循环,并在约t=1.2秒处发生按钮按下事件。该图表使用Lucidchart创建。

第3.3部分 — 时间测量

使用 ARM Cortex-M4 上的 DWT(数据断点与跟踪)循环计数器获取了真实的时间值。该计数器是一个 32 位寄存器,以 84 MHz 的精度计数 CPU 时钟周期(1 个周期周期 ≈ 11.9 ns)。代码中已启用 DWTWT 计数器:

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;

DWT->CYCCNT = 0;

DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

在TIM2中断服务例程(ISR)的入口/出口处,以及当task_adc_ready = 1和if (task_adc_ready for TLatency)时设置了断点。每次断点处使用STM32CubeIDE中的表达式窗口读取DWT->CYCCNT寄存器。

TISR测量:

DWT在ISR开始时(第69行):246

DWT在ISR末端(第76行):346

时钟周期:346 - 246 = 10000 周期

时间:100 / 84,000,000 = 1.199 微秒

延迟测量:

DWT 在 task_adc_ready = 1 时:44,094,304

DWT 在 if(task_adc_ready): 50, 141, 984

时钟周期:50,141,984 - 44,094,304 = 6,047,68000 周期

时间:6,047,680 / 84,000,000 = 7222 毫秒

时间表:

72毫秒的延迟高于理论上的20毫秒估算值。这是因为该延迟不仅包含了任务B中的HAL_Delay(20),还包括中断服务例程(ISR)完成、返回主循环以及再次回到任务adc_ready检查的时间。这与系统设计预期的情况非常吻合。

第四部分 - 分析

第五部分 — 结论

我学到的东西:

该实验展示了轮询调度与中断驱动调度之间的实际差异。使用硬件定时器可避免在主循环中使用 HAL_Delay(),从而让 CPU 在事件之间有更多时间处理其他任务。前景/后台架构是一种简洁而简单的方式,可在不依赖完整实时操作系统的情况下处理不同优先级的任务。DWTWT 循环计数器是一个有用的工具——测量到的 TISR 为 1.199 微秒,证实了保持中断服务例程(ISRs)较短的重要性,因为整个 TIM2 中断服务例程仅需 100 个时钟周期即可完成。

面临的问题:

问题1——LED在第一次闪烁后一直保持亮起且无法闪烁。系统时钟使用16 MHz的原始HSI运行,而ARR设置为4,294,967,295,而非9999。这两个问题通过将HCLK设置为84 MHz,并在CubeMX中修正ARR得以解决。

问题2——按钮中断未生效。RT-Spark板上PA0(按要求)没有物理按钮,KEY_UP位于PC5。配置已更改为PC5的下降沿+上拉,并将回调函数更新为检查GPIO_PIN_5。

问题3——在TIM3 NVIC设置选项卡中,NVIC抢占优先级被灰色显示。通过从“系统核心 → NVIC”下的全局NVIC表中修改优先级来解决该问题。

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭