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

Pico使用C/C++选择使用哪个I2C控制器,以及SDA和SCL针脚

本文一开始讲述了解决方案,后面是我做的笔记,用来讲述我的发现流程和探究的 Pico I2C 代码结构。

前提知识

首先要说明一点:Pico 有两个 I2C,也就是两套 SDA 和 SCL。这点你可以在针脚图中名字看出,比如下图的 Pin 4 和 Pin 5是 I2C1 的,而默认的 Pin 6 和 Pin 7 是 I2C0 的。

请添加图片描述

默认情况下是只开启了第一个 I2C,也就是只有 I2C0 的针脚是可以使用的。如果这种情况下,你哪怕修改了针脚,但不是 I2C0 的,也是不会正常运行的。

如何选择哪个I2C控制器,以及SDA和SCL针脚

在设置之前声明三个变量或宏来方便开发。建议使用宏,这比较符合树莓派的开发风格:

#define I2C				i2c0
#define I2C_SDA_PIN 	4
#define I2C_SCL_PIN 	5

如果宏扩展出错,那么就使用变量。

然后初始化 I2C 的时候来设置使用哪个 I2C 控制器,以及哪个SDA和SCL针脚。下面是设置根据上面的设置,这里使用的是第一个 I2C 控制器,SDA 使用的是 GP4,SCL 使用的是 GP5,频率为1000000

i2c_init(I2C, 1000000);
gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA_PIN);
gpio_pull_up(I2C_SCL_PIN);

由于有两个 I2C 控制器,那么可以同时使用两套SDASCL针脚,但是要注意必须是I2C0I2C1的针脚,不能是同一个控制器的。

发现历程(选读)

这部分不一定要看。这里记录一下我是怎么知道是这样处理的,顺道了解了一下代码结构和信息传递的流程,万一以后需要就不用花时间翻来翻去了。

第一次尝试

首先分析一下:要定义针脚就要知道针脚这个值是如何被利用的,这样就可以知道如何传递处理这个值了。

一般是在初始化的时候设置使用哪个I2C控制器以及SDA和SCL针脚,代码一般如下:

i2c_init(i2c_default, CLK);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);

研究《用C/C++修改I2C默认的SDA和SCL针脚》的时候,我知道了默认针脚是在pico.h中配置的的,相关值有三个:PICO_DEFAULT_I2CPICO_DEFAULT_I2C_SDA_PINPICO_DEFAULT_I2C_SCL_PIN,那么只要追溯这三个值就行。

但是这样不好找,引用太多了。所以我就尝试了从另一方面先入手:I2C 是通过i2c_init()函数初始化的,如下:

i2c_init(i2c_default, SSD1306_I2C_CLK);

我需要的只有第一个参数i2c_default,因为这个参数传递了一些信息,第二个参数uint baudrate是传递速率的,和针脚无关。

那么i2c_init()函数的内容是什么呢?知道这个才能知道i2c_default的类型是什么结构,以及内部进行了什么处理。

i2c_init()函数声明在pico-sdk/src/rp2_common/hardware_i2c/i2c.c中,函数参数列表如下:

uint i2c_init(i2c_inst_t *i2c, uint baudrate) {i2c_reset(i2c);i2c_unreset(i2c);i2c->restart_on_next = false;i2c->hw->enable = 0;...// Re-sets i2c->hw->enable upon returning:return i2c_set_baudrate(i2c, baudrate);
}

那这个i2c_inst_t是个什么数据类型呢?我就继续找它。

pico-sdk/src/rp2_common/hardware_i2c/include/hardware/i2c.h的第 52 行可以看到它是i2c_inst结构体的重命名:

typedef struct i2c_inst i2c_inst_t;

那继续找结构体i2c_inst,这个结构体就在同一个文件里的第 135 行:

struct i2c_inst {i2c_hw_t *hw;bool restart_on_next;
};

终点还是第一个变量i2c_hw_t *hw,因为只有它可能会传递针脚的值,那就继续找i2c_hw_t是什么数据类型。

这个数据类型的声明在pico-sdk/src/rp2040/hardware_structs/include/hardware/structs/i2c.h中。换句话说,这个文件就是为i2c_hw_t结构体所准备的:

请添加图片描述

这个结构体存储了很多 I2C 的信息,但还是没找到针脚的信息,那么我就回到一开始在进行寻找。

第二次尝试

最开始我是寻找了i2c_init()的第一个参数的类型i2c_inst_t,收获不大。但是它的值我还没寻找,所以这次从参数值出发i2c_default,这个值是哪定义的呢?

在刚才发现i2c_inst_t声明和定义的pico-sdk/src/rp2_common/hardware_i2c/include/hardware/i2c.h头文件中发现了需要的东西(第 76 行):

#ifdef PICO_DEFAULT_I2C_INSTANCE
#define i2c_default PICO_DEFAULT_I2C_INSTANCE
#endif

这个PICO_DEFAULT_I2C_INSTANCE是什么呢?往上一瞅就能看到:

#if !defined(PICO_DEFAULT_I2C_INSTANCE) && defined(PICO_DEFAULT_I2C)
#define PICO_DEFAULT_I2C_INSTANCE (__CONCAT(i2c,PICO_DEFAULT_I2C))
#endif

在这里终于看到一个需要的值:PICO_DEFAULT_I2C,前文可知这个默认为0

这里的(__CONCAT(i2c,PICO_DEFAULT_I2C))是将i2cPICO_DEFAULT_I2C的值连接起来了,默认情况下也就是i2c0也就是说,参数i2c_default就是i2c0

这个技巧很不错,但是有些编译器用不了,比如我用 Clang x86_64-apple-darwin21.6.0 就无法扩展PICO_DEFAULT_I2C

再深入一些

但是这里的i2c0是什么呢?这是个什么类型的数据呢?

请添加图片描述

还是在pico-sdk/src/rp2_common/hardware_i2c/include/hardware/i2c.h头文件中(如上图)有这样一段:

#define i2c0 (&i2c0_inst) ///< Identifier for I2C HW Block 0
#define i2c1 (&i2c1_inst) ///< Identifier for I2C HW Block 1

可以看到i2c0i2c0_inst的地址,注释说这是I2C HW Block 0的标识符。从上面的

extern i2c_inst_t i2c0_inst;
extern i2c_inst_t i2c1_inst;

可以看到i2c0_insti2c1_inst是外部变量,类型是i2c_inst_t,这个类型之前我看到了定义的结构体:

struct i2c_inst {i2c_hw_t *hw;bool restart_on_next;
};

那这个i2c0_inst是在哪声明的?

这部分在pico-sdk/src/rp2_common/hardware_i2c/i2c.c中声明的:

i2c_inst_t i2c0_inst = {i2c0_hw, false};
i2c_inst_t i2c1_inst = {i2c1_hw, false};

这个i2c0_hw又是啥呢?在哪定义的呢?

这是在pico-sdk/src/rp2040/hardware_structs/include/hardware/structs/i2c.h中:

#define i2c0_hw ((i2c_hw_t *)I2C0_BASE)
#define i2c1_hw ((i2c_hw_t *)I2C1_BASE)

i2c0_hw表示((i2c_hw_t *)I2C0_BASE),意思是I2C0_BASE是个指向i2c_hw_t的指针,它的内容在pico-sdk/src/rp2040/hardware_regs/include/hardware/regs/addressmap.h中:

#define I2C0_BASE _u(0x40044000)
#define I2C1_BASE _u(0x40048000)

也就是说I2C0_BASE就是0x40044000,而i2c0_hw的地址就是0x40044000

补充一点,这里_()是无符号整数的意思,定义在pico-sdk/src/rp2040/hardware_regs/include/hardware/platform_defs

#ifndef _u
#ifdef __ASSEMBLER__
#define _u(x) x
#else
#define _u(x) x ## u
#endif
#endif

了解了蛮多知识,也希望能帮到有需要的人~

相关文章:

Pico使用C/C++选择使用哪个I2C控制器,以及SDA和SCL针脚

本文一开始讲述了解决方案&#xff0c;后面是我做的笔记&#xff0c;用来讲述我的发现流程和探究的 Pico I2C 代码结构。 前提知识 首先要说明一点&#xff1a;Pico 有两个 I2C&#xff0c;也就是两套 SDA 和 SCL。这点你可以在针脚图中名字看出&#xff0c;比如下图的 Pin 4…...

C++动态内存管理

动态内存 在C/C程序中&#xff08;线程&#xff09;栈空间是有限的&#xff0c;大部分变量使用的都是动态分配来的堆内存&#xff0c;这些动态申请来的堆内存是需要开发者通过代码去自行管理的。如何管理好这些动态申请来的内存&#xff0c;是C/C开发中的一个重点难点问题。 m…...

SpringBoot—日志

目录 日志使用日志日志级别设置日志级别设置分组指定日志文件路径日志切割归档使用第三方日志框架log4j2配置文件【分级存储】logback配置文件【分级存储】 实例代码 日志 使用日志 给controller添加日志信息 要给controller类上添加Slf4j注解&#xff0c;然后使用log.info(…...

如何在,Linux中安装Luajit2.*

1.文件下载The LuaJIT Project 2.将下载文件上传到对应的服务器&#xff1a;例如/opt 3.进入对应的文件夹 4.make PREFIX/usr/local&#xff0c;设置安装路径 5.make install&#xff0c;编译安装 6.进入安装目录&#xff0c;cd /usr/local/include/luajit-2.0 7.luajit -v…...

单片机-如何让数码管动态显示

数码管硬件图 1、数码管 连接 74HC245 芯片 单片机IO口输出难稳定&#xff0c;需要数码管与单片机连接需要增加驱动电路&#xff0c; 使用 74HC245 abcdefgDP并联导出 74HC245 对数码管进行驱动&#xff0c;P0 是输出电流 来驱动各个段的 驱动芯片 增加电阻 是为了防止电流…...

在Visual Studio 2017上配置并使用OpenGL

1 在Visual Studio 2017上配置并使用OpenGL 在GLUT - The OpenGL Utility Toolkit&#xff1a;GLUT - The OpenGL Utility Toolkit中点击“GLUT for Microsoft Windows 95 & NT users”&#xff0c;选择“If you want just the GLUT header file, the .LIB, and .DLL file…...

【C++】多态学习

多态 多态的概念与定义多态的概念构成多态的两个条件虚函数与重写重写的两个特例 final 和 override重载、重写(覆盖)、重定义(隐藏)的对比抽象类多态的原理静态绑定与动态绑定 单继承与多继承关系下的虚函数表(派生类)单继承中的虚函数表查看多继承中的虚函数表查看 菱形继承与…...

大数据之Maven

一、Maven的作用 作用一&#xff1a;下载对应的jar包 避免jar包重复下载配置&#xff0c;保证多个工程共用一份jar包。Maven有一个本地仓库&#xff0c;可以通过pom.xml文件来记录jar所在的位置。Maven会自动从远程仓库下载jar包&#xff0c;并且会下载所依赖的其他jar包&…...

自制centos7.9的wsl发行版

自制centos7.9的wsl发行版 参考&#xff1a;https://zhuanlan.zhihu.com/p/482538727 Windows10提供了一个wsl工具用于直接在windows上运行Linux子系统。 CentOS国内镜像下载&#xff1a;https://mirrors.aliyun.com/centos/ 这里选择了7.9.2009版本&#xff1a;https://mirr…...

使用VisualStudio制作上位机(五)

文章目录 使用VisualStudio制作上位机(五)第四部分:GUI界面数据显示使用VisualStudio制作上位机(五) Author:YAL 第四部分:GUI界面数据显示 这一部分,主要实现GUI的界面显示。 上一文已经实现了CAN数据的接收,并将数据更新到数组里。所以在做界面的显示时,只需要在…...

ChatGPT在医疗领域可应用于改善与患者的沟通

注意&#xff1a;本信息仅供参考&#xff0c;发布该内容旨在传递更多信息的目的&#xff0c;并不意味着赞同其观点或证实其说法。 自从ChatGPT在2022年末对公众开放以来&#xff0c;OpenAI的这款生成式AI聊天机器人在医疗领域展示出了巨大潜力。它已经通过了美国医学执照考试&a…...

直播预告|博睿学院第四季即将开讲:博睿数据资深运维团队现身说法!

博睿学院第四季开讲啦&#xff01;本季博睿学院的课程将于本周四&#xff08;8月31日&#xff09;16点正式启动。本季我们邀请到了博睿数据平台支撑中心的四位资深运维专家现身说法&#xff0c;来为我们分享一体化智能可观测平台Bonree ONE的实践干货。 他们&#xff0c;见多识…...

端到端自动驾驶综述

End-to-end Autonomous Driving: Challenges and Frontiers 文章脉路 Introduction 从经典的模块化的方法到端到端方法的一个对比, 讲了各自的优缺点, 模块化的好处是各个模块都有自己明确的优化的目标, 可解释性较强, 且容易debug, 缺点是各个模块优化的目标并不是最终的驾…...

mysql索引、事务、存储引擎

一、索引 索引的概念&#xff1a; 索引是一个排序的列表&#xff0c;在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址&#xff08;类似于C语言的链表通过指针指向数据记录的内存地址&#xff09;。使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是…...

【CMU15445】Fall 2019, Project 2: Hash Table 实验记录

目录 实验准备实验测试 实验准备 官方说明&#xff1a;https://15445.courses.cs.cmu.edu/fall2019/project2/ 实验测试 Task 1&#xff1a; mkdir build cd build make hash_table_page_test ./test/hash_table_page_testTask 2&#xff1a; make hash_table_test ./test…...

PMP证书是不是烂大街了?

大家都知道&#xff0c;PMP证书是项目管理领域的金字招牌。近年来&#xff0c;随着项目管理的重要性日益凸显&#xff0c;越来越多的人开始关注和学习PMP证书。无论是企业招聘还是个人职业发展&#xff0c;PMP证书都成为了一张炙手可热的敲门砖。 那么&#xff0c;PMP证书到底…...

Mac下Docker Desktop安装命令行工具、开启本地远程访问

Mac系统下&#xff0c;为了方便在terminal和idea里使用docker&#xff0c;需要安装docker命令行工具&#xff0c;和开启Docker Desktop本地远程访问。 具体方法是在设置-高级下&#xff0c; 1.将勾选的User调整为System&#xff0c;这样不用手动配置PATH即可使用docker命令 …...

Java实现根据商品ID获取京东商品详情数据,1688商品详情接口,1688API接口封装方法

要通过京东的API获取商品详情数据&#xff0c;您可以使用京东开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过京东开放平台API获取商品详情&#xff1a; 首先&#xff0c;确保您已注册成为京东开放平台的开发者&#xff0c;并创建一…...

element-plus指定el-date-picker的弹出框位置

此处记录一下,通过popper-options指定popper出现的位置...

游戏陪玩语音聊天系统3.0商业升级独立版本源码

首发价值29800元的最新商业版游戏陪玩语音聊天系统3.0商业升级独立版本源码 1、增加人气店员轮播 2、优化ui界面丨优化游戏图标展示丨优化分类展示 3、增加动态礼物打赏功能 4、增加礼物墙功能 增加店员满足业绩&#xff0c;才能升级功能 5、增加店员等级不同&#xff0c;…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...