STM32——GPIO篇

技术笔记!

1.  什么是GPIO?

        GPIO是通用输入输出端口(General-purpose input/output)的英文简写,是所有的微控制器必不可少的外设之一,可以由STM32直接驱动从而实现与外部设备通信、控制以及采集和捕获的功能。

        GPIO口可配置为多种输入输出模式,如输入浮空、输入上拉、输入下拉、模拟输入、开漏输出、开漏复用功能、推挽式输出以及推挽式复用功能等。

        STM32单片机的GPIO被分为很多组,每组最多有16个引脚,不同型号的 MCU 的GPIO个数是不同的。

        引脚电平:0V~3.3V,部分引脚可容忍5V(FT)。

2.  GPIO内部结构

3.  GPIO工作模式(重点)

4  GPIO寄存器(以STM32f103C8T6为例)

        1.  端口配置低寄存器 CRL

        通常最多拥有16个引脚,每个引脚需要4位来进行配置,需要64位,两字节,所以端口配置寄存器分为高位和低位。

        端口配置寄存器主要是配置端口的八种模式以及输出速度,如下图

        2.  端口配置高寄存器 CRH(作用和CRL一样)

        3.  端口输入数据寄存器 IDR

        将输入的值存入相应的引脚位置中。

        4.  端口输出数据寄存器 ODR

        将ODR寄存器对应的 引脚内的值输出到接收的值中。

        5.  端口位设置/清除寄存器 BSRR

           6.  端口位清除寄存器 BRR (不常用)

           7.  端口配置锁定寄存器 LCKR(不常用)

5  GPIO中的HAL库

        其中GPIO_TypeDef *GPIOx指的是GPIO中的组别,GPIO_Pin指的是需要操作的引脚。

        Init 函数对GPIO进行初始化,EXTI是中断函数,ReadPin是读相应的引脚,TogglePin是翻转引脚,WritePin是将值写入相应的引脚。

6.  点亮led灯实验

led.c

#include "led.h"
#include "sys.h"//初始化GPIO函数
void led_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOB_CLK_ENABLE();                           // 使能GPIOB时钟//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_8;                       // LED1对应的引脚gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             // 推挽输出gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           // 高速HAL_GPIO_Init(GPIOB, &gpio_initstruct);//关闭LEDled1_off();
}//点亮LED1的函数
void led1_on(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);   // 拉低LED1引脚,点亮LED1
}//熄灭LED1的函数
void led1_off(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);     // 拉高LED1引脚,熄灭LED1
}//翻转LED1状态的函数
void led1_toggle(void)
{HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
}

main.c

#include "sys.h"
#include "delay.h"
#include "led.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* 初始化LED灯 */
//    led1_on();                        /* 点亮LED1 */
//    led1_off();                       /* 熄灭LED1 */while(1){ led1_toggle();/*led1_on();delay_ms(500);led1_off();*/delay_ms(500);}
}

实验小结:

        本次实验主要是掌握gpio引脚的使用,通过使能GPIO时钟,进而控制通过原理图所查到的led相关引脚,使用GPIO初始化函数进行GPIO的初始化。初始化gpio之前得配置GPIO的初始化结构体,如对应的引脚,GPIO模式(输出、输入、复用等),上下拉以及速度等。通过HAL_GPIO_Write函数写入led引脚对应的寄存器中的值,改变电位,进而控制led灯的亮灭,并且使用了翻转函数HAL_GPIO_Toggle函数,翻转对应引脚的状态,起到led灯的状态翻转。

        主函数中首先初始化了HAL库(本次实验通过调用HAL库来实现),并且初始化了时钟,接着初始化led函数。

7.  按键实验

key.c

#include "key.h"//初始化GPIO函数
void key_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOA_CLK_ENABLE();                           // 使能GPIOB时钟//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;                       // key1,key2对应的引脚gpio_initstruct.Mode =  GPIO_MODE_INPUT;             // 输入gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉,该模式的设置须和跟工作模式相反gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           // 高速HAL_GPIO_Init(GPIOA, &gpio_initstruct);}
//按键扫描函数
uint8_t key_scan(void)
{//检测按键1是否被按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){//消抖delay_ms(10);//再次判断是否被按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){//如果确实是按下的状态,等待按键松开while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET);//返回按键值return 1;}}//检测按键2是否被按下,使用了readPin函数if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET){//消抖delay_ms(10);//再次判断是否被按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET){//如果确实是按下的状态,等待按键松开while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET);//返回按键值return 2;}}//返回默认值return 0;
}

main.c

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* 初始化LED灯 */key_init();                         /* 初始化key*/uint8_t key_num = 0;while(1){ key_num = key_scan();           /* 扫面按键获取按键的值*/if(key_num == 1)                /* 检测按键1按下*/{led1_toggle();              /*翻转LED1*/}if(key_num == 2)                /* 检测按键2按下*/{led2_toggle();              /*翻转LED2*/}}
}

实验小结:

        按键实验是为了对GPIO有更加深层次的认识,在led的实验的基础上,通过多个引脚控制led灯的亮灭。实验步骤首先是对GPIO时钟使能,进而初始化GPIO,通过gpio结构体结构体对GPIO进行相关引脚的配置,当需要初始化多个引脚时可以使用  ’|‘ 或运算符,如 GPIO_PIN_0 | GPIO_PIN_1,模式设为输入模式,led中的是输入模式,上下拉设置为上拉模式(不工作的状态)。使用自定义的按键扫描函数检测按键的状态,通过两次HAL_GPIO_ReadPin读取引脚状态,第一次为了防止是误触并且使用延时函数进行消抖,通过轮询的读取引脚等待按键的松开,最后返回对应的按键。

        主函数初始化HAL库,时钟的初始化,通过自定义的按键扫描函数返回的值进而控制led灯的翻转。

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

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

相关文章

当管道运算符遇上无限可能:探索数据流的奇妙之旅

文章目录 序言目的进程间通信的理解进程间通信的发展历史管道创建验证管道的大小管道的4种情况管道的5种特征 序言 通过该命令计算了在当前路径下一共有多少个文件夹的任务 进程虽然有独立性,但是进程并不孤僻,他们之间也会相互进行协作共同完成一件事 这个前提是他们之间的信…

嵌入式全栈开发学习笔记---C语言笔试复习大全7(编程题1~8)

目录 1、200~300之间能被3整除的数,5个一行输出; 2、求两个数的最大公约数、最小公倍数; 3、输入十个数,求出平均值; 4、通过编程实现,统计1~n有多少个9; 5、有1、2、3、4个数字&#xff0…

C#简单创建DLL文件并调用

DLL是Dynamic Link Library的缩写,意为动态链接库。动态链接库其实是由编译器将一系列相关的类型编译、链接并封装成一个独立的文件,与对其进行调用的程序分开。这样一个独立的文件相当于程序的一个模块,如果需要对程序进行更新,只…

ESP32-C3第二路串口(非调试)串口打通(1)

1. 概述与引脚复用 《ESP32-C3 系列芯片技术规格书》中提到,ESP32-C3系列芯片中有两路串口。 第1路串口就是常用的调试串口,在笔者使用的ESP32-C3-DevKitC-02开发板中,这一路串口通过CP2102 USB转UART桥芯片与电脑的USB口相连接,…

42 线程池

一种线程使用模式,线程过多会带来调度开销,进而影响缓存局部性和整体性能。线程池维护多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价,线程池不仅能保证内核的充分利用&#xf…

redis中的双写一致性问题

双写一致性问题 1.先删除缓存或者先修改数据库都可能出现脏数据。 2.删除两次缓存,可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离,读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…

数据结构------栈的介绍和实现

目录 1.栈的一些初步认识 2.栈的实现 3.相关的函数介绍 (1)栈的初始化 (2)栈的销毁 (3)栈的数据插入 (6)判断是否为空 (7)栈的大小 4.栈的实现完整…

【数据结构(邓俊辉)学习笔记】列表01——从向量到列表

文章目录 0.概述1. 从向量到列表1.1 从静态到动态1.2 从向量到列表1.3 从秩到位置1.4 列表 2. 接口2.1 列表节点2.1.1 ADT接口2.1.2 ListNode模板类 2.2 列表2.2.1 ADT接口2.2.2 List模板类 0.概述 学习了向量,再介绍下列表。先介绍下列表里的概念和语义&#xff0…

【HM】DevEco Studio如何使用代码编程AI助手

大家可能都有用过或了解过github copilot插件,确实为我们编码智能、提升开发效率有很大的帮助。推荐两款国产的ai编程插件,分别是华为的CodeArts Snap和阿里的通义灵码。 DevEco 中如何安装通义灵码? 一、下载通义灵码离线安装包 打开官网…

每日OJ题_贪心算法二⑤_力扣870. 优势洗牌(田忌赛马)

目录 力扣870. 优势洗牌(田忌赛马) 解析代码 力扣870. 优势洗牌(田忌赛马) 870. 优势洗牌 难度 中等 给定两个长度相等的数组 nums1 和 nums2,nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引…

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

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

解决layui的bug 在layui tree 组件中 禁用选中父节点后自动选中子节点功能

最近做权限管理后台,用了layui tree 组件,发现选中了父节点后,自动选中了子节点。不满足现实业务需求。所以微调了下源代码。 在用树形组件中,在用文档中 tree.setChecked(demoId, [2, 3]); //批量勾选 id 为 2、3 的节点 用这句…

linux 服务器利用阿里网盘API实现文件的上传和下载

文章目录 背景脚本初始化 阿里云盘API工具 aligo安装aligoaligo教程实战parse.py 演示上传文件上传文件夹下载文件下载文件夹 背景 最近在用ubuntu系统做实验,而ubuntu 系统的文件上传和下载操作很麻烦; 于是便打算使用阿里网盘的API 进行文件下载与上传…

腾锐D2000-8 MXM VPX,全国产,可广泛应用于边缘计算网关、入侵检测、VPN、网络监控等等应用领域

腾锐D2000-8 MXM VPX 1. 概述 XMVPX-108 是一款基于飞腾 D2000/8 处理器的低功耗逻辑运算和图形处理 VPX 刀片, 板贴 32GB DDR4 内存,搭载飞腾 X100 套片,满足通用 IO 接口功能。GPU 采用 MXM 小型插卡形式, 搭配 8GB 显卡。提供…

NIO和NIO.2对比

Java NIO (New Input/Output) 是从Java 1.4版本开始引入的一个新的I/O API,用于替代原来的BIO(Blocking I/O)API。NIO提供了更加灵活和高效的网络通信方式,特别适合于高吞吐量的网络编程。NIO的主要特点是非阻塞模式,它…

3.4 无关、基和维度

这一节是关于子空间的真实大小。对于 m n m\times n mn 的矩阵,它有 n n n 个列,但是它真正的维数不一定为 n n n,维数可以由无关列的个数来得到。列空间的实际维度就是秩 r r r。 无关的概念是用于向量空间中的任意向量 v 1 , . . . ,…

【LAMMPS学习】八、基础知识(5.7)Drude感应偶极子

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

人工智能|推荐系统——工业界的推荐系统之召回

基于物品的协同过滤 ⽤索引,离线计算量⼤,线上计算量⼩ Swing额外考虑重合的⽤户是否来⾃⼀个⼩圈⼦,两个⽤户重合度⼤,则可能来⾃⼀个⼩圈⼦,权重降低。 基于用户的协同过滤 同样是离线计算索引,在线召回的流程 离散特征处理 Embedding 层参数数量=向量维度 类别数量 矩

DS高阶:图论算法经典应用

一、最小生成树(无向图) 在了解最小生成树算法之前,我们首先要先了解以下的准则: 连通图中的每一棵生成树,都是原图的一个极大无环子图,即:从其中删去任何一条边,生成树就不在连通&a…

mysql查询数据不对

sum(id)是算id这一列的数值总和,无论主键与否,sum都是算数值总和 count(id)或count(*)是算当前列的行数,id是主键才行