当前位置: 首页 > news >正文

Linux学习笔记3-GPIO(1)

学习单片机时最开始也是从GPIO开始的,Linux的主芯片I.MX6UL124个GPIO,当然很多是复用的,与之对比,STM32F407系列的单片机GPIO口是112个。回顾之前单片机的学习,大部分的GPIO功能是通过HAL库函数调用的,例如HAL_GPIO_WritePin()HAL_GPIO_TogglePin()都是很方便的操作GPIO的库函数,编程者无需关心寄存器如何设置。那I.MX6UL有没有这种利器呢?答案是有的,NXP为这款主芯片开发了相应的库函数,可以在NXP的官网上下载SDK,有WIN版和LINUX版两种供选择,下载完之后安装,在安装文件夹下找到fsl_common.hfsl_iomuxc.hMCIMX6YH2.h,把这几个头文件复制到自己的工程文件夹里,就可以调用相关的库函数了。
我们还是从GPIO最简单的应用,点亮LED灯开始学习。由于GPIO的复用比较多,首先是选择复用哪个功能,使用IOMUXC_SetPinMux()这个函数,在fsl_iomuxc.h里可以看到函数定义,它一共有6个参数。

static inline void IOMUXC_SetPinMux(uint32_t muxRegister,uint32_t muxMode,uint32_t inputRegister,uint32_t inputDaisy,uint32_t configRegister,uint32_t inputOnfield)
{*((volatile uint32_t *)muxRegister) =IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);if (inputRegister){*((volatile uint32_t *)inputRegister) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy);}
}

实际用的时候,是这样的,IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0)。为什么6个参数变成了2个?因为在这个头文件里还定义了很多宏,这样来方便开发者调用,比如#define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U。通过这种调用开发者就不需要记寄存器啥的,很友好了。

同样在fsl_iomuxc.h里可以看到每个IO口的宏定义:

#define IOMUXC_GPIO1_IO03_I2C1_SDA                           0x020E0068U, 0x0U, 0x020E05A8U, 0x1U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_GPT1_COMPARE3                      0x020E0068U, 0x1U, 0x00000000U, 0x0U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_USB_OTG2_OC                        0x020E0068U, 0x2U, 0x020E0660U, 0x0U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_USDHC1_CD_B                        0x020E0068U, 0x4U, 0x020E0668U, 0x0U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_GPIO1_IO03                         0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_CCM_DI0_EXT_CLK                    0x020E0068U, 0x6U, 0x00000000U, 0x0U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_SRC_TESTER_ACK                     0x020E0068U, 0x7U, 0x00000000U, 0x0U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_UART1_RX                           0x020E0068U, 0x8U, 0x020E0624U, 0x1U, 0x020E02F4U
#define IOMUXC_GPIO1_IO03_UART1_TX                           0x020E0068U, 0x8U, 0x00000000U, 0x0U, 0x020E02F4U

可以看到GPIO1_IO03一共有9个复用功能,你要用哪个功能,选择这个功能的宏即可。

另外一个函数IOMUXC_SetPinConfig()的作用是设置GPIO口的IO属性,具体来看定义

static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,uint32_t muxMode,uint32_t inputRegister,uint32_t inputDaisy,uint32_t configRegister,uint32_t configValue)
{if (configRegister){*((volatile uint32_t *)configRegister) = configValue;}
}

可以看到前5个参数和IOMUXC_SetPinMux()是一模一样的,所以在使用时选择相应的宏即可。最后一个configValue参数就要看手册了,它其实就是设置GPIO的各种参数,例如上下拉、速度,还有一些和单片机不一样的参数,例如SRE(压摆率),代表从0到1需要多少时间,如果时间越小波形的斜率就越大,代表压摆率高,反之压摆率小。还有DSE,代表IO的驱动能力。这是我在chatgpt上问到的信息。

在 i.MX6UL 处理器中,DSE 代表的是 Drive Strength Field,即驱动强度字段。这是用来配置 GPIO 的一个参数,它控制输出驱动器的输出电流。不同的驱动强度设置可以影响 GPIO 引脚的输出电流和稳定性。

这个特性对我来说比较新,需要时间消化。
总之configValue对应的寄存器是IOMUXC_SW_MUX_CTL_PAD_GPIO1_IOXX(XX代表的是IO的号码),这是个32位寄存器,查询IMX6UL参考手册,可以看到这个寄存器的每位定义,它只有低17位有效,具体来看

16位HYS,使能迟滞比较器,当IO作为输入时有效,比较器的意思是即输入信号必须超过一个阈值才能将输出状态切换,并且在输入信号低于另一个较低的阈值时保持输出状态不变。0禁止,1使能
15-14位,上拉或下拉电阻设置,一共4种选择:00-100K欧的下拉;01-47K欧的上拉;10-100K欧的上拉;11-22K欧的上拉
13位:状态保持器,当IO作为输入时有效,为0时当外部电路断电以后此IO口可以保持住以前的状态,为1时使用上下拉
12位,使能或者禁止上下拉/状态保持器功能,为0时禁止,为1时使能
11位,当IO作为输出时有效,0:禁止开路输出;1:使能开路输出
10-8位保留,不用
7-6位,设置GPIO的速度,从00-11有4档可选,50MHz到200MHz
5-3位,上面说的DSE,000:禁止DSE功能;001:R0的阻值,3.3V下是260欧,1.8V下是150欧,接DDR时是240欧;010-111,分别把R0
的值设为001时R0值的1/2到1/7
2-1位保留,不用
0位,上面说的压摆率SRE,0为低压摆率,1为高压摆率

实际使用时,可以这么写函数IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10B0),按照上述的每位定义,这个0x010B0对应的就是

  • 禁止HYS
  • 100K欧下拉
  • 断电后IO口保持以前状态
  • 使能状态保持器
  • 禁止开路输出
  • 7-6位是10,150MHz速
  • DSE为110
  • 低压摆率

以上的学习针对的都是IO口的复用和相关参数设置,但并没有涉及到GPIO的属性,例如怎么设置输入输出,怎么设置高低电平值等等,这一块是怎么设置的呢?
另外,STM32单片机还需要初始化GPIO的时钟,还有中断,I.MX6UL的这些设置在哪里进行?

(未完待续)

相关文章:

  • 63基于matlab的生物地理的优化器(BBO)被用作多层感知器(MLP)的训练器。
  • Python---集合中的交集 、并集 | 与差集 - 特性
  • 基于单片机的塑料厂房气体检测系统设计
  • Java读取文件内容写入新文件
  • 深入理解 Django 单元测试
  • 企业大数据治理管理平台解决方案:PPT全文33页,附下载
  • 四、Vue3中使用Pinia解构Store
  • UML建模语言
  • Linux 安装与配置
  • SpringBoot 是什么
  • Python数据容器之[列表]
  • postman上传照片,视频,音频等上传文件操作测试方法
  • 【C#学习】backgroundWorker控件
  • Qt之qobject_cast使用
  • 媒体软文投放的流程与媒体平台的选择
  • [LeetCode] Wiggle Sort
  • 08.Android之View事件问题
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • 77. Combinations
  • mysql_config not found
  • mysql常用命令汇总
  • python3 使用 asyncio 代替线程
  • socket.io+express实现聊天室的思考(三)
  • Spring Cloud中负载均衡器概览
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • 如何编写一个可升级的智能合约
  • 我这样减少了26.5M Java内存!
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 阿里云ACE认证学习知识点梳理
  • 进程与线程(三)——进程/线程间通信
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​ssh免密码登录设置及问题总结
  • # 达梦数据库知识点
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (超详细)语音信号处理之特征提取
  • (第61天)多租户架构(CDB/PDB)
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (篇九)MySQL常用内置函数
  • (强烈推荐)移动端音视频从零到上手(上)
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (一)插入排序
  • (转)用.Net的File控件上传文件的解决方案
  • .gitattributes 文件
  • .net 设置默认首页
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .NET多线程执行函数
  • .net反编译的九款神器
  • .NET中GET与SET的用法
  • [ C++ ] STL---string类的使用指南
  • [ SNOI 2013 ] Quare
  • []指针
  • [Android学习笔记]ScrollView的使用
  • [asp.net core]project.json(2)