新闻详情

新闻详情

首页 / 资讯中心 / 详情

STM32F407 :RGB 流水灯的原理与实现

发布时间:2026/11/13 22:57:01来源:尧图网络
STM32F407 :RGB 流水灯的原理与实现
一、实验目标使用 STM32F407 控制板载 RGB LED让红、绿、蓝三种颜色依次点亮每种颜色保持 500ms然后循环。本实验使用STM32 标准外设库。代码分为三部分led目录配置 GPIO提供点亮和熄灭接口。delay目录使用 SysTick 实现毫秒延时。User/main.c决定亮灯顺序和保持时间。这里的“流水”是一颗 RGB 灯依次切换颜色。如果要实现一排 LED 逐颗移动还需要多个独立可控的灯。二、先看原理图为什么低电平点亮本实验所用板卡资料中RGB LED 的三个通道连接如下颜色STM32 引脚点亮电平熄灭电平红PF6低高绿PF7低高蓝PF8低高这是共阳 RGB LED。它的公共正极接电源三个颜色通道的负极分别连接 GPIO。当某个 GPIO 输出低电平时对应通道形成电流路径LED 点亮。3.3V → LED → 限流电阻 → GPIO 低电平 → GND因此在这块板上GPIO_ResetBits(GPIOF, GPIO_Pin_6); /* PF6 输出低电平红灯亮 */ GPIO_SetBits(GPIOF, GPIO_Pin_6); /* PF6 输出高电平红灯灭 */LED 是高电平亮还是低电平亮必须以实际原理图为准。本地 V2 原理图还显示 RGB 灯公共端通过 J73 接到 3.3V如果使用该版本需要确认跳帽已接通。三、GPIO 时钟和系统时钟是什么关系GPIO 是 STM32 内部的外设模块需要时钟才能工作。STM32F407 的 GPIOF 位于AHB1 总线所以使用 GPIOF 前要开启它的外设时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);这行代码的作用是打开通往 GPIOF 的时钟开关。PF6、PF7、PF8 都属于 GPIOF开启一次即可。本工程的时钟配置以 25MHz 外部晶振为基础经过 PLL 后得到 168MHz 系统时钟25MHz ÷ 25 × 336 ÷ 2 168MHz时钟路径可以简化为外部晶振 → PLL → 系统时钟 → AHB1 总线 → GPIOFGPIOF 有时钟不代表 LED 会按这个频率闪烁。程序把 PF6 拉低后它会保持低电平红灯持续亮只有程序再次改变 PF6 的电平红灯状态才会改变。四、GPIO 如何配置本实验把 PF6、PF7、PF8 配置成普通 GPIO 推挽输出配置项设置引脚PF6、PF7、PF8模式普通 GPIO 输出输出类型推挽输出上下拉无上下拉输出速度GPIO_Speed_2MHz初始输出高电平三个颜色都熄灭GPIO_Speed_2MHz是 GPIO 的输出速度等级不是流水灯每秒切换 200 万次。流水灯的切换速度由程序中的延时时间决定。初始化时先预置高电平再配置为输出模式可以避免启用输出时 LED 短暂亮起。五、LED BSP封装引脚和电平操作1.led/bsp_led.h#ifndef BSP_LED_H #define BSP_LED_H #include stm32f4xx.h /* 共阳 RGB LEDPF6 红、PF7 绿、PF8 蓝低电平亮 */ #define LED_RED GPIO_Pin_6 #define LED_GREEN GPIO_Pin_7 #define LED_BLUE GPIO_Pin_8 #define LED_ALL (LED_RED | LED_GREEN | LED_BLUE) void LED_GPIO_Config(void); void LED_On(uint16_t pins); void LED_Off(uint16_t pins); #endif2.led/bsp_led.c#include bsp_led.h void LED_GPIO_Config(void) { GPIO_InitTypeDef gpio; /* 开启 GPIOF 外设时钟 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); /* 先输出高电平让三个颜色保持熄灭 */ GPIO_SetBits(GPIOF, LED_ALL); /* 配置 PF6、PF7、PF8 为普通 GPIO 推挽输出 */ GPIO_StructInit(gpio); gpio.GPIO_Pin LED_ALL; gpio.GPIO_Mode GPIO_Mode_OUT; gpio.GPIO_OType GPIO_OType_PP; gpio.GPIO_PuPd GPIO_PuPd_NOPULL; gpio.GPIO_Speed GPIO_Speed_2MHz; GPIO_Init(GPIOF, gpio); } void LED_On(uint16_t pins) { /* 低电平点亮 */ GPIO_ResetBits(GPIOF, pins LED_ALL); } void LED_Off(uint16_t pins) { /* 高电平熄灭 */ GPIO_SetBits(GPIOF, pins LED_ALL); }这样main.c只需写LED_On(LED_RED)不必每次都考虑 PF6 对应哪个颜色、该输出高电平还是低电平。LED_On()只操作指定通道不会自动关闭其他颜色。要保证红、绿、蓝轮流单独点亮需要在打开下一个颜色前关闭上一个颜色。六、SysTick 如何实现 1ms 计时使用空循环延时for (i 0; i 100000; i) { }很难准确知道经过了多久因为耗时会受时钟频率和编译优化影响。本实验使用 Cortex-M4 内核的SysTick 定时器。假设内核时钟为 168MHz下面的配置表示每计数 168000 个内核时钟周期产生一次 SysTick 中断SysTick_Config(168000);中断间隔为168000 ÷ 168000000 秒 0.001 秒 1ms工程中使用下面的写法根据SystemCoreClock计算计数值SystemCoreClockUpdate(); SysTick_Config(SystemCoreClock / 1000U);SystemCoreClockUpdate()读取当前时钟配置并更新软件变量不会重新配置系统时钟。计算正确的前提是工程定义的外部晶振频率与实物一致。1.delay/bsp_delay.h#ifndef BSP_DELAY_H #define BSP_DELAY_H #include stm32f4xx.h void Delay_Init(void); void Delay_ms(uint32_t ms); void Delay_Tick(void); #endif2.delay/bsp_delay.c#include bsp_delay.h /* 中断中会修改主程序中会读取 */ static volatile uint32_t ticks; void Delay_Init(void) { SystemCoreClockUpdate(); ticks 0; /* 配置 SysTick 约每 1ms 产生一次中断 */ if (SysTick_Config(SystemCoreClock / 1000U) ! 0U) { while (1) { } } } void Delay_Tick(void) { ticks; } void Delay_ms(uint32_t ms) { uint32_t start ticks; while ((uint32_t)(ticks - start) ms) { } }ticks是毫秒计数。volatile告诉编译器这个变量可能被中断改变主程序每次读取时都要获取它的当前值。Delay_ms()等待的是计数增加了多少不是靠执行多少次空循环来估算时间。3. 在 SysTick 中断函数中更新计数在现有User/stm32f4xx_it.c中加入#include bsp_delay.h找到原有的SysTick_Handler()将它修改为void SysTick_Handler(void) { Delay_Tick(); }这里是修改已有函数不要再写第二个同名的SysTick_Handler()。执行过程如下SysTick 每约 1ms 产生一次中断 ↓ CPU 自动进入 SysTick_Handler() ↓ 调用 Delay_Tick() ↓ ticks 加 1以Delay_ms(500)为例假设开始时ticks为 100当前ticks与开始时相差是否继续等待1000ms是200100ms是599499ms是600500ms否如果SysTick_Handler()仍是空函数ticks就不会增加Delay_ms(500)也就无法结束。这个延时函数会让主循环等待但等待期间仍需要保持中断开启因为ticks依赖 SysTick 中断更新。不要在 SysTick 中断函数内部调用这个Delay_ms()。七、main.c负责流水灯顺序#include bsp_led.h #include bsp_delay.h /* 每个颜色保持 500ms */ #define LED_STEP_MS 500U int main(void) { LED_GPIO_Config(); Delay_Init(); while (1) { LED_On(LED_RED); Delay_ms(LED_STEP_MS); LED_Off(LED_RED); LED_On(LED_GREEN); Delay_ms(LED_STEP_MS); LED_Off(LED_GREEN); LED_On(LED_BLUE); Delay_ms(LED_STEP_MS); LED_Off(LED_BLUE); } }程序运行顺序为开启 GPIOF 时钟、初始化 LED 引脚 ↓ 初始化 SysTick 毫秒计时 ↓ 红灯亮 500ms → 红灯灭 ↓ 绿灯亮 500ms → 绿灯灭 ↓ 蓝灯亮 500ms → 蓝灯灭 ↓ 返回红灯持续循环修改LED_STEP_MS就能改变流水速度。例如改为200U每种颜色约保持 200ms。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/13 0:43:49

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/12 23:59:09

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/13 10:09:00

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/13 13:31:48

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/13 16:11:45

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/13 0:02:27

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉