自学STM32---GPIO

2023-11-04

1、STM32有5组GPIO引脚,分别是GPIOA,GPIOB,GPIOC,GPIOD,GPIOE,每组GPIO有16个引脚。
2、每个引脚都有4个位来配置其端口,可以配置出不同的输入\输出模式
表1配置IO口输出方式

配置模式 CNF1 CNF2 M1  M0 

推挽式输出 0   0 1 1 50MHz速度

开漏输出 0 1   0   1 10MHz速度

复用推挽式输出 0 0 1 0 2MHz速度
复用开漏输出 1 1 1 1 50MHz速度
模拟输入 0 0   0    0
浮空输入 0 1   0    0
下拉输入 1 0   0   0  
上拉输入 1 1  0    0  

M0 M1 输出速度 0  1   10MHz ;   1     0   2MHz;   1     1   50MHz
3、GPIOA->CRL(32位) 是用来配置低8个引脚的,GPIOA->CRH(32位) 是用来配置高8个引脚的。配置方式见参考手册
4、GPIOA->IDR(32位,只用到低16位配置对应16个引脚)是用来配置端口输入数据寄存器的(外设->MCU)。
5、GPIOA->ODR(32位,只用到低16位配置对应16个引脚)是用来配置端口输出数据寄存器的(MCU->外设)。
6、用软件仿真的时候,如果在一个引脚给如一个高电平,只能在Pins相应的位打上√(看程序里的第3次课代码调试)
7、位运算主要有&  |  ~(取反)  <<  >>  ^(异或)  等操作,因为都是针对寄存器编程,寄存器的引脚状态就0和1,所以一般用位运算。STM32不同于51和其他单片机,它内部有集成了2个对位运算的寄存器(BSRR对某一位置1,BRR对某一位清0)。这样运算的速度快,代码量少,效率高出很多倍。(具体见GPIO程序第4节课的例子)。(位运算与或的作用,清0,置1,隐藏)。
8、位绑定 把某一位映射到内存地址上,对地址的最低位进行操作来把引脚这一位给置1和清0.
位n 映射 内存地址a
n = 0/1 a = 0 2 4 8(最低位为0)/1 3 5 7(最低位为1)
传统置1和清0需要3步完成,读  修改  写
只有STM32以下2个区的位才可以进行位绑定(可以看参考手册2.3节内存分布图)
SRAM区 0x2000 0000~ 0x200f ffff 1M(20位,2~20=1M)(n = 0~7,A=0x2000 0000~0x200f ffff)
公式:AliasAddr = 0x22000000 + ((A-0x2000 0000)*8 +n)*4
      = 0x22000000 + (A-0x2000 0000)*32 +n*4
片上外设 0x4000 0000~ 0x400f ffff 1M  (n = 0~31,A=0x4000 0000~0x400f ffff)
公式:AliasAddr = 0x42000000 + ((A-0x4000 0000)*8 +n)*4
      = 0x42000000 + (A-0x4000 0000)*32 +n*4
  例子:把GPIOA的6位作为输出,GPIOA的14位作为输入,用位绑定的方式对其进行位操作
//A = GPIOA_BASE + ODR偏移地址 = GPIOA_BASE + 0x0c      n = 6
//A = GPIOA_BASE + IDR偏移地址 = GPIOA_BASE + 0x08        n = 14
//AliasAddr = 0x42000000 + (A-0x4000 0000)*32 +n*4
u32 *PAO6 = (u32 *) (0x42000000 + (0x4001080c - 0x40000000)*32 + 6*4);0c为输出的偏移地址(手册),第6位n=6
u32 *PAI14 = (u32 *) (0x42000000 + (0x40010808 - 0x40000000)*32 + 14*4);08为输入的偏移地址(手册),第14位n=14

if (*PAI14 == 1) *PAO6 = 1;//1也可以换成其他的奇数,只要满足最低位为1
else *PAO6 = 0;//0也可以换成其他的偶数,只要满足最低位为0

/***通用位绑定GPIO端口****/
#define GPIOA_ODR_A  (GPIOA_BASE+0x0c)
#define GPIOA_IDR_A  (GPIOA_BASE+0x08)
#define GPIOA_ODR_B  (GPIOB_BASE+0x0c)
#define GPIOA_IDR_B  (GPIOB_BASE+0x08)
#define GPIOA_ODR_C  (GPIOC_BASE+0x0c)
#define GPIOA_IDR_C  (GPIOC_BASE+0x08)
#define GPIOA_ODR_D  (GPIOD_BASE+0x0c)
#define GPIOA_IDR_D  (GPIOD_BASE+0x08)
#define GPIOA_ODR_E  (GPIOE_BASE+0x0c)
#define GPIOA_IDR_E  (GPIOE_BASE+0x08)
位绑定的指定位的地址中的值 绑定的地址的类型    取地址最高位(2或4)   次高位   取低5位并*32    相应的位n*4
#define BitBand(Addr,BitNum) *(volatile unsigned long *)((Addr & 0xf0000000) + 0x2000000+ ((Addr & 0xfffff)<<5) + (BitNum<<2))
//在MCU运算处理器中,位运算比乘法运算要快(左移n等价于乘以2~n;右移n位等价于除以2~n),volatile关键字的作用是告诉编译器,这处的代码不需要
//去优化它,直接从源头处去读取就行了。

#define PAout(n)   BitBand(GPIOA_ODR_A,n)
#define PAin(n)    BitBand(GPIOA_IDR_A,n)
#define PBout(n)   BitBand(GPIOB_ODR_B,n)
#define PBin(n)    BitBand(GPIOB_IDR_B,n)
#define PCout(n)   BitBand(GPIOC_ODR_C,n)
#define PCin(n)    BitBand(GPIOC_IDR_C,n)
#define PDout(n)   BitBand(GPIOD_ODR_D,n)
#define PDin(n)    BitBand(GPIOD_IDR_D,n)
#define PEout(n)   BitBand(GPIOE_ODR_E,n)
#define PEin(n)    BitBand(GPIOE_IDR_E,n)

/****操作测试****/
if(PAin(14) == 1) PAout(6) = 1;
else PAout(6) = 0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自学STM32---GPIO 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐