第1章 跑马灯实验

第一章 跑马灯实验

1. 导入

任何一个单片机, 最简单的外设莫过于 IO 口的高低电平控制了,本章将通过一个经典的跑马灯程序,带大家开启 STM32F4 之旅, 通过本章的学习, 你将了解到 STM32F4 的 IO 口作为输出使用的方法。 在本章中, 我们将通过代码控制开发板上的两个 LED: DS0 和 DS1 交替闪烁,实现类似跑马灯的效果。

2. 硬件设计

本章用到的硬件只有 LED(DS0 和 DS1)。其电路在开发板上默认是已经连接好了的。 DS0 接 PF9, DS1 接 PF10。所以在硬件上不需要动任何东西。(低电平点亮)根据原理图一下就可以看出来,就不做分析了吧。。。

屏幕截图 20241217 210533png

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 代码解释

  1. 头文件引入
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
  • sys.h 可能包含了系统级的初始化函数,例如时钟配置。
  • delay.h 提供了延时函数的声明。
  • usart.h 可能包含了串口通信相关的函数声明(在这段代码中并未使用)。
  • led.h 包含了LED控制相关的函数声明。
  1. 主函数
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 修订内容,优化代码

posted @ 2024-09-27 14:55  hazy1k  阅读(41)  评论(0编辑  收藏  举报