通过GPIO探究STM32F10x的寄存器与函数_2021-04-24

2023-11-12

 

 

通过GPIO探究STM32F10x的寄存器与函数

 

 

将地址用标识符定义出来可以增加可读性

/*	定义引脚	*/
#define GPIO_PIN_0 	((uint16_t)0x0001)
#define GPIO_PIN_1 	((uint16_t)0x0002)
#define GPIO_PIN_2 	((uint16_t)0x0004)
#define GPIO_PIN_3 	((uint16_t)0x0008)
#define GPIO_PIN_4 	((uint16_t)0x0010)
#define GPIO_PIN_5	((uint16_t)0x0020)
#define GPIO_PIN_6 	((uint16_t)0x0040)
#define GPIO_PIN_7 	((uint16_t)0x0080)
#define GPIO_PIN_8 	((uint16_t)0x0100)
#define GPIO_PIN_9 	((uint16_t)0x0200)
#define GPIO_PIN_10 ((uint16_t)0x0400)
#define GPIO_PIN_11 ((uint16_t)0x0800)
#define GPIO_PIN_12 ((uint16_t)0x1000)
#define GPIO_PIN_13 ((uint16_t)0x2000)
#define GPIO_PIN_14 ((uint16_t)0x4000)
#define GPIO_PIN_15 ((uint16_t)0x8000)
#define GPIO_PIN_ALL ((uint16_t)0xFFFF)

函数的作用是对寄存器操作,知道对应寄存器的地址就能直接对寄存器操作 

#define _D *(unsigned int*) //强制转换为地址指针后再用*去访问
	
#define GPIOA_Base 0x40010800
#define GPIOB_Base 0X40010C00
#define GPIOC_Base 0x40011000

#define RCC_APB2_Base 0x40021000

	


int main()
{
	_D (RCC_APB2_Base+0x18) |= (0x1<<2); 	//ABP2外部时钟GPIOA使能
	_D GPIOA_Base &= (0x0F<<16);	//清空Pin4配置
	_D GPIOA_Base |= (0x11<<16);	//Pin4输出模式
	_D (GPIOA_Base+0x0C) |= (1<<4);	//Pin4高电平
	
}

 

如果寄存器在地址上是连续的可以巧妙的应用结构体来定义对应的寄存器,结构体的地址就是结构体首个成员变量的地址,确定了首地址成员变量的地址也就一一对应了,

typedef struct
{
	uint32_t CRL;
	uint32_t CRH;
	uint32_t IDR;
	uint32_t ODR;
	uint32_t BSRR;
	uint32_t BRR;
	uint32_t LCKR;
	
}GPIO_TypeDef;

这样做的好处在于可以直接通过结构体访问寄存器 

	RCC->APB2ENR |= 1<<2;        //使能GPIOA时钟
	GPIOA->CRL &= ~(0x0F<<20);	//清空Pin4配置
	GPIOA->CRL |= 0x11<<20;		//Pin4输出模式
	GPIOA->ODR |= 0x01<<4;		//Pin4输出高电平

对于寄存器的位上的参数也可以用枚举来定义

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_MDOE_AF_OD = 0x1C,
	GPIO_MODE_AF_PP = 0x18,
	
	
}GPIOMODE_TypeDef;

 进一步封装得到了GPIO初始化结构体的原形

typedef struct 
{
	uint16_t GPIO_PIN;
	GPIOMODE_TypeDef GPIO_MODE;
	GPIOSPEED_TypeDef GPIO_SPEED;
	
}GPIO_InitTypeDef;

接下来要将数据写入到寄存器需要一个函数来处理,这需要熟悉参考手册

void GPIO_Init(GPIO_TypeDef* GPIOx,GPIO_InitTypeDef* GPIOx_InitStructure)
{
	uint32_t pinpos=0x00,pos=0x00,currentpin=0x00,currentmode=0x00;
	uint32_t tmpreg=0x00,pinmask=0x00;
	/*---------------------------GPIO模式配置------------------------*/
	currentmode |= (uint32_t)GPIOx_InitStructure->GPIO_MODE&0x0F;//保留mod低四位
	//判断bit4是0还是1,即输入还是输出
	if(((uint32_t)GPIOx_InitStructure->GPIO_MODE&(uint32_t)0x10) != 0)
	{
		currentmode |= (uint32_t)GPIOx_InitStructure->GPIO_SPEED;//如果是输出要设置速度
	}
	
	/*------------------------判断是否为低8位-----------------------*/
	if(((uint32_t)GPIOx_InitStructure->GPIO_PIN  & (uint32_t)0x00FF) != 0)
	{
		tmpreg = GPIOx->CRL;//保存GPIOx低位值配置的值
		
		for(pinpos = 0x00;pinpos < 0x08;pinpos++)//找出具体的Pin
		{
			pos = (uint32_t)1<<pinpos;
			currentpin = GPIOx_InitStructure->GPIO_PIN & pos;//为下面配对pin做准备
			
			if(currentpin == pos)
			{
				pos = pinpos<<2;					//对应Pin值,每4位操作一个pin
				pinmask = ((uint32_t)0x0F)<<pos;	//写入清空位值
				tmpreg &= ~pinmask;					//清空操作位,其他位不变
				tmpreg |= (currentmode<<pos);		//向寄存器写入要配置的引脚模式
				if(GPIOx_InitStructure->GPIO_MODE == GPIO_MODE_IPD)//判断是否为下拉输入模式
				{
					//BRR置1
					GPIOx->BRR = (((uint32_t)0x01)<<pinpos);
				}
				if(GPIOx_InitStructure->GPIO_MODE == GPIO_MODE_IPU)//判断是否为上拉输入模式
				{
					//BSRR置1
					GPIOx->BSRR = ((uint32_t)0x01<<pinpos);
				}
				
			}
			
		}
		
		GPIOx->CRL = tmpreg;
	}
	
	
	/*---------------------判断是否为高位----------------------------*/
	if(GPIOx_InitStructure->GPIO_PIN > 0x00FF)
	{
		tmpreg =GPIOx->CRH;
		for(pinpos=0x00;pinpos<0x08;pinpos++)
		{
			pos = ((uint32_t)0x01)<<(pinpos + 0x08);
			currentpin = ((GPIOx_InitStructure->GPIO_PIN) & pos);
			if(currentpin == pos)
			{
				pos = pinpos<<2;
				pinmask = ((uint32_t)0x0F)<<pos;
				tmpreg &= ~pinmask;
				tmpreg |= (currentmode<<pos);
				if(GPIOx_InitStructure->GPIO_MODE == GPIO_MODE_IPD)
				{
					GPIOx->BRR = ((uint32_t)0x01)<<(pinpos + 0x08);
				}				
				if(GPIOx_InitStructure->GPIO_MODE == GPIO_MODE_IPU)
				{
					GPIOx->BSRR = ((uint32_t)0x01)<<(pinpos + 0x08);
				}
				
			}
			
		}
		
		GPIOx->CRH = tmpreg;
	}
}

诸如此类的寄存器都是如此封装成函数来操作

根据函数的作用将函数大致可以分为三种

  1. 初始化函数GPIO_Init\GPIO_DeInit\GPIO_AFIODeInit\GPIO_AFIODeInit
  2. 功能函数GPIO_Writ\...
  3. 控制函数GPIO_PinLockConfig\GPIO_EventOutputCmd\GPIO_PinRemapConfig\GPIO_EXTILineConfig...

 

 

 

 

 

 

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过GPIO探究STM32F10x的寄存器与函数_2021-04-24 的相关文章

  • U-Boot初始化及工作流程分析

    0 概述 U Boot通常是从架构相关的汇编文件 尾缀为大写S的汇编文件意为可链接 中获取第一条执行的指令 例如 arch arm cpu armv7 start S arch powerpc cpu mpc83xx start S arc
  • 如何实现弹窗一天只弹一次的需求

    你是否有这种需求 页面需要对用户有一个信息提示的弹窗 但是为了骚扰次数过多导致用户的反感于是产品要求一天只弹一次 服务器显需求太小懒得搭理 于是 重任 就落在你的头上 跟我来 一招搞定一天一次的弹窗 解决思路是 进页面的时候判断如果本地没保

随机推荐

  • Matlab常用字符串操作教程

    Matlab是一种功能强大的编程语言 它提供了丰富的字符串操作函数 在本教程中 我们将介绍一些常用的Matlab字符串操作函数和用法 字符串的创建和访问 使用单引号或双引号创建字符串 str Hello World 或 str Hello
  • 入职阿里工作5年,晋升到P8就剩这份学习笔记了,已帮助多个朋友拿到Offer

    关于程序员 除了做项目来提高自身的技术之外 还有一种提升自己的专业技能就是 多 看 书 入职阿里到现在已经5年了 工作压力大 节奏快 从刚开始的P6到现在的P8 技术上确实得到了成长 尤其是当你维护与大促相关的系统的时候 熬到P8也费了不少
  • vue3使用element组件中的Image导致频闪

    只需要把el image标签换成原生img标签就可以了
  • arma3服务器滚动信息,【图片】武装突袭3服∷务器状态信息查询 - 接口/模块/JАVa-机器人_武装突袭3吧_百度贴吧...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 然后是java如何使用接口 以下文档仅供参考 已字符防和谐处理 GetXMLtoServerPlayer GSP new GetXMLtoServerPlayer 得到玩家信息 String S
  • python format 冒号_python之格式化输出

    字符串格式化有两种方式 和format 先介绍下 号的方法 s的语法结构 叫做占位符 就是先占一个位置 然后我们用真实的要显示的数据替换占位符即可 最简单的用法就是下面的方式 其实 s还有其他的功能 s 我的名字是 s 我的年龄是 d al
  • xss-labs通关参考(7-10)

    7 第七关 先提交 Oonn gt 查看源代码 过滤了script 和On 双引号闭合 所以payload oONnmouseover alert xss 8 第八关 先提交 Oonn gt 查看源代码 发现 script和on中间都被加上
  • [leetcode] 437. Path Sum III 解题报告

    题目链接 https leetcode com problems path sum iii You are given a binary tree in which each node contains an integer value F
  • 传输线理论--学习笔记

    1 1传输线方程及其通解 下图为双导线的集总电路模型 在一个微分段内 双导线可以等效集总电路模型 的模型怎么来的 gt 双导线的射频效应 导体损耗 趋肤效应 单位长度串联电阻R0 介质损耗 两根导线之间有介质 如空气 单位长度并联电导G0
  • 第一届排序算法性能大赛(上万字激烈解说)

    写在前面 最近学到了一些重要的排序 并且简单地测了一下各种排序算法在不同的算法实现 优化以及递归和非递归下的运行速度 本文一共提及了以下几种常用到的排序 其他排序使用场景较少 便没有提及 并且本文的全部代码实现均为通俗易懂的c语言 如果觉得
  • Flink Table API & SQL - 概念和通用API

    Table API 和 SQL 集成在一个 API 中 这个 API 用作查询 输入和输出的表 本文档展示了带有 Table API 和 SQL 查询的程序的公共结构 如何注册表 如何查询表以及如何写入表 目录 两个Planner之间的主要
  • shell运行class文件 导入class依赖的jar包

    shell脚本运行class文件导入class依赖的jar包 如下图 我要用shell运行TestFinish类 类中引入了rt jar包 在shell中怎么引入rt jar包呢 很简单只要三步就可以运行了 1 javac cp rt ja
  • win10无法登陆到你的账户解决方法

    进入win10系统登录的时候很多用户遇到了win10无法登陆到你的账户情况 这种问题都会需要来进行重新设置 来看看怎么解决这个无法登录问题吧 更多重装系统教程尽在小白系统重装官网 1 首先我们需要进入win10系统安全模式 安全模式进入方法
  • 【IIOT】欧姆龙PLC数采之NX/NJ系列

    IIOT 欧姆龙PLC数采之NX NJ系列 前言 一 车间级数采系统架构 二 欧姆龙PLC介绍 三 NX NJ系列产品说明 3 1 CPU规格 3 2 内部寄存器 3 3 支持协议 四 数采方案 4 1 选择协议 4 2 硬件架构 1 确认
  • 防页面url缓存

    在开发中 发现当我们访问一个地址之后 包括ajax访问 打开检测会发现第二次请求没有去服务器端 直接走的浏览器自身的缓存 如何避免这样的情况呢 通过在地址栏后拼一串随机数 即可 例如 XXXX t 生成的随机数 随机数可以跟时间戳 或者随机
  • Vue+el-table+sortable踩坑

    1 拖拽后 同页面切换tab 表格数据更新 表头显示顺序有误 拖拽 1 2 3 2 1 3 更新后为 5 4 6 应为 4 5 6 原代码
  • Kendo UI开发教程(26): 单页面应用(四) Layout

    Layout继承自View 可以用来包含其它的View或是Layout 下面例子使用Layout来显示一个View 1
  • matplotlib绘制直方图

    统计250部电影的时长分布状态 from matplotlib import pyplot as plt from matplotlib import font manager time 131 98 125 131 124 139 131
  • MySQL之 表

    表是关于特定实体的数据集合 这也是关系型数据库模型的核心 1索引组织表 在InnoDB存储引擎中 每张表都有一个主键 Primary Key 如果创建表时没有显示定义主键 则会按照如下方式创建主键 存在非空的唯一索引 Unique NOT
  • html回到顶部的特效

    html代码 div class istop a href self 返回顶部 a div js代码 function istop click function html body animate scrollTop 0 500
  • 通过GPIO探究STM32F10x的寄存器与函数_2021-04-24

    通过GPIO探究STM32F10x的寄存器与函数 将地址用标识符定义出来可以增加可读性 定义引脚 define GPIO PIN 0 uint16 t 0x0001 define GPIO PIN 1 uint16 t 0x0002 def