《ARM嵌入式》课程

普中STM32-F103精灵开发版LED灯闪烁教程(含完整代码与解析)

一、开发环境搭建

1. 硬件准备

• 普中STM32-F103精灵开发板(芯片型号:STM32F103C8)

• USB数据线(用于供电和程序下载)

2. 软件准备

• Keil MDK 5(STM32开发集成环境,下载地址)

• STM32F1系列器件支持包(通过Keil内的Pack Installer安装)

二、硬件原理分析

1. LED灯电路

• 控制方式:通过GPIO端口输出高低电平控制,开发板采用低电平点亮逻辑。

• 示例连接:假设LED灯连接到PA8引脚,当PA8输出低电平时,LED导通点亮;输出高电平时熄灭。

2. 按键电路(可选功能)

• 检测逻辑:按键连接到PB12引脚,开发板内部已配置上拉电阻,按键未按下时PB12为高电平,按下时电平拉低。

三、完整程序代码及分段解析

1. 新建工程步骤

1. 打开Keil MDK,点击 Project → New μVision Project,命名工程(如“LED_Flash”)并选择保存路径。

2. 在器件选择窗口中搜索并选择 STM32F103C8,点击 OK。

3. 在弹出的“Manage Run-Time Environment”中,勾选 CMSIS 和 STM32F1xx Device Family 下的 Startup 文件,点击 OK 完成工程创建。

2. 编写代码及解析

main.c
#include "stm32f10x.h"                  // 芯片寄存器定义  
#include "stm32f10x_conf.h"              // 库函数头文件配置  
解析:

• #include "stm32f10x.h":包含了STM32F10x系列芯片的寄存器定义,是操作硬件寄存器的基础。

• #include "stm32f10x_conf.h":用于配置工程中需要使用的库函数头文件,在本文件中配置了GPIO和RCC相关的头文件,为后续调用相关库函数做准备。
// 宏定义:LED和按键对应引脚  
#define LED_PIN       GPIO_Pin_8    // LED连接PA8  
#define LED_PORT      GPIOA         // 端口A  
#define KEY_PIN       GPIO_Pin_12   // 按键连接PB12(可选功能)  
#define KEY_PORT      GPIOB         // 端口B  
解析:
使用宏定义将具体的引脚编号和端口名称进行符号化,方便后续代码的修改和维护。如果开发板上LED或按键的连接引脚发生变化,只需要修改此处的宏定义即可,无需在代码中逐个修改引脚参数。
// 延时函数(基于SysTick定时器,72MHz系统时钟)  
void delay_ms(uint32_t ms) {  
    SysTick->LOAD = (ms * 72000) / 8;  // 计算重载值  
    SysTick->VAL = 0x00;               // 清空当前值  
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;  // 使能定时器  
    while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));  // 等待计数完成  
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭定时器  
}  
解析:

• 函数功能:实现毫秒级延时。

• 原理:利用STM32内部的SysTick定时器。SysTick定时器是一个24位的倒计数定时器,当计数值为0时,将从LOAD寄存器中自动重装初值。

• 关键代码解释:

◦ SysTick->LOAD = (ms * 72000) / 8;:计算定时器的重载值。STM32F103默认系统时钟为72MHz,经8分频后,SysTick定时器的时钟频率为9MHz(即每1/9μs计数一次)。为了实现ms毫秒的延时,需要计数ms * 9000次,因此将该值赋给LOAD寄存器。

◦ SysTick->VAL = 0x00;:清空当前计数值,确保定时器从0开始计数。

◦ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;:使能SysTick定时器。

◦ while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));:等待定时器计数完成,当计数值减为0时,会设置COUNTFLAG标志位,通过循环检测该标志位判断延时是否结束。

◦ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;:关闭SysTick定时器。
int main(void) {  
    GPIO_InitTypeDef GPIO_InitStruct;  // GPIO初始化结构体  

    // 1. 使能GPIOA和GPIOB时钟(APB2总线)  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);  
解析:

• GPIO_InitTypeDef GPIO_InitStruct;:定义一个GPIO初始化结构体变量,用于配置GPIO引脚的工作模式、速度等参数。

• RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);:

◦ 功能:使能GPIOA和GPIOB的时钟。在STM32中,外设使用前必须先使能其对应的时钟,GPIOA和GPIOB挂载在APB2总线上,因此通过此函数开启时钟。

◦ 参数解释:

◦ RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB:通过按位或操作同时选择GPIOA和GPIOB两个外设。

◦ ENABLE:表示使能选定的外设时钟。
    // 2. 配置LED引脚为推挽输出(50MHz速度)  
    GPIO_InitStruct.GPIO_Pin = LED_PIN;  
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出模式  
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(LED_PORT, &GPIO_InitStruct);  
解析:

• 配置LED引脚为推挽输出模式:

◦ GPIO_InitStruct.GPIO_Pin = LED_PIN;:选择要配置的引脚为之前定义的LED_PIN(即PA8)。

◦ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;:设置引脚工作模式为推挽输出。推挽输出模式下,引脚可以输出高电平或低电平,适合直接驱动LED等负载。

◦ GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;:设置引脚的最大输出速度为50MHz,以满足快速切换电平的需求。

◦ GPIO_Init(LED_PORT, &GPIO_InitStruct);:将配置好的参数应用到LED_PORT(即GPIOA)上。
    // 3. 配置按键引脚为浮空输入(可选功能)  
    GPIO_InitStruct.GPIO_Pin = KEY_PIN;  
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  // 浮空输入模式  
    GPIO_Init(KEY_PORT, &GPIO_InitStruct);  
解析:

• 配置按键引脚为浮空输入模式:

◦ GPIO_InitStruct.GPIO_Pin = KEY_PIN;:选择要配置的引脚为之前定义的KEY_PIN(即PB12)。

◦ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;:设置引脚工作模式为浮空输入。浮空输入模式下,引脚电平状态完全由外部电路决定,由于开发板内部已为按键引脚配置上拉电阻,按键未按下时引脚为高电平,按下时拉低为低电平。

◦ GPIO_Init(KEY_PORT, &GPIO_InitStruct);:将配置好的参数应用到KEY_PORT(即GPIOB)上。
    while (1) {  
        // 基础功能:LED闪烁(无需按键,独立运行)  
        GPIO_ResetBits(LED_PORT, LED_PIN);  // 低电平点亮LED  
        delay_ms(500);                      // 延时500ms  
        GPIO_SetBits(LED_PORT, LED_PIN);    // 高电平熄灭LED  
        delay_ms(500);                      // 延时500ms  

        // 扩展功能:按键控制(单次按下常亮,双击快速闪烁)  
        // (如需使用,取消下方注释并连接按键电路)  
        /*  
        if (GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_RESET) {  
            delay_ms(10);  // 消抖  
            if (GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_RESET) {  
                // 单次按下逻辑  
                GPIO_ResetBits(LED_PORT, LED_PIN);  // 常亮  
                while (GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_RESET);  
            }  
        }  
        */  
    }  
}  
解析:

• 基础功能:LED闪烁:

◦ GPIO_ResetBits(LED_PORT, LED_PIN);:将LED_PIN(PA8)引脚电平置为低电平,点亮LED。

◦ delay_ms(500);:调用延时函数,使LED保持点亮状态500毫秒。

◦ GPIO_SetBits(LED_PORT, LED_PIN);:将LED_PIN(PA8)引脚电平置为高电平,熄灭LED。

◦ delay_ms(500);:再次调用延时函数,使LED保持熄灭状态500毫秒。通过不断循环实现LED的周期性闪烁。

• 扩展功能:按键控制(注释状态,需手动启用):

◦ if (GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_RESET):检测按键是否按下,通过读取KEY_PIN(PB12)引脚电平是否为低电平判断。

◦ delay_ms(10);:软件消抖,防止按键机械抖动导致误判。

◦ 内层if语句:二次确认按键按下,确保检测的有效性。

◦ GPIO_ResetBits(LED_PORT, LED_PIN);:按键按下时,将LED置为常亮状态。

◦ while (GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_RESET);:等待按键释放,阻塞程序直至按键松开。

四、程序编译与下载

1. 编译工程

点击Keil界面上方 Rebuild All,编译成功后生成 .hex 文件(若报错,检查引脚配置或语法错误)。

2. 下载程序

• ST-Link下载(开发板支持ST-Link接口):

1. 用USB线连接开发板与电脑。

2. 打开 ST-Link Utility,点击 Connect 连接开发板。

3. 点击 Open File 选择编译生成的**.hex**文件,点击 Program 下载。

五、功能测试

1. 基础功能(无按键版)

• 下载程序后,开发板上电,LED灯会以500ms间隔闪烁(亮灭交替)。

2. 扩展功能(按键控制版,需连接按键)

• 单次按下:按键按下时LED常亮,松手后恢复闪烁。

• 双击操作:快速连续按下两次,LED以200ms间隔快速闪烁,再次按下任意键恢复默认节奏。

六、常见问题排查

1. LED不亮:

◦ 检查USB供电是否正常(开发板电源指示灯是否亮起)。

◦ 确认代码中LED引脚与开发板实际连接一致(如是否为PA8或其他引脚)。

2. 程序无法下载:

◦ 确保开发板处于待机模式(部分开发板需按下复位键再下载)。

◦ 检查下载工具是否匹配(如使用DAP-Link需更换对应驱动)。

通过本教程,可快速掌握STM32基础开发流程,后续可尝试修改延时参数或添加更多外设(如蜂鸣器、OLED屏幕)扩展功能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值