STM32——GPIO输出(点亮第一个LED灯)

news2024/11/20 0:48:04

代码示例:

#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函数对GPIO口进行初始化:

  • 在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灯的亮灭。

结构体参数的赋值步骤:

2.GPIO_Init函数第二个参数是一个结构体,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_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,...)

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

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

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

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

相关文章

【JAVA基础之Stream流】掌握Stream流

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 目录 1.Stream流 1.1 概述 2.2 常见方法 2.2.1 实现步骤 2.2.2 获取Stream的方式 2.2.3 中间方法 2.2.4 终结方法 1.Stream流 1.1 概述 Stream流可以让你通过链…

Spring AOP(2)

目录 Spring AOP详解 PointCut 切面优先级Order 切点表达式 execution表达式 切点表达式示例 annotation 自定义注解MyAspect 切面类 添加自定义注解 Spring AOP详解 PointCut 上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重…

Cmake编译源代码生成库文件以及使用

在项目实战中&#xff0c;通过模块化设计能够使整个工程更加简洁明了。简单的示例如下&#xff1a; 1、项目结构 project_folder/├── CMakeLists.txt├── src/│ ├── my_library.cpp│ └── my_library.h└── app/└── main.cpp2、CMakeList文件 # CMake …

[机器学习系列]深入探索回归决策树:从参数选择到模型可视化

目录 一、回归决策树的参数 二、准备数据 三、构建回归决策树 (一)拟合模型 (二)预测数据 (三)查看特征重要性 (四)查看模型拟合效果 (五) 可视化回归决策树真实值和预测值 (六)可视化决策树并保存 部分结果如下&#xff1a; 一、回归决策树的参数 DecisionTreeRegress…

基于springboot+mybatis+vue的项目实战之增删改查CRUD

目录结构 PeotController.java package com.example.controller;import com.example.pojo.Peot; import com.example.pojo.Result; import com.example.service.PeotService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web…

分布式锁讲解

概括 分布式锁是一种用于在分布式系统中实现同步机制的锁。在单机系统中&#xff0c;我们可以使用如Java中的synchronized关键字或者 ReentrantLock来实现线程间的同步&#xff0c;但在分布式系统中&#xff0c;由于多个节点&#xff08;服务器&#xff09;之间的并发操作&am…

谷歌CEO最新访谈:AI浪潮仍处于早期阶段,公司未来最大威胁是执行力不足

作为搜索领域无可争议的霸主&#xff0c;谷歌改变了我们生活的方方面面&#xff0c;从日常琐事到工作事务&#xff0c;再到我们的沟通方式。多年来&#xff0c;谷歌一直是互联网的窗口&#xff0c;为我们提供大量知识和信息&#xff0c;但如今&#xff0c;随着其他类似平台的崛…

融知财经:期货交易的规则和操作方法

期货交易是指在未来的某一特定时期&#xff0c;买卖双方通过签订合约的方式&#xff0c;约定以某种价格买卖一定数量的某种商品或资产的行为。期货交易的规则和操作方法如下&#xff1a; 期货交易的规则和操作方法 1、双向交易&#xff1a; 期货市场允许投资者进行多头&#xf…

Chrono下载管理器:提升下载体验,有效管理文件

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、介绍二、下载安装1、Chrome应用商店&#xff08;需科学&#xff09;2、第三方直链下载 三、使…

【密码守护者】让弱密码无处遁形,保护你的UOS系统安全!

欢迎点赞、关注、分享&#xff0c;后期将会有更多的工作小工具分享给大家&#xff0c;嘻嘻 密码&#xff0c;是守护我们数字世界的钥匙。一个强大、复杂的密码&#xff0c;能够有效地抵御黑客攻击和信息泄露的风险。但在日常使用中&#xff0c;许多人因为方便记忆而选择了简单易…

【Linux】yum与vim

文章目录 软件包管理器&#xff1a;yumLinux安装和卸载软件包Linux中的编辑器&#xff1a;vimvim下的底行模式vim下的正常模式vim下的替换模式vim下的视图模式vim下的多线程 软件包管理器&#xff1a;yum yum其实就是一个软件,也可以叫商店 和你手机上的应用商店或app store一…

Meta-SR: A Magnification-Arbitrary Network for Super-Resolution

CVPR2019https://github.com/XuecaiHu/Meta-SR-Pytorch 问题引入 首个解决任意尺度超分问题的模型&#xff0c;借鉴了meta-learning的思想&#xff1b;weight prediction strategy(meta-learning)&#xff1a;神经网络的权重是由另一个神经网络预测的&#xff0c;而不是通过从…

【16-Ⅱ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

【win10 文件夹数量和看到不一致查看隐藏文件已经打开,Thumb文件作妖】

目录 任务介绍&#xff1a;重命名规则修改前修改后 实现思路VB代码实现BUG犯罪现场&#xff08;眼见不一定为实&#xff09;破案1&#xff1a;抓顶风作案的反贼&#xff01;&#xff01;&#xff01;破案2&#xff1a;破隐身抓刺客&#xff01;&#xff01;&#xff01;杀器&am…

JavaWeb之Servlet(上)

前言 1. 什么是Servlet (1) Servlet介绍 (2) Servlet运行于支持Java的应用服务器中。 (3) Servlet工作模式&#xff1a; 2. Servlet API 3. 第一个Servlet (1) 创建一个类实现Servlet接口,重写方法。或继承HttpServlet亦可 (2) 在web.xml文档中配置映射关系 标签的执行…

书生浦语训练营第2期-第7节作业

一、基础作业 二、进阶作业

作为餐饮行业HR,怎么选择一套合适的HCM人事管理系统?

在餐饮业这个行业中&#xff0c;人员流动性较高&#xff0c;特别是对于服务员和厨师这类基层员工&#xff0c;招聘一直是一个难题。根据艾瑞数据测算&#xff0c;到2024年&#xff0c;中国餐饮行业的年收入将超过6万亿元&#xff0c;年复合增长率高达8.8%。作为餐饮企业的品牌战…

Vue从入门到实战Day03

一、生命周期 1. 生命周期四个阶段 思考&#xff1a; ①什么时候可以发送初始化渲染请求&#xff1f; 答&#xff1a;越早越好&#xff0c;在创建阶段后 ②什么时候可以开始操作DOM&#xff1f; 答&#xff1a;至少DOM得渲染出来&#xff0c;在挂载阶段结束后。 Vue生命周…

【用文本生成歌声】Learn2Sing 2.0——歌声转换算法即梅尔频谱详解

一. 频谱图与梅尔谱图的介绍 频谱图&#xff1a;频谱图可以理解为一堆垂直堆叠在一起的快速傅里叶变换结果。 1.1 信号 在进入频谱图模块之前&#xff0c;首先我们需要了解信号是什么。 信号就是某一特定量随时间变化&#xff0c;对于音频来说&#xff0c;这个特定的变化量就…

Django之创建Model以及后台管理

一&#xff0c;创建项目App python manage.py startapp App 二&#xff0c;在App.models.py中创建类&#xff0c;以下是示例 class UserModel(models.Model):uid models.AutoField(primary_keyTrue, auto_createdTrue)name models.CharField(max_length10, uniqueTrue, db…