STM32——点亮第一个LED灯

代码示例:

#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输入或者输出函数,可以直接右键跳转到定义处,根据注释自己使用。
在这里插入图片描述
注释在函数定义的上面,包含简介、参数、返回值。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AWS 机器学习课程--1.机器学习的介绍

课程链接&#xff1a;机器学习&#xff08;ML&#xff09;和人工智能&#xff08;AI&#xff09;— AWS 数字和课堂培训 免费课程&#xff0c;注册结束之后&#xff0c;就可以选择课程了。 共计6个课程&#xff0c;推荐学习时长为8小时13分钟 本章建议学习时间为30min&#…

C++奇迹之旅:C++内存管理的机制(进阶篇)

文章目录 &#x1f4dd;new和delete操作自定义类型&#x1f320; operator new与operator delete函数&#x1f309;operator new与operator delete函数 &#x1f320;new和delete的实现原理&#x1f309;内置类型&#x1f309;自定义类型 &#x1f320;定位new表达式(placement…

Flutter笔记:使用Flutter私有类涉及的授权协议问题

Flutter笔记 使用Flutter私有类涉及的授权协议问题 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.cs…

202012青少年软件编程(Python)等级考试试卷(一级)

第 1 题 【单选题】 运行下方代码段&#xff0c;输出是6&#xff0c;则输入的可能是&#xff08; &#xff09;。 a eval(input())print(a)A :8%2 B :8/2 C :3*2 D :3**2 正确答案:C 试题解析: 第 2 题 【单选题】 关于Python变量&#xff0c;下列叙述正确的是&#x…

中仕公考:北京额度管理(社会化/员额制)教师和在编教师的区别

一、什么是额度管理(社会化/员额制)教师? 社会化、员额制教师、额度管理教师&#xff0c;是为了解决中小学教师总量或编制不足&#xff0c;在现有编制基础上另外核定一定数额由地方政府保障&#xff0c;不纳入编制管理&#xff0c;另外实行专项管理。不办理入编手续&#xff…

自定义表单元素组件内容变化触发ElForm重新校验

对于下图中“付费类型”怎么实现有很多种方式&#xff0c;我能想到的是以下两种&#xff1a; Element Plus的RadioButton自定义组件 1. RadioButton 它本质上就是一个单选组件&#xff0c;它跟Element Plus的RadioButton本质上没有区别&#xff0c;无非是外观上的差别。那么…

Windows计算机安装并连接Linux系统(VMware、XShell)

一、Windows计算机可以通过VMware虚拟机&#xff0c;安装Linux系统 说明&#xff1a;VMware Workstation虚拟化软件&#xff0c;在Windows或Linux计算机运行的应用程序&#xff0c;可模拟基于X86的标准PC环境&#xff0c;构建的虚拟机和真实的物理主机没太大区别&#xff08;区…

自学Vue3 Day2

一、组合式Api组件通信 1.父与子之间 父传子&#xff1a;父导入子组件&#xff0c;定义好数据&#xff0c;子组件用props接收&#xff0c;这里defineProps底层本质还是props. 注意模板渲染过程不需要写props 子传 父&#xff1a; 2.模版引用&#xff08;ref&#xff09;和组…

MySQL:设置唯一索引还是出现重复数据

一、MySQL中null和null不相等 MySQL中&#xff1a;两个值比较会出现&#xff1a;true、false、null 三种情况&#xff1b; null和null相比较会出现未知的类型 二、然后看完这个视频 美团二面&#xff1a;我记得明明加了mysql唯一索引&#xff0c;为啥还会出现重复数据吗&…

PHP的数组练习实验

实 验 目 的 掌握索引和关联数组&#xff0c;以及下标和元素概念&#xff1b; 掌握数组创建、初始化&#xff0c;以及元素添加、删除、修改操作&#xff1b; 掌握foreach作用、语法、执行过程和使用&#xff1b; 能应用数组输出表格和数据。 任务1&#xff1a;使用一维索引数…

GPT是什么?直观解释Transformer | 深度学习第5章 【3Blue1Brown 官方双语】

【官方双语】GPT是什么&#xff1f;直观解释Transformer | 深度学习第5章 0:00 - 预测&#xff0c;采样&#xff0c;重复&#xff1a;预训练/生成式/Transformer模型 3:03 - Transformer 的内部结构 6:36 - 本期总述 7:20 - 深度学习的大框架 12:27 - GPT的第一层&#xff1a;…

(一)JSP教程——JSP脚本标签

JSP脚本标签 JSP脚本标签通常用作对象操作和数据运算&#xff0c;从而动态地生成页面内容。这里有三种类型的脚本标签&#xff1a;声明、代码段和表达式。 JSP声明 JSP声明一个或多个变量、方法&#xff0c;供以后的代码使用。必须先对变量和方法进行声明&#xff0c;才能使用…

golang学习笔记(内存逃逸分析)

golang的内存逃逸 逃逸分析&#xff08; Escape analysis&#xff09; 是指由编译器决定内存分配的位置&#xff0c; 不需要程序员指定。 函数中申请一个新的对象。 如果分配在栈中&#xff0c; 则函数执行结束可自动将内存回收&#xff1b;如果分配在堆中&#xff0c; 则函数…

微软开源 MS-DOS「GitHub 热点速览」

上周又是被「大模型」霸榜的一周&#xff0c;各种 AI、LLM、ChatGPT、Sora、RAG 的开源项目在 GitHub 上“争相斗艳”。这不 Meta 刚开源 Llama 3 没几天&#xff0c;苹果紧跟着就开源了手机端大模型&#xff1a;CoreNet。 GitHub 地址&#xff1a;github.com/apple/corenet 开…

网络安全前置知识-linux操作系统

计算机体系结构 计算机发展历史 计算机组成 计算机硬件组成 1. CPU 原文链接&#xff1a;https://blog.csdn.net/stone_fall/article/details/88414017 一条指令的执行过程分为以下5个周期&#xff1a; 取指令周期&#xff08;Instruction Fetch&#xff0c;IF&#xff…

【Cpp】类和对象

标题&#xff1a;【Cpp】类和对象 水墨不写bug 正文开始&#xff1a; &#xff08;一&#xff09;面向过程与面向对象 面向过程和面向对象是两种不同的编程思想。 面向过程指的是将程序分解成多个步骤&#xff0c;每个步骤都是一个独立的函数&#xff0c;通过函数之间的调用实…

使用OneAPI创建LLM访问API Key

OneAPI 是一个能替代 springdoc-openapi/Swagger 的 API 生产工具&#xff0c;既不需要修改后端代码&#xff0c;也不需要启动应用。 也支持导出 OpenAPI 3.0 协议数据&#xff0c;方便在其他工具中消费。 前面我们介绍了LobeChat需要配置LLM的API访问Key&#xff0c;今天你可…

《架构即未来》读后感

目录 一、引言 二、《架构即未来》读后感 1、主题的简要介绍 2、我的看法和理解 3、作者的优点和传递的信息 4、思想如何适用于当今社会 三、《架构即未来》对于企业发展的影响具体体现在哪些方面&#xff1f; 一、引言 任何一个持续成长的公司最终都需要解决系统、组织…

【讲解下如何解决一些常见的 Composer 错误】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【Spring AI】09. ETL 管道

文章目录 ETL PipelineAPI 概述入门指南ETL 接口和实现DocumentReaderJsonReaderTextReaderPagePdfDocumentReaderParagraphPdfDocumentReaderTikaDocumentReader DocumentTransformerTextSplitterTokenTextSplitterContentFormatTransformerKeywordMetadataEnricherSummaryMet…