惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 热门话题
Stack Overflow Blog
Stack Overflow Blog
B
Blog
WordPress大学
WordPress大学
Project Zero
Project Zero
P
Palo Alto Networks Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
有赞技术团队
有赞技术团队
S
SegmentFault 最新的问题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
T
Tailwind CSS Blog
Forbes - Security
Forbes - Security
F
Full Disclosure
SecWiki News
SecWiki News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hacker News: Ask HN
Hacker News: Ask HN
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs
Cisco Talos Blog
Cisco Talos Blog
G
Google Developers Blog
J
Java Code Geeks
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
O
OpenAI News
Spread Privacy
Spread Privacy
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Cybersecurity and Infrastructure Security Agency CISA
S
Securelist
V
Vulnerabilities – Threatpost
Y
Y Combinator Blog
IT之家
IT之家
U
Unit 42
腾讯CDC
S
Security Affairs
C
Cisco Blogs
Schneier on Security
Schneier on Security
The Last Watchdog
The Last Watchdog
B
Blog RSS Feed
宝玉的分享
宝玉的分享
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Security @ Cisco Blogs
Cyberwarzone
Cyberwarzone
T
The Blog of Author Tim Ferriss

博客园 - midhillzhou

windows 11关闭防火墙 以使得 外部的开发板可以主动发起ping通电脑 uboot中调试景略以太网phy JL3111A2-NA windows上excel运行macro之后出现错误 在linux上移植sgdisk 在linux上移植phytool + 调试tja1103 以太网phy 使用gdb调试user程序 之 某个线程的调用栈 在uboot中修改tja 1103以太网phy from slave to master porting perf性能观测工具 porting 开源memtester uboot 2020版本下gpio命令的使用 + linux下的libgpiod lib库的移植使用 ubi文件系统的 制作 + 挂载 + 若干问题 windows下outlook 撤回邮件 安装repo 使用lauterbach debug uboot之重定位 uboot中各种memory读写命令 uboot nand flash dump 环境变量 + 制作环境变量分区 + 代码结构详解 uboot bootm代码详解图 Beyond Compare 进行二进制文档的比对时,怎么去对齐(转载) notepad++分析log小技巧 使用继电器控制开发板上下电 uboot debug小技巧
i2c指令使用 + 仿照开源i2ctransfer实现的自己的i2ctransfer
midhillzhou · 2025-08-08 · via 博客园 - midhillzhou

1. 列出目前有哪些i2c controller

i2cdetect -l

image

2.查看某个特定i2c controller下面下挂的设备

i2cdetect -y 0

一般我们还会加上-r选项

其中0表示想要查看i2c controller的标号,可以改成命令i2cdetect -l 中列出所有的数字

image

3.通过i2c指令读取camera的温度

i2ctransfer -y 0 w2@0x36 0x4D 0x60 r2@0x36

image

其中0x36表示slave address

0x4d60表示摄像头温度的寄存器,由于我们要读取两个值,所以写的是r2, 这样我们就可以读取出0x4D60, 0x4D61两个连续的值。

可以这样理解 w2@0x36 0x4D 0x60,设置了 start point是0x4d60,然后往下读两个,即0x4D60 + 0x4D61两个位置的寄存器,加起来总共两个byte,一个整数部分,一个小数部分

转换成人类可读的温度的方法如下

0x4e52因为小于0xc000
HEX2DEC(0x4e)-50+HEX2DEC(0x52)/256=28.3203125
大于0xc000的值为零下,公式中的-50改为-142

上面的结果中 0x4e是寄存器0x4D60的值,0x52是寄存器0x4D61的值

image

 4.通过研究开源i2ctransfer的代码,自己实现的代码如下,这样其他上层app就可以用函数的形式 向底层发出i2c命令。

以等效于命令“i2ctransfer -y 0 w2@0x36 0x4D 0x60 r2@0x36” 来讲解如何调用下面的函数

slave_address: 0x36
reg_part1:0x4D
reg_part2:0x60
result, result_len: 2,用来存放返回的2个byte的数据

所以上层代码调用的示例代码如下

unsigned char *return_array[2];

zhongshan_i2c_transfer(0x36, 0x4D, 0x60, return_array, 2);

#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>
#include <fcntl.h>

int zhongshan_i2c_transfer(unsigned char slave_address, unsigned char reg_part1, unsigned char reg_part2, unsigned char *result, int result_len) {
    struct i2c_msg msgs[2];
    unsigned char *buf;
    struct i2c_rdwr_ioctl_data rdwr;
    int file, nmsgs_sent;

    file = open("/dev/i2c-0", O_RDWR);
    if (file < 0)
        printf("can not open /dev/i2c-0.");

    //construct write message.
    msgs[0].addr = slave_address;
    msgs[0].flags = 0;
    msgs[0].len = 2;
    buf = (unsigned char *)malloc(msgs[0].len);
    if (!buf)
        printf("Error: No memory for buffer\n");
    memset(buf, 0, msgs[0].len);
    msgs[0].buf = buf;
    msgs[0].buf[0] = reg_part1;
    msgs[0].buf[1] = reg_part2;

    //construct read message.
    msgs[1].addr = slave_address;
    msgs[1].flags = I2C_M_RD;   // #define I2C_M_RD        0x0001
    msgs[1].len = result_len;
    buf = (unsigned char *)malloc(msgs[1].len);
    if (!buf)
        printf("Error: No memory for buffer\n");
    memset(buf, 0, msgs[1].len);
    msgs[1].buf = buf;

    rdwr.msgs = msgs;
    rdwr.nmsgs = 2;
    nmsgs_sent = ioctl(file, I2C_RDWR, &rdwr);
    if (nmsgs_sent < 0) {
        printf("Error: Sending messages failed\n");
        return 1;
    } else if (nmsgs_sent < rdwr.nmsgs) {
        printf("Error: only %d/%d messages were sent\n", nmsgs_sent, rdwr.nmsgs);
        return 1;
    }
    
    result[0] = msgs[1].buf[0];
    if (result_len > 1)
        result[1] = msgs[1].buf[1];

    close(file);

    for (int i = 0; i < 2; i++)
        free(msgs[i].buf);

    return 0;
}