当前位置: 首页 > news >正文

普中STM32F103ZET6开发攻略(一)

各位看官老爷们,点击关注不迷路哟。你的点赞、收藏,一键三连,是我持续更新的动力哟!!!

目录

普中STM32F103ZET6开发攻略

1. GPIO端口实验——点亮LED灯

1.1 实验目的

1.2 实验原理

1.3 实验环境和器材:

1.4 实验思路

1.5 实验代码

1.5.1 LED相关代码

1.5.2 delay相关代码

1.6 实验思考和拓展

1.6.1 如何调整LED灯的闪烁频率?

1.6.2 如何实现呼吸灯效果?

1.6.2.1 非 PWM 实现呼吸灯的原理

1.6.2.2 具体实现方法(以 STM32 为例)

1. 亮度等级划分

2. 控制亮灭时间比例

1.6.2.3 代码实例:

1.6.3 除了使用简单延时外,STM32还有哪些更加精准的延时方式?

1.7 注意事项


普中STM32F103ZET6开发攻略

1. GPIO端口实验——点亮LED灯

1.1 实验目的

  1. 了解STM32F10x微控制器的GPIO口结构和基本操作

  1. 掌握STM32标准库函数对GPIO的配置和使用方法

  1. 学会使用GPIO控制LED的亮灭,实现LED基本显示效果

  1. 掌握简单延时函数的编写方法

1.2 实验原理

  1. GPIO原理

    STM32的GPIO(通用输入/输出端口)用于外设信号的输入输出控制。STM32F10x系列GPIO具有以下特性:

    (1) 每个I/O端口有16个可独立配置的I/O位

    (2) 支持8种不同的工作模式

    模式分类具体模式核心特点典型应用
    输入模式浮空输入无内部上下拉,电平由外部决定外部信号采集(需外部上下拉)
    上拉输入内部上拉,默认高电平按键输入(低电平有效)
    下拉输入内部下拉,默认低电平按键输入(高电平有效)
    模拟输入连接 ADC,禁用数字输入功能ADC 模数转换
    输出模式开漏输出需外部上拉,支持线与逻辑I2C 总线、电平转换
    推挽输出直接输出高低电平,驱动能力强LED 控制、普通数字信号
    开漏复用功能外设驱动,需外部上拉SPI/I2C 外设输出
    推挽复用功能外设驱动,直接输出高低电平USART/CAN 外设输出

    通过配置 GPIO 的模式寄存器(CRL/CRH)和输出类型寄存器,可灵活选择上述工作模式,满足不同外设的控制需求。

    (3) 每个I/O口可以产生外部中断

    (4) 位设置/复位寄存器,支持原子位操作

  2. LED控制原理

    LED (发光二极管) 是一种单向导电器件,只有在正向偏置时才会发光。根据开发板硬件设计,LED灯通常采用如下接法:

    (1) 共阳极接法:LED阳极接VCC,阴极接单片机GPIO,GPIO输出低电平时LED点亮;

    (2) 共阴极接法:LED阴极接地,阳极接单片机GPIO,GPIO输出高电平时LED点亮;

    本实验中,LED灯采用的是共阳极接法。

1.3 实验环境和器材:

  1. 电脑:Keil5+Vstudio

  2. 硬件资源:普中玄武F103开发板(主控芯片:STM32F103ZET6

1.4 实验思路

硬件接线图如下所示:

由上图可知:

  1. DS0即LED0、DS1即LED1,分别连接着:PB5和PE5

    LED0连接到GPIOB的Pin5引脚,LED1连接到GPIOE的Pin5引脚

  2. 为了完成实验目的:

    我们需要再项目工程中新建两个“库函数”:LED.c+delay.c

1.5 实验代码

1.5.1 LED相关代码

头文件:

//led.h
#ifndef _led_H
#define _led_H
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"  // 包含GPIO相关的函数和宏定义
#include "stm32f10x_rcc.h"   // 包含RCC(时钟控制)相关的函数和宏定义
void LED_init(void); 
void LED0_On(void);
void LED0_Off(void);
void LED1_On(void);
void LED1_Off(void);
void LED0_Toggle(void);
void LED1_Toggle(void);
#endif
​

源文件:

//led.c
#include "led.h"
​
void LED_init(void)
{// 使能 GPIOB 和 GPIOE 的时钟(几乎所有外设(包括 GPIO)在使用前都需要先使能对应的时钟)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);
​GPIO_InitTypeDef GPIO_InitStructure;
​// 配置 PB5 为推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);
​// 配置 PE5 为推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_Init(GPIOE, &GPIO_InitStructure);
​// 初始状态GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);
}
​
​
void LED0_On(void) {GPIO_ResetBits(GPIOB, GPIO_Pin_5);
}
void LED0_Off(void){GPIO_SetBits(GPIOB, GPIO_Pin_5);
}
void LED1_On(void) {GPIO_ResetBits(GPIOE, GPIO_Pin_5);
}
void LED1_Off(void) {GPIO_SetBits(GPIOE, GPIO_Pin_5);
}
void LED0_Toggle(void) {GPIOB->ODR ^= GPIO_Pin_5;
}
void LED1_Toggle(void) {GPIOE->ODR ^= GPIO_Pin_5;
}
​

因为我们这里是直接输出高低电平:所以采用的是推挽输出的方式,由上文可知:推完输出直接输出高低电平,驱动能力强。

初始状态需要设置成为高电平,由上文中的硬件接线图可知,LED(发光二极管)是在正向偏置时才会发光,所以应该是“低电平有效

1.5.2 delay相关代码

头文件:

#ifndef __DELAY_H
#define __DELAY_H
​
#include "stm32f10x.h"
​
void Delay_Init(void);
void Delay_ms(u32 nms);
​
#endif
​

源文件:

#include "delay.h"
​
static u32 fac_ms = 0;
​
void Delay_Init(void)
{SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // HCLK/8fac_ms = SystemCoreClock / 8000;
}
​
void Delay_ms(u32 nms)
{u32 temp;SysTick->LOAD = nms * fac_ms;SysTick->VAL = 0x00;SysTick->CTRL = 0x01;do{temp = SysTick->CTRL;} while ((temp & 0x01) && !(temp & (1 << 16)));SysTick->CTRL = 0x00;SysTick->VAL = 0X00;
}
​

1.6 实验思考和拓展

1.6.1 如何调整LED灯的闪烁频率?

LED灯闪烁的频率,归根结底还是由灯光的亮和灭时间间隔决定的,亮和灭的时间间隔越小,那么频率就越高

实现方法:

  1. 使用定时器实现精确延时

    若使用自定义简单延时函数(如void Delay_ms(uint32_t ms)),直接调整传入的延时参数。 :原闪烁周期为 0.6 秒(亮 0.3 秒 + 灭 0.3 秒),若改为亮 0.1 秒 + 灭 0.1 秒,则周期变为 0.2 秒,频率提高 3 倍。

    // 原代码(周期0.6秒)
    LED0_ON();  // 亮
    Delay_ms(300);
    LED0_OFF(); // 灭
    Delay_ms(300);
    ​
    // 调整后(周期0.2秒)
    LED0_ON();
    Delay_ms(100);
    Delay_ms(100);
  2. 使用定时器实现精确延时

    简单延时函数依赖系统时钟和循环次数,可通过计算循环次数与时钟周期的关系提高精度。 :若系统时钟为 72MHz,一个循环约耗时 1 微秒,则延时 1 毫秒需循环 1000 次。

  3. 使用定时器实现精确延时:

    利用 STM32 的定时器(如 TIM2、TIM3)产生精确中断,通过中断计数实现延时,避免 CPU 空转,提升系统效率。 步骤: ① 初始化定时器,配置为定时中断模式(如定时 1 毫秒); ② 在中断服务函数中维护一个全局计数器; ③ 主函数中通过判断计数器值实现延时。

1.6.2 如何实现呼吸灯效果?

方法:软件模拟渐变效果

1.6.2.1 非 PWM 实现呼吸灯的原理

呼吸灯的本质是让人眼感知到 LED 亮度的线性渐变(从暗到亮或从亮到暗)。人眼对亮度的感知具有惰性,当 LED 在极短时间内(如几毫秒)频繁亮灭时,会将亮灭时间的平均值视为 “亮度”。因此,即使不使用硬件 PWM,也可以通过软件控制 LED 的亮灭占空比(即导通时间与周期的比例),逐步改变占空比来模拟亮度变化。

1.6.2.2 具体实现方法(以 STM32 为例)

LED 为共阳极接法(低电平点亮),通过以下步骤实现亮度渐变:

1. 亮度等级划分

将亮度从 0%(全灭)到 100%(最亮)划分为若干等级(如 256 级),用一个变量(如brightness)表示当前等级(范围:0~255)。

  • brightness=0:LED 全灭(高电平)。

  • brightness=255:LED 全亮(低电平)。

2. 控制亮灭时间比例

每个亮度等级对应一个周期总时间(如 10ms),其中:

  • 点亮时间 = (brightness / 255) × 周期总时间

  • 熄灭时间 = 周期总时间 - 点亮时间

通过循环改变brightness的值(如从 0 逐渐增加到 255,再逐渐减小到 0),并在每个等级中控制 LED 的亮灭时间,即可实现渐变效果。

1.6.2.3 代码实例:
// 定义LED引脚(共阳极,低电平点亮)
#define LED_GPIO_PORT GPIOB
#define LED_PIN GPIO_Pin_5
​
// 亮度等级(0~255)
uint8_t brightness = 0;
uint8_t direction = 1; // 1表示亮度增加,-1表示亮度减少
​
void breathe_led(void) {// 亮度渐变方向控制(到达边界时反转方向)if (brightness == 255) direction = -1;if (brightness == 0) direction = 1;brightness += direction;
​// 计算亮灭时间(周期总时间设为10ms,可调整)uint16_t on_time = (brightness * 10) / 255; // 点亮时间(ms)uint16_t off_time = 10 - on_time; // 熄灭时间(ms)
​// 控制LED点亮GPIO_ResetBits(LED_GPIO_PORT, LED_PIN); // 低电平点亮delay_ms(on_time); // 点亮持续时间
​// 控制LED熄灭GPIO_SetBits(LED_GPIO_PORT, LED_PIN); // 高电平熄灭delay_ms(off_time); // 熄灭持续时间
}
​
// 主循环中调用
while (1) {breathe_led();
}

与 PWM 方案的对比

特性非 PWM 软件模拟硬件 PWM
实现复杂度需编写循环逻辑和延时函数,代码较繁琐直接配置定时器 PWM 模式,代码简洁
CPU 占用率高(需实时控制亮灭时间,阻塞延时)低(定时器硬件自动更新占空比)
亮度平滑度受延时精度限制,可能有闪烁感平滑(硬件驱动,频率稳定)
适用场景简单实验、对实时性要求低的场合高要求场景(如电机调速、精密调光)

1.6.3 除了使用简单延时外,STM32还有哪些更加精准的延时方式?
  1. 定时器延时(精确且不阻塞 CPU)

    原理:利用定时器的计数功能,通过配置自动重装载值(TIMx_ARR)和预分频器(TIMx_PSC)设定定时时间,结合中断或查询方式实现延时。

    优点:精度高(可达微秒级),延时期间 CPU 可执行其他任务。

  2. SysTick 定时器延时(系统级延时)

    原理:利用 STM32 内部的 SysTick 定时器(系统滴答定时器),基于系统时钟(如 72MHz)产生精确中断。

    优点:无需额外外设,由 Cortex-M 内核直接支持,适合系统级延时。

  3. 实时操作系统(RTOS)任务调度

    原理:在 RTOS(如 FreeRTOS、uCOS)中,通过任务调度函数(如vTaskDelay())实现延时,本质是释放 CPU 资源给其他任务。

    优点:多任务并行处理,延时期间可执行其他任务,适合复杂系统。

  4. 总结与拓展

    1. 简单场景:优先使用 SysTick 或定时器查询方式,兼顾精度与代码复杂度。

    2. 复杂场景:引入 RTOS 或定时器中断,实现多任务协同和精确时序控制。

    3. 进阶实践:结合 DMA(直接内存访问)与定时器,实现无 CPU 参与的自动 PWM 输出,进一步提升效率。

1.7 注意事项

(1) 使用标准库函数时,需要注意头文件的包含和依赖关系。

(2) 共阳极LED的控制逻辑:低电平点亮,高电平熄灭。

(3) 简单延时函数的精确度受系统时钟和编译优化的影响。

(4) GPIO操作前必须先使能对应的外设时钟。

文章有写的不当的地方,欢迎在评论区中指正修改。如果感觉文章实用对你有帮助,欢迎点赞收藏和关注,你的点赞关注就是我动力,大家一起学习进步。

有不懂的可以在评论区里提出来哟,博主看见后会及时回答的。

相关文章:

  • Java代码重构:如何提升项目的可维护性和扩展性?
  • Android之ListView
  • 第十二节:第三部分:集合框架:List系列集合:特点、方法、遍历方式、ArrayList集合的底层原理
  • TK海外抢单源码/指定卡单
  • 车载诊断架构SOVD --- 车辆发现与建连
  • STM32 HAL库函数学习 CRC篇
  • DeepSeek 赋能金融反洗钱:AI 驱动的风险监测革新之路
  • Reactor 和 Preactor
  • Python训练营---Day41
  • [yolov11改进系列]基于yolov11引入重参数化模块DiverseBranchBlock的python源码+训练源码
  • [python]Prophet‘ object has no attribute ‘stan_backend‘解决方法
  • 前端学习(7)—— HTML + CSS实现博客系统页面
  • vue-08(使用slot进行灵活的组件渲染)
  • 数组题解——最大子数组和​【LeetCode】
  • 流媒体基础解析:音视频封装格式与传输协议
  • 新版智慧景区信息化系统解决方案
  • leetcode216.组合总和III:回溯算法中多条件约束下的状态管理
  • SCSS 全面深度解析
  • C56-亲自实现字符串拷贝函数
  • [学习] RTKlib 实用工具介绍
  • wordpress 上传主题/seo搜索规则
  • 北京网站建设有哪些/好用搜索引擎排名
  • wordpress 商业网站/seo建站是什么
  • 做微信平台图片网站/百度竞价排名平台
  • 荆州北京网站建设/深圳网络推广引流
  • 像网站的ppt怎么做的/成人本科