STM32F4xx开发学习—GPIO

news2024/12/27 11:09:20

GPIO

学习使用STM32F407VET6GPIO外设

寄存器和标准外设库

1. 寄存器

  1. 存储器映射
    存储器本身是不具有地址的,是一块具有特定功能的内存单元,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就叫做存储区映射。给内存单元分配地址之后,就可以通过指针去操作内存地址。
  2. 存储器映射表
    STM32是一个32位的单片机,它的地址范围为2的32次方,也就是4GB的地址空间。为了降低不同客户在相同应用时的软件复杂度,存储映射是按Cortex-M4处理器提供的规则预先定义的。在存储器映射表中,一部分地址空间由Arm Cortex-M4的系统外设所占用,且不可更改,其余部分地址空间可由芯片供应商定义使用,如下图所示。
    memory map
  3. 什么是寄存器
    寄存器是读取速度最快的存储单元,具有特定功能的内存单元,通过操作这些内存单元可以驱动外设工作。寄存器按功能又可分为指令寄存器、地址寄存器和数据寄存器,处理器可以使用相互独立的总线来读取指令和加载/存储数据。
  4. 寄存器映射
    程序存储器,数据存储器,寄存器和I / O端口都在同一个线性的4 GB的地址空间之内。每一个寄存器都对应不同的功能,操作相应的寄存器就可以配置不同的功能。如果我们要控制某个外设工作,那我们可以找到这个单元的起始地址,然后通过c语言指针的方式来访问这些内存单元。但通常我们会给这个特殊的内存单元取一个名字,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射,这个别名就是我们所说的寄存器。
  5. 寄存器重映射
    有时在映射的结果中,地址会不够而造成重复,这里给寄存器再分配一个地址的过程叫做寄存器重映射。
  6. 总线基地址
    片上外设区域分为四条总线,分别为AHB1总线、AHB2总线、APB1总线和APB2总线。AHB总线最高时钟可达168MHZ,APB1总线最高时钟可达42MHZ,APB2总线时钟最高可达84MHZ。根据外设速度的不同,不同的总线挂载着不同的外设。总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址,可以通过参考手册中存储器映射这一节查询,四条总线地址如下表所示。
总线名称总线基地址总线地址范围
APB10x4000 00000x4000 0000-0x4000 FFFF
APB20x4001 00000x4001 0000-0x4001 FFFF
AHB10x4002 00000x4002 0000-0x4FFF FFFF
AHB20x5000 00000x5000 0000-0x5FFF FFFF
  1. 外设基地址
    每个总线上都挂载着很多外设,这些外设也都有自己的地址范围。
  2. 外设寄存器地址
    在外设的地址范围内,分布着该外设的寄存器。以GPIO外设为例,GPIO外设地址范围内有很多个寄存器,每一个都有特定的功能,通过操作对应的寄存器来配置GPIO的功能。每个寄存器都为32位,占4个字节,这里我们以GPIOA端口的寄存器进行介绍。
  3. 如何操作寄存器
    比如我们想让GPIOA端口的16个引脚都置1。我们需要去配置端口输出寄存器GPIOx_ODR(输出数据寄存器),通过查找用户手册283页可以知道这个寄存器的地址偏移量为0x14,GPIOA端口的基地址为0x4002 0000,所以GPIOx_ODR寄存器的地址为0x4002 0000 + 0x14 = 0x4002 0014,那我们就是对这个地址进行操作。

GPIO_ODR
该寄存器高16位保留,仅需配置低16位即可。每一位对应一个引脚输出,即向GPIOx_ODR写入0x0000FFFF即可。

  • 通过绝对地址访问内存单元
    代码如下
/*GPIOA端口16个引脚全部输出高电平*/
*(unsigned int*)(0x40020014) = 0x0000FFFF;//通过指针向0x40020014这个地址写入数值
  • 通过别名访问内存单元
    由于直接操作地址很麻烦,可通过预定义将所需用到的地址进行归纳,代码如下
/* GPIOA 端口的16个引脚全部输出高电平 */
#define GPIOA_ODR  (unsigned int*)(0x40020014)
*GPIOA_ODR = 0xFFFF;

2. 标准库函数

  1. 为什么要用库函数
    从上一节我们了解到如何去用寄存器驱动外设,但我们也同时了解到STM32的寄存器数量非常多,这么多的寄存器光是定义就需要花费很多的时间,更不用说还要去查找对应的功能,找到对应的地址,然后配置需要的值,这在难度和时间上都是不可取的。为此,库函数就在这种情况下应运而生,库函数能使我们的开发效率大大提高。关于STM32的标准外设库函数,STM32的官方已经给我们开发好了,我们只需要移植到我们的工程使用即可。库函数的使用不需要让我们去了解硬件的机制,只需要根据需要的功能去查找对应的函数,然后调用即可,大大降低了开发要求。
  2. 标准库函数介绍
    库函数就是在寄存器的基础上又封装了一层,使操作起来更简单,最后还是通过寄存器来实现的。
  3. 寄存器和库函数区别
    • 寄存器更能理解原理,更直观,库函数相对来说屏蔽底层,直接面向应用
    • 使用库函数较寄存器代码量会增大,库函数会把所有情况都考虑到函数里,有时会造成代码的冗余
    • 库函数使用起来相对简单,容易上手,可快速开发应用,大大提高效率
    • 寄存器占用内存少,速度快,在资源有限或者要求执行速度的情况下寄存器是一个不错的选择

GPIO外设

每个GPIO具有 4 个 32 位配置寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR 和 GPIOx_PUPDR)、2 个 32 位数据寄存器(GPIOx_IDR 和 GPIOx_ODR)、1 个 32 位设置/复位寄存器 (GPIOx_BSRR)、1 个 32 位锁定寄存器 (GPIOx_LCKR) 和 2 个 32 位备用功能选择寄存器(GPIOx_AFRH 和 GPIOx_AFRL)。

GPIO基本结构

GPIO版图
GPIO外设位于AHB1总线。每个端口通过16个引脚引出,由配置寄存器进行配置。

I/O引脚多路复用和映射

微控制器 I/O 引脚通过多路复用器连接到板载外设/模块,该多路复用器一次只允许一个外设的备用功能(AF)连接到 I/O 引脚。这样,共享同一 I/O 引脚的外设之间就不会发生冲突。同时每个 I/O 引脚都有一个多路复用器,具有 16 个备用功能输入(AF0 至 AF15),可通过 GPIOx_AFRL(引脚 0 至 7)和 GPIOx_AFRH(引脚 8 至 15)寄存器进行配置。在更小的封装内实现更多的外设数量

输入模式

GPIO输入基本结构如下
GPIO_输入模式
当I/O端口被编辑为输入模式时,输出驱动断开。

输出模式

GPIO输出基本结构如下
GPIO_输出模式
当I/O端口被编辑为输出模式时,输入驱动没有断开,具有采样功能

复用功能配置

GPIO复用基本结构如下
GPIO_复用
和输出模式类似,只不过增加了复用功能输入和复用功能输出。

LED灯

LED等基础知识

  1. LED灯结构组成
    LED灯,也称发光二极管,是一种能够将电能转化为可见光的固态的半导体器件,它可以直接把电转化为光。LED的内部是一个半导体的晶片,晶片的一端附在一个支架上,一端是负极,另一端连接电源的正极,整个晶片被环氧树脂封装起来。
  2. LED灯发光原理
    半导体晶片由两部分组成,一部分是P型半导体,另一端是N型半导体。这两种半导体连接起来的时候,它们之间就形成了一个P-N结。当电流通过导线作用于这个晶片的时候,电子就会被推向P区,在P区里电子跟空穴复合,然后就会以光子的形式发出能量,这就是LED灯发光的原理。
  3. LED灯驱动原理
    LED灯的驱动比较简单,只需要给将对应的正负极接到单片机的正负极即可驱动。需要注意的是LED灯的颜色不同,对应的电压也不同,同时需要串联分压电阻。板载LED如下图所示
    LED

LED灯驱动流程

通过上面的原理图可知LED灯正极接到电源上,负极连接到单片机GPIO口上,这里给PA6和PA7引脚输出低电平即可点亮LED。

寄存器点亮LED

STM32所有的外设资源时钟默认都是关闭的,因此在配置外设之前需要先开启对应的时钟。点亮板载LED需要使用GPIO外设,在stm32f4xx_gpio.c文件中知,使用GPIO端口,需要有一下几个步骤:

  • 开启GPIO时钟
  • 配置GPIO模式
  • 配置GPIO输出

开启GPIO外设端口时钟

STM32F407的GPIO外设在AHB1总线,需要配置AHB1使能寄存器,AHB1外设时钟寄存器如下图
GPIO外设时钟
该寄存器地址偏移量为0x30,查表得RCC外设基地址为0x4002 3800,那么RCC_AHB1ENR寄存器地址为:0x4002 3800 + 0x30 = 0x4002 3830。所使用得引脚是GPIOA端口,第零位Bit 0值为1,为保持其他位不变这里采用一个或运算。
代码为RCC->AHB1ENR |= 0x01;

配置GPIO模式

GPIO的模式配置可分为两步

  • 通过控制寄存器(GPIOx_MODER)配置为输入功能,输出功能,复用功能还是模拟功能
  • 通过 GPIO 上/下拉寄存器(GPIOx_PUPDR)配置GPIO的上下拉模式或者浮空

GPIO配置模式
该寄存器地址偏移量为0x00,GPIOA端口基地址为0x4002 0000,则GPIOx_MODER寄存器地址为:0x4002 0000 + 0x00 = 0x4002 0000,要使用的是第6号和第7号引脚,即选择该寄存器位12、13、14和15,为保持其他位数据不变,需先清空这两位后再写入数值。操作为:GPIOA_MODER &= 0xFFFF 0FFF;GPIOA_MODER |= 0x0000 5000;
输出模式一般配置为浮空模式,输入模式才需要考虑上拉还是下拉。通过寄存器GPIOx_PUPDR进行配置
GPIO配置模式
该寄存器地址偏移量为0x0C,GPIOA端口基地址为0x4002 0000,则GPIOx_MODER寄存器地址为:0x4002 0000 + 0x0C = 0x4002 000C,要使用的是第6号和第7号引脚,即选择该寄存器位12、13、14和15,为保持其他位数据不变,需先清空这两位后再写入数值。操作为:GPIOx_PUPDR &= 0xFFFF 0FFF;GPIOx_PUPDR |= 0x0000 0000;
转化为代码如下

GPIOA->MODER |= (0x05 << 2 * 6);//配置为输出模式
GPIOA->PUPDR &= ~(0x05 << 2 * 6);//配置为浮空模式

配置GPIO的输出

配置GPIO的输出同样分为两步,输出模式和端口速度。

  • 通过端口输出模式寄存器(GPIOx_OTYPER)配置为推挽模式、开漏模式
  • 通过端口输出速度寄存器(GPIOx_OSPEEDR)配置四种速度

GPIO输出模式
GPIO端口速度
寄存器写入数值过程同上。
转化为代码如下

GPIOA->OTYPER |= 0x0000;//配置为推挽输出
GPIOA->OSPEEDR |= (0x0F << 2 * 6);//配置为最高速

配置GPIO输出高低电平

配置GPIO引脚输出高低电平,即板载引脚PA6和PA7输出高低电平,可以通过端口输出数据寄存器GPIOx_ODR进行配置。

GPIO输出数据寄存器
转化为代码:GPIOA->ODR |= 0x0C;//输出高电平
总体代码如下

#include "stm32f4xx.h"                  // Device header

int main()
{
	RCC->AHB1ENR |= 0x01;//开启AHB1总线时钟
	
	GPIOA->MODER |= (0x05 << 2 * 6);//配置为输出模式
	GPIOA->PUPDR &= ~(0x05 << 2 * 6);//配置为浮空模式
	GPIOA->OTYPER &= ~(0x03 << 2 * 3);//配置为推挽模式
	GPIOA->OSPEEDR |= (0x0F << 2 * 6);//配置为最高速
	
//	GPIOA->ODR |= (0x03 << 2 * 3);//输出高电平
	GPIOA->ODR |= (0x00 << 2 * 3);//输出低电平
}

库函数点亮LED

同样按照上述步骤进行编写代码,这里新建一个LED.c文件便于对外设进行管理。

//LED.c文件
#include "LED.h"

void LED_Init()
{
	//初始化PA6和PA7为输出口	
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;//LED0和LED1对应IO口
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
	
	GPIO_SetBits(GPIOA,GPIO_Pin_6 | GPIO_Pin_7);//设置高,灯灭
	
}

void LED1_ON()
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_6);
}

void LED2_ON()
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}

void LED1_OFF()
{
	GPIO_SetBits(GPIOA, GPIO_Pin_6);
}

void LED2_OFF()
{
	GPIO_SetBits(GPIOA, GPIO_Pin_7);
}

所对应的头文件LED.h代码如下

//LED.c文件
#ifndef __LED_H
#define __LED_H

#include "stm32f4xx.h"                  // Device header

void LED_Init(void);//初始化	
void LED1_ON();
void LED1_OFF();
void LED2_ON();
void LED2_OFF();

#endif

主函数main代码如下

#include "LED.h"
int main()
{
	//库函数点亮LED
	LED_Init();
	LED1_OFF();
	LED2_ON();
	while(1)
	{
		
	}
}

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

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

相关文章

页面多开、谷歌浏览器解决不能批量打开问题、批量打开被限制

目录 问题原因谷歌浏览器解决办法来看效果 问题 我们使用批量打开页面的时候 只能打开第一个页面 原因 这种问题是因为 浏览器限制了浏览器的弹出 并不是人家页面功能不能用 谷歌浏览器解决办法 在浏览器输入这个路径 chrome://settings/content/popups?search%E9%87%…

Vue MVVM这一篇就够啦!

Vue vs React 相似之处: 它们都有使用 Virtual DOM虚拟DOM-CSDN博客&#xff1b;提供了响应式&#xff08;Reactive&#xff09;和组件化&#xff08;Composable&#xff09;的视图组件。将注意力集中保持在核心库&#xff0c;而将其他功能如路由和全局状态管理交给相关的库。R…

Python安装以及环境配置

目录 一、下载安装包二级目录三级目录 一、下载安装包 方式网址Python官网python.org镜像下载地址Download pythonpycharmDownload PyCharm https://blog.csdn.net/sun80760/article/details/135256627 二级目录 三级目录

Spring+SpringMVC+Jsp实现校园二手交易系统

前言介绍 在社会快速发展的影响下&#xff0c;使校园二手交易系统的管理和运营比过去十年更加理性化。依照这一现实为基础&#xff0c;设计一个快捷而又方便的网上校园二手交易系统是一项十分重要并且有价值的事情。对于传统的管理控制模型来说&#xff0c;网上校园二手交易系…

C++构造函数和析构函数的调用顺序

一般情况下&#xff0c;调用析构函数的次序正好与调用构造函数的次序相反&#xff0c;也就是最先被调用的构造函数&#xff0c;其对应的析构函数最后被调用&#xff0c;而最后被调用的构造函数&#xff0c;其对应的析构函数最先被调用。 当然对象的构造函数和析构函数调用时机和…

图片浏览器-PicView

一、前言 PicView 是一款适用于 Windows 10 或 11 的快速高效的图像查看器&#xff0c;配备了干净简洁的用户界面&#xff0c;可以在不需要时方便地隐藏。 二、支持类型 它支持广泛的图像文件类型&#xff0c;包括&#xff1a;WEBP、GIF、SVG、PNG、JXL、HEIC、PSD 三、软件特…

Docker 的网络实现

简介 标准的 Docker 支持以下 4 类网络模式&#xff1a; 1&#xff09;host 模式&#xff1a;使用 --nethost 指定 2&#xff09;container 模式&#xff1a;使用–netcontainer:NAME_or_ID 指定 3&#xff09;none模式&#xff1a;使用 --netnone 指定 4&#xff09;bridge 模…

2.5W字 一文读懂汽车智能座舱的FLASH 存储市场、技术

吃瓜群众&#xff1a;机哥&#xff0c;存储是什么玩意&#xff0c;我买手机、电脑的时候导购员都说买内存大的&#xff0c;三星的好&#xff0c;品牌大&#xff0c;问题少&#xff0c;我也只有看哪个内存大就买那个。 机哥&#xff1a;额&#xff0c;这个嘛&#xff0c;说来话长…

SpringBoot+Vue+Element-UI实现学生综合成绩测评系统

前言介绍 学生成绩是高校人才培养计划的重要组成部分&#xff0c;是实现人才培养目标、培养学生科研能力与创新思维、检验学生综合素质与实践能力的重要手段与综合性实践教学环节。而学生所在学院多采用半手工管理学生成绩的方式&#xff0c;所以有必要开发学生综合成绩测评系…

Day62:单调栈 LeedCode503. 下一个更大元素 II 42. 接雨水

503. 下一个更大元素 II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数…

分布式与一致性协议之ZAB协议(三)

ZAB协议 主节点崩溃了&#xff0c;怎么办&#xff1f; 众所周知&#xff0c;系统在运行中不可避免会出现各种各样的问题&#xff0c;比如进程崩溃了、服务器死机了&#xff0c;这些问题会导致很严重的后果&#xff0c;让系统没办法继续运行。在ZAB协议中&#xff0c;写请求是…

【软考】模拟考卷错题本2024-05-05

1 算法 关键词&#xff1a;按照单位重量价值大优先&#xff0c;那就是1、2、3即430&#xff1b;之后的根据排除法又可以得到630&#xff1b;故C。 2 UML 序列图 上图已经基本上有解析&#xff1b;重点在于在四个选项中选正确的。根据概念排除&#xff1a;异步和同步是不一样的&…

GateWay检查接口耗时

添加gateway依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency>创建一个LogTimeGateWayFilterFactory类&#xff0c;可以不是这个名字但是后面必须是x…

opencv基础篇 ——(十六)图形绘制与填充

OpenCV 提供了丰富的图形绘制和填充功能&#xff0c;主要通过 cv::rectangle, cv::circle, cv::line, cv::polylines, cv::fillPoly 和 cv::ellipse 等函数实现。以下是一些基本的图形绘制和填充操作的说明&#xff1a; 矩形: 函数: cv::rectangle语法: cv::rectangle(img, rec…

10000 字详细讲解 Spring 中常用注解及其使用

如下图京东购物页面&#xff0c;当我们选择点击访问某一类商品时&#xff0c;就会向后端发起 HTTP 请求&#xff0c;当后端收到请求时&#xff0c;就会找到对应的代码逻辑对请求进行处理&#xff0c;那么&#xff0c;后端是如何来查找处理请求相对应的代码呢&#xff1f;答案就…

JRT1.6发布

经过51的三天努力&#xff0c;完成基于JRT的质控核心部分。框架部分已经达到了第一个可生产版本。 可生产包括以下部分&#xff1a; 1.Web开发基础和发布运维基础 2.Linux和WIndows客户端浏览器 3.Linux和WIndows客户端打印导出程序 4.Linux和WIndows初始化程序 5.Linux和WInd…

调用第三方接口——支付宝付款

沙箱环境是支付宝开放平台为开发者提供的用于接口开发及主要功能联调的模拟环境。 参考 登录 - 支付宝 在沙箱环境下&#xff0c;已经分配好了用于模拟测试的应用信息、商家信息、买家信息等 小程序文档 - 支付宝文档中心 内网穿透&#xff08;支付宝付款需要在公网进行检查…

谁能取代迈巴赫,征服互联网安全大佬周鸿祎?

‍作者 |老缅 编辑 |德新 4月18日&#xff0c;「周鸿祎卖车」登上了微博热搜。这位360创始人、董事长发微博称&#xff1a;自己做了一个艰难的决定&#xff0c;将把陪伴9年的迈巴赫600给卖掉。 随后&#xff0c;他解释道&#xff1a;「这是因为我需要体验新一代车的感觉。古人…

从零开始学RSA: [WUSTCTF2020]情书等5题

1 [WUSTCTF2020]情书 题目 Premise: Enumerate the alphabet by 0、1、2、..... 、25 Using the RSA system Encryption:0156 0821 1616 0041 0140 2130 1616 0793 Public Key:2537 and 13 Private Key:2537 and 937flag: wctf2020{Decryption}解题 前提&#xff1a;用0、…

C++初阶学习第五弹——类与对象(下)——类与对象的收官战

类与对象&#xff08;上&#xff09;&#xff1a;C初阶学习第三弹——类与对象&#xff08;上&#xff09;——初始类与对象-CSDN博客 类与对象&#xff08;中&#xff09;&#xff1a;C初阶学习第四弹——类与对象&#xff08;中&#xff09;——刨析类与对象的核心点-CSDN博…