stm32f103-gpio源码理解

2023-05-16

提要:参照野火的stm32f103开发指南,对标准库的构造进行理解:
(1)使用结构体,使用宏,使用枚举
(2)因为参数是可变的,所以针对可变的参数,设计了函数,目的是尽管参数不同,但最终都能配置
相关的寄存器。

//枚举
typedef enum
{ 
  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

//结构体
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;

//结构体
typedef struct
{
  uint16_t GPIO_Pin;             

  GPIOSpeed_TypeDef GPIO_Speed; 

  GPIOMode_TypeDef GPIO_Mode;   
                                     
}GPIO_InitTypeDef;

这个结构体中包含了初始化 GPIO 所需要的信息,包括引脚号、工作模式、输出速率。设计这个结构体的思路是:初始化 GPIO 前,先定义一个这样的结构体变量,根据需要配置 GPIO 的模式,对这个结构体的各个成员进行赋值,然后把这个变量作为“GPIO 初始化函数”的输入参数,该函数能根据这个变量值中的内容去配置寄存器,从而实现 GPIO 的初始化

图1
bit4 用来区分端口是输入还是输出, 0 表示输入, 1 表示输出。

bit2 和 bit3 对应寄存器的 CNFY[1:0]位【】指明输入是什么模式,输出是什么模式【】,是我们真正要写入到 CRL 和 CRH 这两个端口控制寄存器中的值。

bit0 和 bit1 对应寄存器的 MODEY[1:0]位【v】指明是输入模式还是输出模式,指出输出模式时,还指定了输出的速度【0】,这里我们暂不初始化,在 GPIO_Init()初始化函数中用来跟 GPIOSpeed 【v】又是一个枚举变量【0】的值相加即可实现速率的配置。

其中在下拉输入和上拉输入中我们设置 bit5 和 bit6 的值为 01 和 10 来以示区别。

所以使用枚举类型可以对结构体成员起到限定输入的作用,只能输入相应已定义的枚举值。

GPIO_InitTypeDef GPIO_InitStructure;

 /* GPIO 端口初始化 */
/*选择要控制的 GPIO 引脚, GPIO_Pin_0是宏定义*/
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
/*设置引脚模式为输出模式,GPIO_Mode_Out_PP 是枚举变量*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚的输出类型为推挽输出,GPIO_Mode_Out_PP 是枚举变量*/
GPIO_InitStructure.GPIO_Speed = GPIO_Mode_Out_PP;

接着前面的思路,对初始化结构体赋值后,把它输入到 GPIO 初始化函数,由它来实
现寄存器配置。


void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
  uint32_t tmpreg = 0x00, pinmask = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
  
/*---------------------------- GPIO Mode Configuration -----------------------*/
  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
	
	/*判断是输出模式还是输入模式*/
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
  { 
    /* Check the parameters */
    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
		
    /* Output mode,如果是输出模式,就将输出速度的枚举值与输出模式的值相或,
		那么,bit0,bit1,bit2,bit3的值都确定了,确定了是开漏输出还是推挽输出(bit2和bit3),确定了输出速度(bit0和bit1) */
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
  }
/*---------------------------- GPIO CRL Configuration ------------------------*/
  /* Configure the eight low port pins*/
	/*-----GPIO CRL 寄存器配置 CRL 寄存器控制着低 8 位 IO- ----*/
 /*配置端口低 8 位,即 Pin0~Pin7 */
  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)/*说明设置了低8位的pin*/
  {
		/*先备份GPIOx->CRL的值,可能先前有别的设置*/
    tmpreg = GPIOx->CRL;
		
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = ((uint32_t)0x01) << pinpos;
      /* Get the port pins position */
      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
      if (currentpin == pos)
      {
        pos = pinpos << 2;/*pinpos的值左移2位(乘以4),因为寄存器中4个位配置一个引脚*/
        /* Clear the corresponding low control register bits ,先清0*/
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits ,后置位*/
        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)/*判断是否为下拉输入*/
        {
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);/*下拉输入模式,引脚置0,对BRR寄存器写1对引脚置0*/
        }
        else
        {
          /* Set the corresponding ODR bit ,判断是否为上拉输入模式*/
          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          {
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);/*上拉输入模式,引脚默认置1,对BSRR寄存器写1对引脚置1*/
          }
        }
      }
    }
		/*把前面处理后的暂存值写入到CRL*/
    GPIOx->CRL = tmpreg;
  }
/*---------------------------- GPIO CRH Configuration ------------------------*/
  /* Configure the eight high port pins ,配置端口高8位,Pin8~Pin15*/
  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
  {
    tmpreg = GPIOx->CRH;/*先备份CRH寄存器的值*/
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = (((uint32_t)0x01) << (pinpos + 0x08));/*循环,从Pin8开始配对,找出具体的Pin*/
      /* Get the port pins position */
      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
      if (currentpin == pos)
      {
        pos = pinpos << 2;
        /* Clear the corresponding high control register bits */
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */
        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
        /* Set the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
        {
          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
      }
    }
    GPIOx->CRH = tmpreg;/*把前面处理后的暂存值写入到CRH寄存器之中*/
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stm32f103-gpio源码理解 的相关文章

  • 树莓派GPIO

    命令行执行下行 xff0c 即可得树莓派管脚编码表 gpio readall 也可看下图 xff1a BOARD 编号参考 Raspberry Pi 主板上 P1 接线柱的针脚编号 使用该方式的优点是无需考虑主板的修订版本 xff0c 无需
  • void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)的一些理解

    GPIO TypeDef GPIOA BASE 表示将GPIOA BASE强制转换为指针类型的结构体 xff0c define GPIOA GPIO TypeDef GPIOA BASE 表示用 GPIO TypeDef GPIOA BAS
  • STM32F103驱动LD3320语音识别模块

    STM32F103驱动LD3320语音识别模块 LD3320语音识别模块简介模块引脚定义STM32F103ZET6开发板与模块接线测试代码实验结果 LD3320语音识别模块简介 基于 LD3320 xff0c 可以在任何的电子产品中 xff
  • STM32F103 GPIO内部电路图

    GPIO结构图 GPIO工作模式 输入模式 输入浮空 输入上拉 输入下拉 模拟输入 输出模式 开漏输出 开漏复用功能 推挽式输出 推挽式复用功能 输入浮空 输入上拉 输入下拉 模拟输入 开漏输出 开漏复用功能 推挽式输出 推挽式复用功能
  • linux用户态使用gpio中断方法

    一 用户空间gpio的调用文件 用户空间访问gpio 即通过sysfs接口访问gpio 下面是 sys class gpio目录下的三种文件 export unexport文件 gpioN指代具体的gpio引脚 gpio chipN指代gp
  • AIR103

    基础资料 基于Air103开发板 Air103 LuatOS 文档 上手 开发上手 LuatOS 文档 探讨重点 对官方社区库接口GPIO库使用及示例进行复现及分析 了解该的基本原理及操作方法 软件及工具版本 LuatOS AIR103 b
  • [STM32系列]二、实现STM32 GPIO端口状态实现最大速度翻转

    STM32系列 二 实现STM32 GPIO最快速度翻转 文章目录 STM32系列 二 实现STM32 GPIO最快速度翻转 前言 一 实验准备 二 测试 1 C语言翻转测试 2 汇编翻转测试 总结 前言 在STM32F103系列应用过程中
  • 基于STM32的超声波感应垃圾桶

    目录 成果演示 材料 主要代码 总结 成果演示 材料 STM323f103开发板 最小系统均可 超声波模块 HC SR04模块 舵机一个 垃圾桶模型 主要代码 超声波模块 include ultrasonsic h include dela
  • wiringPi引脚编号方式

    树莓派引出的20 2排针引脚 引脚定义使用gpio readall命令查看 如下 可以看到wiringpi库有三种引脚编号方式 分别为 BCM编号方式 就是使用芯片的GPIO引脚编号 wiringpi库编号方式 使用wiringpi库自己规
  • 学习笔记:STM32的ACD

    STM32f103系列有3个ADC ADC1 ADC2 ADC3 通道 ADC1和ADC2都有16个外部通道 2个内部通道 连接到温度传感器和内部参考电压 VREFINT 1 2V ADC3有8个外部通道 通道列表 通道顺序转换 使用多个通
  • stm32f103 TIM2定时器4路PWM输出实验

    这里以TIM2为例 pwm c include pwm h uint16 t TIM2 CCR1 Val uint16 t TIM2 CCR2 Val uint16 t TIM2 CCR3 Val uint16 t TIM2 CCR4 Va
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • STM32基本IO的寄存器介绍

    STM32基本IO的寄存器介绍 说明 简介 端口配置低寄存器 32位 数据寄存器 32位 置位 复位寄存器 32位 复位寄存器 16位 锁存寄存器 32位 说明 最近自己在学习STM32 跟着原子哥的STM32教学视频学习 参考的资料有来自
  • 解决keil中 点击setting 程序中断问题

    自己写了一个LED常亮的程序 入门嘛 但是程序在下载后 点击 debug setting 在软件识别J link后 程序是成功的 但是LED不亮了 下面是解决方法 记住把2标记处的对勾去掉就可以了 这个功能是 在你连接完成时自动在Reset
  • Raspberry pi 4 用 java 控制 GPIO

    我想用java控制我的树莓派4上的16 2液晶显示屏 问题是Pi4J 用java修改gpios的解决方案没有更新到pi4 还有其他解决方案吗 当我启动程序时出现此错误 pi raspberrypi desktop gpio sudo sta
  • [Firefly-Linux] RK3568 gpio-leds驱动详解

    文章目录 一 GPIO 介绍 二 RK3568 GPIO 状况 三 GPIO 引脚计算 四 ITX 3568JQ LED 4 1 LED 原理图 4 2 LED 设备树
  • Raspberry Pi RuntimeError:已为此 GPIO 通道启用冲突边缘检测

    我正在遵循此处找到的教程 https www linkedin com pulse prepare your raspberry pi work aws iot kay lerch I have not even begun the int
  • GPIO-Hog声明的目的和用途

    问题 其目的和用例是什么gpio hog宣言 可以从用户空间连接 占用 的 GPIO 引脚吗 如果 占用 GPIO 引脚无法与用户空间交互 那么是否有任何机制可以在 dts 文件中配置 GPIO 引脚以进行用户空间交互 背景 我正在尝试配置
  • Python使用sudo启动时找不到模块

    我有一个使用 Google Assistant 库的脚本 并且必须从那里导入一些模块 我发现这只适用于 Python 虚拟环境 这真的很奇怪 在同一个文件夹中 我有一个使用 GPIO 引脚并且必须使用 root 的脚本 它们相互交互 因此当
  • “此 GPIO 引脚已存在:”第二次出现 GPIO 1 异常

    我正在 Raspberry pi 和 java 上工作 通过使用 pi4j 使 LED 闪烁 一切都已清除并且工作正常 LED 按照代码闪烁 但是当我第二次运行时 它会导致以下错误 我已经搜索了很多有很多相同的问题没有明确的答案如何解决 任

随机推荐

  • 7.安装Proxmox Backup Server

    安装Proxmox Backup Server 1 安装 安装和Proxmox VE基本是一样的 xff0c 看图一直下一步即可 安装完成会自动重启 xff0c 重启后如下图 2 参考 1 https pbs proxmox com wik
  • 8. 添加Backup Server到PVE集群

    添加Backup Server到PVE集群 1 配置磁盘 2 配置账户 3 PVE中添加 Backup Server
  • 在Harvester上安装windows sever 2012 r2

    安装Windows Server 2012 r2 文章目录 安装Windows Server 2012 r2新建虚拟机配置基础信息配置卷配置网络开机 xff0c 进入安装系统步骤安装磁盘驱动安装网络驱动安装其他驱动测试网络 Harveste
  • SDU 程序设计思维实践 第四周 csp模拟

    文章目录 题目A 咕咕东的奇遇题意InputOutput 思路总结代码 题目B 咕咕东想吃饭题意InputOutput 思路总结代码 题目C 可怕的宇宙射线题意InputOutput 思路总结代码 题目A 咕咕东的奇遇 题意 咕咕东是个贪玩
  • 使用MySQL8.0 by docker

    MySQL8 0 by Docker 拉取镜像 span class token function docker span pull mysql 8 0 为了获取到对应的配置文件而 docker run span class token f
  • 国内安装oh-my-zsh

    zsh有华丽的外表 xff0c 使用便捷的特点 xff0c 但在国内网络环境中 xff0c 安装会存在困难 xff0c 使用zsh官网提供的脚本安装 xff0c 基本会安装失败 xff0c 会显示报访问错误 xff0c 在此提供使用Git安
  • 使用kubeKey快速搭建Kubernetes集群

    使用kubeKey快速搭建Kubernetes集群 文章目录 使用kubeKey快速搭建Kubernetes集群一 安装 kk二 初始化本地主机 xff08 官方没写 xff09 三 安装集群3 1 All in One 测试集群无配置文件
  • 使用docker运行mysql-client

    使用docker运行mysql client 由于服务器环境的限制的 xff0c 能少污染主机环境就尽量不污染 xff0c 在集群环境 xff0c 使用docker运行mysql cli 访问通过NodePort暴露的数据库就是一个不错的方
  • CentOS 快速安装Docker

    CentOS 快速安装Docker 下载及安装 yum span class token function install span span class token function wget span y span class toke
  • 使用Docker快速搭建MSSQL实验环境 (持久化)

    使用Docker快速搭建MSSQL实验环境 xff08 持久化 xff09 前置章节 CentOS 快速安装Docker 使用Docker快速搭建MSSQL实验环境 拉取镜像 span class token function docker
  • 使用Docker快速搭建Oracle实验环境(持久化)

    容器镜像系统用户root密码为 helowin su root helowin 运行及配置 仅限测试环境 1 拉取镜像 span class token function docker span pull registry cn hangz
  • SHELL内涵段子

    1 字符掩码 xff0c 过滤掉不需要的 Database span class token assign left variable DATABASE MASK span span class token operator 61 span
  • Shell中读取文本文件

    读取文本文件 基础范式 span class token function cat span filename span class token operator span span class token keyword while sp
  • MySQL有点用的Shell片段

    获取Table Schema mysql span class token parameter variable uroot span p span class token variable passwd span span class t
  • switch语句作用在byte上却不能作用在String和long上

    在switch xff08 exprl xff09 语句中 xff0c exprl必须是一个整数表达式或者枚举常量 而byte short char都可以隐式转换为int类型 xff0c 整数表达式可以是int或者包装类Integer xf
  • MySQL批量测试账号密码

    账号密码文件 user txt root pass 64 1234 root pass 64 1234 root pass 64 1234 root pass 64 1234 run sh span class token shebang
  • MySQL连接过慢优化

    在配置文件my cnf中加上skip name resolve span class token punctuation span mysqld span class token punctuation span span class to
  • stm32的GPIO口PA0按键没按下就是低电平的分析

    芯片 xff1a stm32f407ZET6X 功能 xff1a 实现两按键分别控制四个灯和一个蜂鸣器 思路 xff1a 将寄存器设置封装成函数 xff0c 体会固件库的实现原理 踩坑记录 xff1a 下载程序后发现与PA0连接的按键 xf
  • 正点原子f103新建工程模板——基于固件库

    编译器版本要选对 xff0c 1 xff0c 原来的MDK版本5 15 xff0c 使用的V5编译器 xff1b 新的MDK5 26使用的是V6编译器 xff1b 2 xff0c 在5 26版本下 xff0c ARM Compiler选择V
  • stm32f103-gpio源码理解

    提要 xff1a 参照野火的stm32f103开发指南 xff0c 对标准库的构造进行理解 xff1a xff08 1 xff09 使用结构体 xff0c 使用宏 xff0c 使用枚举 xff08 2 xff09 因为参数是可变的 xff0