第1章 跑马灯实验
第一章 跑马灯实验
1. 导入
任何一个单片机, 最简单的外设莫过于 IO 口的高低电平控制了,本章将通过一个经典的跑马灯程序,带大家开启 STM32F4 之旅, 通过本章的学习, 你将了解到 STM32F4 的 IO 口作为输出使用的方法。 在本章中, 我们将通过代码控制开发板上的两个 LED: DS0 和 DS1 交替闪烁,实现类似跑马灯的效果。
2. 硬件设计
本章用到的硬件只有 LED(DS0 和 DS1)。其电路在开发板上默认是已经连接好了的。 DS0 接 PF9, DS1 接 PF10。所以在硬件上不需要动任何东西。(低电平点亮)根据原理图一下就可以看出来,就不做分析了吧。。。
3. 软件设计
3.1 LED宏定义设置
#ifndef _LED_H
#define _LED_H
#include "sys.h"
#define LED0_GPIO GPIOF
#define LED0_PIN GPIO_PIN_9
#define LED1_GPIO GPIOF
#define LED1_PIN GPIO_PIN_10
void LED_Init(void);
#endif
现在工程不算复杂,宏定义倒是可有可无,不过以后我们会多多用到,因为宏定义可以使工程结构更加清晰也方便迁移
3.2 LED初始化
#include "led.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOF_CLK_ENABLE(); // 初始化GPIOF时钟
GPIO_Initure.Pin = LED0_PIN | LED1_PIN; // 使用LED0_PIN和LED1_PIN
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_Initure.Pull = GPIO_PULLUP; // 上拉
GPIO_Initure.Speed = GPIO_SPEED_HIGH; // 高速
HAL_GPIO_Init(GPIOF, &GPIO_Initure);
}
// void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
// 该函数用于设置指定GPIO端口的指定引脚的电平状态
// 函数参数:
// GPIOx:GPIO端口,可以是GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF等。
// GPIO_PIN:GPIO引脚,可以是GPIO_PIN_0~GPIO_PIN_15。
// PinState:GPIO引脚的电平状态,可以是GPIO_PIN_RESET、GPIO_PIN_SET。
// 其中GPIO_PIN_RESET为低电平,GPIO_PIN_SET为高电平。
在
在学习STM32F4HAL库函数前,我相信你一定学过了STM32F103标准库,所以这个LED初始化不必多解释,有一个新出现函数我们也用注释的形式讲解了
3.3 主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
int main(void)
{
HAL_Init(); // 初始化HAL库,来源于"stm32f4xx_hal.c"
// 设置时钟,168Mhz,来源于"sys.c" 函数参数:plln,pllm,pllp,pllq
// 部晶振为8M的时候,推荐值:plln=336,pllm=8,pllp=2,pllq=7.
// 得到:Fvco=8*(336/8)=336Mhz
// SYSCLK=336/2=168Mhz
// Fusb=336/7=48Mhz
Stm32_Clock_Init(336,8,2,7); // 系统时钟初始化
delay_init(168); // 初始化延时函数,168Mhz系统时钟
LED_Init(); // 初始化LED
while(1)
{
// 亮LED0,灭LED1
HAL_GPIO_WritePin(LED0_GPIO, LED0_PIN, GPIO_PIN_RESET); // 点亮LED0
HAL_GPIO_WritePin(LED1_GPIO, LED1_PIN, GPIO_PIN_SET); // 熄灭LED1
delay_ms(500); // 延时500ms
// 灭LED0,亮LED1
HAL_GPIO_WritePin(LED0_GPIO, LED0_PIN, GPIO_PIN_SET); // 熄灭LED0
HAL_GPIO_WritePin(LED1_GPIO, LED1_PIN, GPIO_PIN_RESET); // 点亮LED1
delay_ms(500); // 延时500ms
}
}
4. 小结
作为我们第一个HAL库程序,我们有必要解释的详细一点,并且与标准库进行一下比较:
4.1 代码解释
- 头文件引入
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
sys.h
可能包含了系统级的初始化函数,例如时钟配置。delay.h
提供了延时函数的声明。usart.h
可能包含了串口通信相关的函数声明(在这段代码中并未使用)。led.h
包含了LED控制相关的函数声明。
- 主函数
int main(void)
{
HAL_Init(); // 初始化HAL库
Stm32_Clock_Init(336,8,2,7); // 设置时钟,168MHz
delay_init(168); // 初始化延时函数
LED_Init(); // 初始化LED
while(1)
{
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9, GPIO_PIN_RESET); // LED0对应引脚PF9拉低,亮,等同于LED0(0)
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10, GPIO_PIN_SET); // LED1对应引脚PF10拉高,灭,等同于LED1(1)
delay_ms(500); // 延时500ms
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET); // LED0对应引脚PF9拉高,灭,等同于LED0(1)
HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET); // LED1对应引脚PF10拉低,亮,等同于LED1(0)
delay_ms(500); // 延时500ms
}
}
HAL_Init()
:初始化 STM32 的 HAL 库,这为后续的 HAL 函数调用做好准备。Stm32_Clock_Init(336,8,2,7)
:配置系统时钟,可能将系统时钟设置为 168 MHz。delay_init(168)
:初始化延时函数,设置延时时钟源。LED_Init()
:初始化 LED 控制相关的 GPIO 引脚。while(1)
:主循环中,LED0 和 LED1 交替闪烁,每个状态持续 500ms。
4.2 标准库改造
- 主函数
#include "stm32f4xx.h" // 包含 STM32F4 系列微控制器的头文件
#include "delay.h" // 包含延时函数的头文件
// LED 引脚初始化函数
void LED_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct; // 定义 GPIO 初始化结构体
// 使能 GPIOF 时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
// 配置 PF9 和 PF10 为推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // 选择 PF9 和 PF10 引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 设置为输出模式
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度设置为 50 MHz
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // 输出类型设置为推挽输出
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // 不使用上下拉电阻
GPIO_Init(GPIOF, &GPIO_InitStruct); // 初始化 GPIOF
}
int main(void) {
// 系统时钟初始化
SystemInit();
// 延时函数初始化,设置系统时钟频率(假设为 168 MHz)
delay_init(168);
// LED 初始化
LED_Init();
while (1) {
// 点亮 PF9 (LED0)
GPIO_SetBits(GPIOF, GPIO_Pin_9);
// 熄灭 PF10 (LED1)
GPIO_ResetBits(GPIOF, GPIO_Pin_10);
delay_ms(500); // 延时 500 毫秒
// 熄灭 PF9 (LED0)
GPIO_ResetBits(GPIOF, GPIO_Pin_9);
// 点亮 PF10 (LED1)
GPIO_SetBits(dIOF, GPIO_Pin_10);
delay_ms(500); // 延时 500 毫秒
}
}
2024.9.25 第一次修订,后期不再维护
2024.12.17 修订内容,优化代码