stm32学习:(寄存器2)GPIO总体说明

目录

GPIO的主要特点

GPIO的8种工作模式

GPIO电路结构

GPIO输出模式

输出流程

复用输出模式

GPIO输入模式

输入流程

模拟输入流程

GPIO相关的7个寄存器

GPIOx_CRL

GPIOx_CRH

GPIOx_IDR

GPIOx_ODR

GPIOx_BSRR

GPIOx_BRR

GPIOx_LCKR

 实例   三个灯流水灯

main.c 

Delay.h   

Delay.c   

Driver_LED.h 

Driver_LED.c


STM32有多组GPIO,比如我们使用的芯片:STM32F103ZET6共有7GPIO端口,他们分别是GPIOxxA-G),每组控制16个引脚,共有112GPIO引脚。具体一个其他STM32芯片有多少组GPIO,可以去查看他们的对应的数据手册

每个引脚的电平是0-3.3V,部分引脚最高可以兼容到5V。

GPIO的主要特点

  1. 不同型号,IO口的数量可能不一样
  2. 快速翻转。最快可以达到每2个时钟周期翻转一次
  3. 每个IO都可以作为外部中断
  4. 支持8种工作模式

GPIO的8种工作模式

GPIO端口的每个位(引脚)可以由软件分别配置成8种模式,当然对同一个引脚同一时间只能处于某一种模式中

  1. 输入浮空(Input floating)
  2. 输入上拉(Input pull-up)
  3. 输入下拉(Input-pull-down)
  4. 模拟输入(Analog)
  5. 通用开漏输出(Output open-drain)
  6. 通用推挽式输出(Output push-pull)
  7. 推挽式复用功能(Alternate function push-pull)
  8. 开漏复用功能(Alternate function open-drain)

每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字节被访问

输出模式下可以控制端口输出高电平低电平,用于驱动LED,蜂鸣器等,如果是大功率器件(比如电机),还需要加上驱动器(小电流控制大电流)。

输入模式下可以读取端口的高低电平,用于读取外接按键,外接模拟信号的输入,ADC电压采集,模拟通信协议接受数据等。

GPIO电路结构

GPIO输出模式

输出流程

  1. 输出缓冲器被激活
  2. 推挽模式:输出寄存器上的 1 将激活P-MOS,输出高电平。0 将激活N-MOS,输出低电平。
  3. 开漏模式:PMOS永远关闭。 输出寄存器上的 0 激活N-MOS,而输出寄存器上的1 将端口置于高阻状态,所以外部必须要接上拉电阻。
  4. 施密特触发输入被激活。
  5. 弱上拉和下拉电阻被禁止。
  6. 出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器。
  7. 在开漏模式时,对输入数据寄存器的读访问可得到I/O状态。
  8. 在推挽模式时,对输出数据寄存器的读访问得到最后一次写的值。

复用输出模式

  1. 在开漏或推挽式配置中,输出缓冲器被打开。
  2. 内置外设的信号驱动输出缓冲器(复用功能输出)。
  3. 施密特触发输入被激活。
  4. 弱上拉和下拉电阻被禁止。
  5. 在每个APB2时钟周期,出现在I/O脚上的数据被采样到输入数据寄存器。
  6. 开漏模式时,读输入数据寄存器时可得到I/O口状态。
  7. 在推挽模式时,读输出数据寄存器时可得到最后一次写的值。

GPIO输入模式

输入流程

  1. 2个保护二极管的作用是保护我们的芯片不会由于电压过高或过低而烧毁。
    1. VDD是接电源(3.3V),VSS接地(0V)。如果IO引脚的输入电压高于VDD的值到一定程度,上方保护二极管导通,则引脚电压被拉低到VDD。如果IO引脚的输入电压(负电压)低于VSS到一定程度,则下方保护二极管导通,电压被拉高到VSS
  2. 2个开关控制引脚没有输入的时候是上拉,下拉还是浮空。当上面的开关闭合的时候,输入被拉高到高电平。当下面的开关闭合的时候,输入被拉低到低电平。如果两个都不闭合,输入就是悬空状态。两个同时闭合,就是费电了,不会这么做的
  3. TTL触发器是包含正反馈的比较器电路。可以对信号进行波形整形
  4. 从TTL触发起出来的数据,进入到输入数据寄存器中,我们就可以从中读取数据了

模拟输入流程

当配置为模拟输入时:

  1. 输出部分被禁止
  2. 禁止TTL触发输入,实现了每个模拟I/O引脚上的零消耗。施密特触发输出值被强置为0
  3. 弱上拉和下拉电阻被禁止
  4. 读取输入数据寄存器时数值永远为0

GPIO相关的7个寄存器

每个GPIO端口有7个相关的

  1. 2个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)
  2. 2个32位数据寄存器(GPIOx_IDR和GPIOx_ODR)
  3. 1个32位置位/复位寄存器(GPIOx_BSRR)
  4. 1个16位复位寄存器(GPIOx_BRR)
  5. 1个32位锁定寄存器(GPIOx_LCKR)

GPIOx_CRL

端口配置低寄存器,x可以是A-G

 该寄存器配置的每个GPIO的 0-7 这个8个位,所以叫低寄存器

  • MODE:每个端口有2个MODE位进行控制
    • 00:输入模式(复位后的状态)
    • 01:输出模式,最大速度10MHz
    • 10:输出模式,最大速度2MHz
    • 11:输出模式,最大速度50MHz
  • CNF:每个端口有2个CNF位进行控制
    • 当MODE是00 (输入模式)
      • 00:模拟输入模式
      • 01:浮空输入模式(复位后的状态)
      • 10:上拉/下拉输入模式
      • 11:保留
    • 当MODE>00(输出模式)
      • 00:通用推挽输出模式
      • 01:通用开漏输出模式
      • 10:复用功能推挽输出模式
      • 11:复用功能开漏输出模式

GPIOx_CRH

端口配置高寄存器

该寄存器配置的是每个端口的 8-15引脚,配置方式和低位寄存器完全一样

GPIOx_IDR

端口输入数据寄存器,

 保留位始终读为0。剩下的分别对应每个引脚的输入值

GPIOx_ODR

端口输出数据寄存器

保留位始终读为0。剩下的分别对应每个引脚的输出值 

GPIOx_BSRR

端口位设置/清除寄存器

 高16位是用清除对应的数据输出寄存器的位(0-15)的值:设置为0不影响,设置为1会清除ODR对应的位的值(置为0)

低16位是用设置对应的数据输出寄存器的位(0-15)的值:设置为0不影响,设置为1会设置ODR对应的位的值(置为1)

GPIOx_BRR

端口位清除寄存器

这个寄存器具有了GPIOx_BSRR一半的功能:清除

GPIOx_LCKR

端口配置锁定寄存器

该寄存器用来锁定端口位的配置。位[15:0]用于锁定GPIO端口的配置。在规定的写入操作期间,不能改变LCKP[15:0]。当对相应的端口位执行了LOCK序列后,在下次系统复位之前将不能再更改端口位的配置

每个锁定位锁定控制寄存器(CRL,CRH)中相应的4个位(CNF2位和MODE2位)。

第16位用来激活锁定寄存器,必须按照规定的时序来操作才行: 写1 -> 写0 -> 写1 -> 读0 -> 读1

对0-15位:

  • 0:不锁定对应端口的配置
  • 1:锁定对应端口的配置 

 实例   三个灯流水灯

一共有好几个文件,

main.c 

#include "Driver_LED.h"
#include "Delay.h"int main()
{uint32_t leds[] = {LED_1, LED_2, LED_3};/* 1. 初始化LED */Driver_LED_Init();Drviver_LED_OffAll(leds, 3);while (1){for (uint8_t i = 0; i < 3; i++){Drviver_LED_OffAll(leds, 3);Drviver_LED_On(leds[i]);Delay_ms(500);}Drviver_LED_OffAll(leds, 3);Drviver_LED_On(leds[1]);Delay_ms(500);}
}

Delay.h   

#ifndef __delay_h
#define __delay_h
#include "stm32f10x.h"                  // Device headervoid Delay_us(uint16_t us);
void Delay_ms(uint16_t ms);
void Delay_s(uint16_t s);#endif

Delay.c   

#include "delay.h" // Device headervoid Delay_us(uint16_t us)
{/* 定时器重装值 */SysTick->LOAD = 72 * us;/* 清除当前计数值 */SysTick->VAL = 0;/*设置内部时钟源(2位->1),不需要中断(1位->0),并启动定时器(0位->1)*/SysTick->CTRL = 0x5;/*等待计数到0, 如果计数到0则16位会置为1*/while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG));/* 关闭定时器 */SysTick->CTRL &= ~SysTick_CTRL_ENABLE; 
}void Delay_ms(uint16_t ms)
{while (ms--){Delay_us(1000);}
}void Delay_s(uint16_t s)
{while (s--){Delay_ms(1000);}
}

Driver_LED.h 

#ifndef __DRIVER_LED_H
#define __DRIVER_LED_H#include "stm32f10x.h"#define LED_1 GPIO_ODR_ODR0
#define LED_2 GPIO_ODR_ODR1
#define LED_3 GPIO_ODR_ODR8void Driver_LED_Init(void);void Drviver_LED_On(uint32_t led);void Drviver_LED_Off(uint32_t led);void Drviver_LED_Toggle(uint32_t led);void Drviver_LED_OnAll(uint32_t leds[], uint8_t size);void Drviver_LED_OffAll(uint32_t leds[], uint8_t size);#endif

Driver_LED.c

#include "Driver_LED.h"/*** @description: 对LED进行初始化*/
void Driver_LED_Init(void)
{/* 1. 打开GPIOA的时钟 */RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;/* 2. 给用到的端口的所有 PIN (PA0 PA1 PA8) 设置工作模式: 通用推挽输出 MODE:11  CNF:00 */GPIOA->CRL |= (GPIO_CRL_MODE0 | GPIO_CRL_MODE1);GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1);GPIOA->CRH |= GPIO_CRH_MODE8;GPIOA->CRH &= ~GPIO_CRH_CNF8;/* 3. 关闭所有灯  */Drviver_LED_Off(LED_1);Drviver_LED_Off(LED_2);Drviver_LED_Off(LED_3);
}/*** @description: 点亮指定的LED* @param {uint32_t} led 要点亮的LED*/
void Drviver_LED_On(uint32_t led)
{GPIOA->ODR &= ~led;
}/*** @description: 关闭指定的LED* @param {uint32_t} led 要关闭的LED*/
void Drviver_LED_Off(uint32_t led)
{GPIOA->ODR |= led;
}/*** @description: 翻转LED的状态* @param {uint32_t} led 要翻转的LED*/
void Drviver_LED_Toggle(uint32_t led)
{/* 1. 读取引脚的电平,如果是1(目前是关闭), 打开, 否则就关闭 */if ((GPIOA->IDR & led) == 0){Drviver_LED_Off(led);}else{Drviver_LED_On(led);}
}/*** @description: 打开数组中所有的灯* @param {uint32_t} leds 所有灯* @param {uint8_t} size 灯的个数*/
void Drviver_LED_OnAll(uint32_t leds[], uint8_t size)
{for (uint8_t i = 0; i < size; i++){Drviver_LED_On(leds[i]);}
}/*** @description: 关闭数组中所有的灯* @param {uint32_t} leds 所有灯* @param {uint8_t} size 灯的个数*/
void Drviver_LED_OffAll(uint32_t leds[], uint8_t size)
{for (uint8_t i = 0; i < size; i++){Drviver_LED_Off(leds[i]);}
}

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

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

相关文章

C语言基础 9. 指针

C语言基础 9. 指针 文章目录 C语言基础 9. 指针9.1. &9.2. 指针9.3. 指针的使用9.4. 指针与数组9.5. 指针与const9.6. 指针运算9.7. 动态内存分配 9.1. & 运算符&: scanf(“%d”, &i);里的& 获得变量的地址, 它的操作数必须是变量 int i;printf(“%x”, &…

CSS中如何实现鼠标悬停效果?

在CSS中&#xff0c;您可以使用:hover伪类来实现鼠标悬停效果。:hover伪类会在用户将鼠标悬停在选择器所匹配的元素上时应用指定的样式。 下面是一个简单的例子&#xff0c;展示了如何在鼠标悬停时改变文本颜色和背景颜色&#xff1a; <!DOCTYPE html> <html lang&qu…

【SpringBoot Web开发之静态资源访问】笔记

详细内容见官方文档&#xff1a;Static Content SpringBoot Web开发之静态资源访问 1.准备工作&#xff1a;创建WebDemo2.静态资源目录2.1官网原文2.2静态资源目录第一步&#xff1a;依照上面2.1官网原文中创建如下目录第二步&#xff1a;复制粘贴图片到静态资源目录中第三步…

MySQL:JOIN 多表查询

多表查询 在关系型数据库中&#xff0c;表与表之间是有联系的&#xff0c;它们通过 外键 联系在一起&#xff0c;所以在实际应用中&#xff0c;经常使用多表查询。多表查询就是同时查询两个或两个以上的表。 MySQL多表查询是数据库操作中非常重要的一部分&#xff0c;它允许你…

Pandas 33个冷知识 0721

Pandas 33个冷知识 从Excel读取数据: 使用 pd.read_excel(file.xlsx) 来读取Excel文件。 写入Excel: 使用 df.to_excel(file.xlsx, indexFalse) 将DataFrame写入Excel文件。 创建日期索引: 使用 df.set_index(pd.to_datetime(df[date])) 创建日期索引。 向后填充缺失值: 使用…

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos,手写实现一个微服务注册中心

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos&#xff0c;手写实现一个微服务注册中心 注册中心手写实现一个注册中心服务端设计客户端设计 注册中心 注册中心是微服务体系里面非常重要的一个核心组件&#xff0c;它最重要的作用就是实现服务注册与发现。 …

【MyBatisPlus】快速掌握MP插件使用方法

一、MyBatis-Plus简介 1.1 简介 1.2 特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响&#xff0c;如丝般顺滑损耗小&#xff1a;启动即会自动注入基本 CURD&#xff0c;性能基本无损耗&#xff0c;直接面向对象操作强大的 CRUD 操作&#x…

【ACM独立出版|EI检索稳定】2024年智能感知与模式识别国际学术会议(ISPC 2024,9月6日-8)

2024年智能感知与模式识别国际学术会议 (ISPC 2024)将于2024年9月6日-8日于中国青岛召开。 会议将围绕智能感知与模式识别等领域中的最新研究成果&#xff0c;为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提供一个分享专业经验&#xff0c;扩大…

初谈Linux信号-=-信号的产生

文章目录 概述从生活角度理解信号Linux中信号信号常见的处理方式理解信号的发送与保存 信号的产生core、term区别 概述 从生活角度理解信号 你在网上买了很多件商品&#xff0c;再等待不同商品快递的到来。但即便快递没有到来&#xff0c;你也知道快递来临时&#xff0c; 你该…

机械臂泡水维修|机器人雨后进水维修措施

如果机器人不慎被水淹&#xff0c;别慌&#xff01;我们为你准备了一份紧急的机械臂泡水维修抢修指南&#xff0c;帮助你解决这个问题。 【机器人浸水被淹后紧急维修抢修&#xff5c;如何处理&#xff1f;】 机械臂被淹进水后维修处理方式 1. 机械手淹水后断电断网 首先&am…

Redis 深度历险:核心原理与应用实践 - 读书笔记

目录 第一章 基础应用篇Zset并发问题 - 分布式锁再谈分布式锁客户端在请求时加锁失败策略redis异步队列位图Hyperloglog布隆过滤器GeoHashscan 命令字典结构rehash扩容大 key 扫描 第二章 原理篇线程IO模型RESP 序列化协议持久化管道事务PubSub内存管理 第三章 集群篇CAP主从同…

Grid Puzzle

可以看看官方题解&#xff0c;说一下我的赛时做法 肯定操作二看起来都要优秀得多 不难发现&#xff0c;相邻两行不可能放两个及以上操作一&#xff0c;否则的话直接用两个操作二替代 利用数学归纳法考虑&#xff0c;对于第一行&#xff0c;我们要么用操作二&#xff0c;然后…

shell脚本教程学习

Bash 是 Linux 和 Mac 的默认 Shell&#xff08;命令行环境&#xff09;&#xff0c;系统管理和服务器开发都需要用。 echo命令 echo作用是在屏幕上输入一行文本&#xff0c;可以将该命令的参数输出。一般样式 $ echo "<HTML><HEAD><TITLE>Page Titl…

spring整合mybatis,junit纯注解开发(包括连接druid报错的所有解决方法)

目录 Spring整合mybatis开发步骤 第一步&#xff1a;创建我们的数据表 第二步&#xff1a;编写对应的实体类 第三步&#xff1a;在pom.xml中导入我们所需要的坐标 spring所依赖的坐标 mybatis所依赖的坐标 druid数据源坐标 数据库驱动依赖 第四步&#xff1a;编写SpringC…

Random,ThreadLocalRandom,SecureRandom有什么区别

private final Random randomnew Random(); Make sure that using this pseudorandom number generator is safe here. sonar给出的提示&#xff0c;应该如何修改代码? 根据Sonar的提示&#xff0c;为了确保在多线程环境下使用Random是安全的&#xff0c;您可以使用ThreadL…

linux在ssh的时候询问,yes or no 如何关闭

解决&#xff1a; 在~/.ssh/config文件中添加如下配置项&#xff1a; Host *StrictHostKeyChecking no

数据可视化配色新工具,颜色盘多达2500+类

好看的配色,不仅能让图表突出主要信息,更能吸引读者,之前分享过很多配色工具,例如, 👉可视化配色工具:颜色盘多达3000+类,数万种颜色! 本次再分享一个配色工具pypalettes,颜色盘多达2500+类。 安装pypalettes pip install pypalettes pypalettes使用 第1步,挑选…

Java 语言及其常用集合类的操作,以及反射机制与注解

目录 一、Java 语言概述 二、Java 集合框架 ArrayList 操作示例&#xff1a; HashMap 操作示例&#xff1a; 三、反射机制 1. 反射的示例 五、总结 Java 是一种广泛使用的高级编程语言&#xff0c;因其平台独立性、简洁性及丰富的 API 而备受开发者青睐。 一、Java 语言…

【LeetCode】分隔链表

目录 一、题目二、解法完整代码 一、题目 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 示例 1&#xff1a; 输入&a…

JVM中的GC流程与对象晋升机制

JVM中的GC流程与对象晋升机制 1、JVM堆内存结构2、Minor GC流程3、Full GC流程4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;垃圾回收&#xff08;GC&#xff09;是自动管…