STM32——点亮第一个LED灯

news2024/11/25 12:30:54

代码示例:

#include "stm32f10x.h"                  // Device header

int main()
{
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启时钟
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
	while(1)
	{
		
	}
}   

使用的外设:

在要用STM32单片机实现某一个功能之前我们需要除了完成基础步骤之外,要知道需要用的什么外设,然后查看该外设都有哪些库函数,这是在采用库函数的开发模式下。

一.RCC:
在STM32单片机中,RCC(Reset and Clock Control)即复位和时钟控制器,是一个非常重要的模块,负责单片机的复位以及时钟的配置。
RCC模块的主要作用包括:
1.复位控制: STM32F10xxx系列支持多种复位形式,如系统复位、电源复位和备份区域复位。这些复位操作可以通过NRST引脚上的低电平(外部复位)、窗口看门狗计数终止(WWDG复位)、独立看门狗计数终止(IWDG复位)、软件复位(SW复位)或低功耗管理复位等方式触发。系统复位将复位除时钟控制器的RCC_CSR寄存器中的复位标志位和备份区域中的寄存器以外的所有寄存器至其复位状态。
2.时钟配置: 2.时钟配置:RCC模块提供了对时钟源的配置、时钟分频、复位控制等功能。它可以配置主时钟源、系统时钟、AHB总线时钟和APB总线时钟等。通过RCC模块,可以将各种时钟源分配给不同的系统和外设,以满足它们对时钟频率和精度的需求。
3.外设时钟使能:在使用外设模块之前,需要启用相应的外设时钟。RCC模块提供了一系列函数。
如:
RCC_APB2PeriphClockCmd RCC_APB1PeriphClockCmd ,用于启用或禁用外设时钟。这些函数可以确保在需要时向特定外设提供时钟信号,从而使其能够正常工作。
总的来说:RCC模块在STM32单片机中起着至关重要的作用,它负责整个系统的复位和时钟管理,确保系统能够稳定、可靠地运行。

第一步:使用RCC开启GPIO的时钟

首先:
可以在Library中找到rcc.h文件,该文件里面有它能够使用的所有库函数,而我们常用的一般就三个:
1.RCC AHB外设时钟控制
2.RCC APB2外设时钟控制
3.RCC APB1外设时钟控制

在这里插入图片描述

  • 右键可以打开该函数:
    注释部分讲述了该函数的功能。同时里面包含的外设就是你能够通过RCC进行使能的

    在这里插入图片描述

时钟的作用:

  • STM32的时钟系统对于整个微控制器的工作至关重要。时钟系统为STM32提供统一的节拍,就像人的心跳一样,驱动着微控制器内部各个部分按照预定的时序执行相应的指令。具体来说,时钟系统的作用主要体现在以下几个方面:

1. 同步工作:时钟信号为STM32的各个电路模块提供了一个统一的时间基准,使得它们能够按照预定的时序进行工作。例如,CPU核心在时钟的驱动下完成指令执行和状态变换,外设部件(如GPIO端口)在时钟的驱动下完成数据的发送和接收等操作。

2. 控制速度:时钟信号的频率决定了STM32的工作速度。通过调整时钟信号的频率,可以控制STM32的执行效率和功耗。在需要高性能的场景下,可以提高时钟频率以加快执行速度;在需要低功耗的场景下,可以降低时钟频率以降低功耗。

3. 省电设计:STM32的时钟系统采用了时钟门控技术,可以根据需要开启或关闭某个电路模块的时钟。当某个电路模块不需要工作时,关闭其时钟可以节省功耗。这种设计使得STM32在保持高性能的同时,也具有良好的节能性能。

  • 在STM32中,GPIO(通用输入/输出)端口是连接外部设备和微控制器的桥梁。要想使用GPIO端口进行数据的输入和输出,必须先通过RCC(Reset and Clock Control,复位与时钟控制)模块开启其时钟。这是因为GPIO端口的寄存器是由D触发器构成的,而触发器需要时钟信号才能改写其值。只有开启了GPIO的时钟,微控制器才能通过操作寄存器来控制GPIO端口的输入输出状态。因此,在使用GPIO之前,第一步就是使用RCC开启其时钟。

调用RCC的APB2外设时钟控制函数:

  • 本次点灯用的是PA0口,所以对GPIOA的时钟进行使能,打开APB2外设时钟控制函数,在注释里能够看到支持的外设,选择GPIOA放到第一个参数,第二个参数就是使能ENABLE。
    在这里插入图片描述
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

第二步:使用GPIO_Init函数初始化GPIO

首先:
打开GPIO的.H头文件,就可以看到GPIO_Init函数,这个函数用结构体参数来初始化GPIO口,函数会读取结构体成员然后把外设的参数配置好,这种Init函数在所有外设函数中基本都有。

GPIO_Init函数的作用:

  • 在STM32中,使用GPIO_Init函数初始化GPIO是点亮LED灯的关键步骤,原因主要有以下几点:

1.配置GPIO引脚属性:GPIO_Init函数用于配置GPIO引脚的各种属性,如输出模式、上拉/下拉电阻、引脚速度等。对于LED灯来说,通常需要将GPIO引脚配置为输出模式,以便能够控制LED灯的亮灭。

2.确保通信正常:通过GPIO_Init函数的正确配置,可以确保STM32微控制器与LED灯之间的通信正常进行。这包括设置正确的引脚速度、避免冲突和干扰等。

3.简化编程:STM32的HAL(硬件抽象层)库中包含了GPIO_Init函数,使得开发者可以更方便地配置GPIO引脚。通过直接使用这个函数,可以避免直接操作寄存器,从而简化编程过程。

4.适应不同需求:GPIO_Init函数允许开发者根据具体需求配置GPIO引脚。例如,对于不同的LED灯或不同的应用场景,可能需要设置不同的引脚速度或上拉/下拉电阻。通过GPIO_Init函数,可以轻松实现这些配置。

因此,在使用STM32点亮LED灯时,需要使用GPIO_Init函数来初始化GPIO引脚,以确保LED灯能够正常工作。同时,还需要注意在程序中正确设置GPIO引脚的状态(高电平或低电平),以控制LED灯的亮灭。

调用GPIO_Init函数:

//这样就创建了一个GPIO_InitTypeDef类型的变量,GPIO_InitTypeDef是一个已经定义好的结构体。GPIO_InitStructure则是一个用GPIO_InitTypeDe定义的结构体变量。
GPIO_InitTypeDef GPIO_InitStructure;
//接下来对该结构体变量的内部成员进行赋值,然后传给GPIO_Init函数,该函数会读取这些成员变量的值,然后对外设进行配置。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//记得这里传的是该结构体变量的地址
GPIO_Init(GPIOA,&GPIO_InitStructure);

当这段代码执行完,这个GPIOA就自动化被配置为推挽输出、50Mhz的速度了。
1.第一个参数是GPIOA,注释中有写该函数的参数和返回值。

GPIO_Init(GPIOA,...)

结构体参数的赋值步骤:

2.第二个参数是一个结构体,GPIO_InitTypeDef是一个结构体类型,它是这个结构体的名字,将它赋值下来一会在主函数中创建一个该结构体的变量,然后给这个结构体的变量的成员赋值,再将这个结构体变量的地址作为参数传给GPIO_Init函数。

//这样就创建了一个GPIO_InitTypeDef类型的变量,GPIO_InitTypeDef是一个已经定义好的结构体。GPIO_InitStructure则是一个用GPIO_InitTypeDe定义的结构体变量。
GPIO_InitTypeDef GPIO_InitStructure;

第一步:

  • 创建好一个结构体变量,然后通过点操作符先选择一个成员,右键选择去到该成员的定义处,不要画蓝选中,直接鼠标指到该变量右键就好。我们先看GPIO_Mode,配置好GPIO的工作模式。
GPIO_InitStructure.GPIO_Mode

在这里插入图片描述
第二步:
跳转之后如下图,注意旁边的注释。
在这里插入图片描述
*1.注释 /*!< … / 是一种特殊的多行注释,在Doxygen(一个流行的文档生成工具)中用于生成文档。它通常用于为代码添加额外的描述信息,这些信息可以被Doxygen等工具提取并转换为人类可读的文档。

2.@ref GPIOMode_TypeDef 是一个Doxygen标记,用于创建一个到GPIOMode_TypeDef定义的引用。这意味着,当你查看生成的文档时,你可以通过这个引用直接跳转到GPIOMode_TypeDef的定义部分。

第三步:

  • 那么选中注释中的GPIOMode_TyepeDef,然后CTRL + F可以查找到关于GPIO八种工作模式的选择。
    在这里插入图片描述
  • 跳转到该处就能看到一个枚举类型GPIOMode_TyepeDef,可以看到其中的枚举常量(枚举成员)指定的整数值就是不同的输入输出模式。我们点灯用的是推挽输出,所以赋值Out_PP这一项。这个Out_PP是一个枚举常量,而GPIO_Mode是一个枚举类型GPIOMode_TypeDef的变量。**
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

在这里插入图片描述

其他的GPIO_Pin和GPIO_Speed也是同样的步骤

枚举类型:

  • 枚举类型(Enumeration Type)是一种用户定义的数据类型,允许你为整数值指定一组具名的标识符(也称为枚举成员或枚举常量)。在编程中,枚举类型用于表示固定数量的常量值,这些常量值通常与某种上下文或数据类型相关联。

代码块(1):

typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
  • 代码(1)中展示的就是一个枚举类型,其中花括号{}内部的称为枚举成员,花括号结尾的GPIOMode_TypeDef是这个枚举类型的名字。

代码块(2):

typedef struct
{
  uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                      This parameter can be any value of @ref GPIO_pins_define */

  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */

  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                      This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
  • 在上面这块代码中一共用GPIOSpeed_TypeDef定义了两个枚举变量,分别是GPIO_Speed和GPIO_Mode,于是我们就能够用枚举常量(枚举成员)给这两个变量进行赋值。

注意:

  • 在C语言中,如果枚举成员没有显式地指定整数值,那么它们的值将从0开始递增。在这个例子中,MONDAY 的值为0,TUESDAY 的值为1,依此类推。但是,你也可以显式地为枚举成员指定整数值,就像代码块(2)中已经为每个输出模式的名字指定了整数值。

第三步:使用输出或者输入函数控制GPIO口

在这里插入图片描述
图上是所有GPIO输入或者输出函数,可以直接右键跳转到定义处,根据注释自己使用。
在这里插入图片描述
注释在函数定义的上面,包含简介、参数、返回值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1639813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

头歌实践教学平台:投影变换v2.0

第2关&#xff1a;两点透视 一. 任务描述 1. 本关任务 (1) 理解透视投影变换的方法; (2) 将main函数中的空白部分补充完整。 2. 输入 (1) 代码将自动输入一个边长为1的obj正方体模型&#xff0c;具体模型如下图&#xff1a; (2) 代码自动将模型投影到二维平面中心生成一个…

【MySQL | 第十篇】重新认识MySQL索引匹配过程

文章目录 10.重新认识MySQL索引匹配过程10.1匹配规则10.2举例&#xff1a;联合索引遇到范围查询&#xff08;>、<、between、like&#xff09;10.2.1例子一&#xff1a;>10.2.2例子二&#xff1a;>10.2.3例子三&#xff1a;between10.2.4例子四&#xff1a;like 10…

每日OJ题_DFS爆搜深搜回溯剪枝⑧_力扣980. 不同路径 III

目录 力扣980. 不同路径 III 解析代码 力扣980. 不同路径 III 980. 不同路径 III 难度 困难 在二维网格 grid 上&#xff0c;有 4 种类型的方格&#xff1a; 1 表示起始方格。且只有一个起始方格。2 表示结束方格&#xff0c;且只有一个结束方格。0 表示我们可以走过的空…

eclipse开启服务后,网页无法打开,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

java发送请求2次开发-get请求json

因为你请求参数不为空&#xff0c;接口都会把这个参数带上 所以借鉴HttpPost类 继承这个类&#xff0c; 这个类是可以带消息的 httpgetwithentity&#xff0c;httpget请求带上消息 复写 构造方法复制过来进行使用 二次开发类让其get请求时可以发送json

U-boot 编译

引入 在嵌入式系统开发中&#xff0c;U-Boot 作为一个开源的引导加载程序&#xff08;bootloader&#xff09;&#xff0c;扮演着至关重要的角色。它负责在系统启动时初始化硬件&#xff0c;加载并启动操作系统。本文将详细介绍如何从 U-Boot 的源码开始&#xff0c;编译生成适…

【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序

本文设计知识点 树 图论 阶乘 组合 深度优先搜索 图论知识汇总 LeetCoce1916. 统计为蚁群构筑房间的不同顺序 你是一只蚂蚁&#xff0c;负责为蚁群构筑 n 间编号从 0 到 n-1 的新房间。给你一个 下标从 0 开始 且长度为 n 的整数数组 prevRoom 作为扩建计划。其中&#xff0…

聊聊持续测试

这是鼎叔的第九十六篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 本人新书《无测试组织-测试团队的敏捷转型》已出版&#xff08;机械工业出版社&#xff09;。 如果在测试部门只能推行一个技术建设项目&#xff0c;那鼎叔就会选择“持续测试”。 持续测…

【论文阅读笔记】Frequency Perception Network for Camouflaged Object Detection

1.论文介绍 Frequency Perception Network for Camouflaged Object Detection 基于频率感知网络的视频目标检测 2023年 ACM MM Paper Code 2.摘要 隐蔽目标检测&#xff08;COD&#xff09;的目的是准确地检测隐藏在周围环境中的目标。然而&#xff0c;现有的COD方法主要定位…

UI-Diffuser——使用生成式扩散模型的UI原型设计算法解析

概述。 移动UI是影响参与度的一个重要因素&#xff0c;例如用户对应用的熟悉程度和使用的便利性。如果你有一个类似的应用程序&#xff0c;你可能会选择一个具有现代、好看的设计的应用程序&#xff0c;而不是一个旧的设计。然而&#xff0c;要从头开始研究什么样的UI最适合应…

数据的表示和运算试题

01&#xff0e;若十进制数为137.5&#xff0c;则其八进制数为(). A.89.8 B.211.4 C.211.5 D.1011111.101 02.一个16位无符号二进制数的表示范围是()。 A. 0&#xff5e;65536 B.0~65535 c. -32768~32767 D.-32768~32768 03.下列说法有误的是( ). A.任何二进制整数都可以用十进…

若依框架详细使用教程

目录 若依简介 若依使用 搭建后端 搭建前端 若依的使用 若依简介 RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|开源后台系统|RuoYi|RuoYi-Vue|RuoYi-Cloud|RuoYi框架|RuoYi开源|RuoYi视频|若依视频|Ruo…

golang判断通道chan是否关闭的2种方式

chan通道在go语言的办法编程中使用频繁&#xff0c;我们可以通过以下2种方式来判断channel通道是否已经关闭&#xff0c;1是使用 for range循环&#xff0c;另外是通过 for循环中if 简短语句的 逗号 ok 模式来判断。 示例代码如下&#xff1a; //方式1 通过for range形式判断…

ZooKeeper知识点总结及分布式锁实现

最初接触ZooKeeper是之前的一个公司的微服务项目中&#xff0c;涉及到Dubbo和ZooKeeper&#xff0c;ZooKeeper作为微服务的注册和配置中心。好了&#xff0c;开始介绍ZooKeeper了。 目录 1.ZooKeeper的基本概念 2.ZooKeeper的节点&#xff08;ZNode&#xff09; 3. ZooKeep…

基于MSOGI的交叉对消谐波信号提取网络MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介&#xff1a; 此模型利用二阶广义积分器&#xff08;SOGI&#xff09;对基波电流和相应次的谐波电流进行取 &#xff0c;具体是通过多个基于二阶广义积分器的正交信号发生器 &#xff08; S&#xf…

基于Vue Router和element-ui的LayOut

一、展示 二、代码 app.vue <template><div id"app"><el-container style"border: 1px solid #eee; height: 100vh"><el-aside v-bind:width"asideWidth" style"background-color: rgb(48, 65, 86);"><…

【数据结构】这样学习串的朴素模式匹配算法,简直不要太容易……

串的朴素模式匹配算法 导读一、串的模式匹配1.1 模式匹配是什么&#xff1f;1.2 为什么要有模式匹配算法&#xff1f; 二、朴素模式匹配算法2.1 算法底层逻辑2.2 算法实现2.2.1 过程解析2.2.2 思路分析2.2.3 思路总结2.2.4 代码编写数据类型函数的三要素函数主体 2.2.5 代码测试…

【Linux 系统】多线程(线程控制、线程互斥与同步、互斥量与条件变量)-- 详解

一、线程概念 线程是进程的一个执行分支&#xff0c;是在进程内部运行的一个执行流。下面将从是什么、为什么、怎么办三个角度来解释线程。 1、什么是线程 上面是一张用户级页表&#xff0c;我们都知道可执行程序在磁盘中无非就是代码或数据&#xff0c;更准确点表述&#xff0…

python从0开始学习

目录 前言 1、print函数 2、input函数 3、保留字和标识符 总结 前言 本篇文章我们开辟一个新的学习模块&#xff1a;python。python是一个十分简洁实用的编程语言&#xff0c;我们将从0开始学习python 1、print函数 print(*args, sep , end\n, fileNone, flushFalse) pytho…

高手的黑箱:AI时代学习、思考与创作

课程目录 01 不要错过这个时代的巨大红利&#xff0c;AI时代竞争力养成指南.mp4 02 解密高手的黑箱——那些创作高手不告诉你的事.mp4 03 创作&#xff1a;人生发展中最重要的事.mp4 04 创作中最重要的事&#xff08;1&#xff09;&#xff1a;对过程的掌控力.mp4 05 创作…