2.2.I2C编程实践
创始人
2024-06-02 05:32:09
0

linux内核I2C驱动代码中的一些重要结构体:

一般一条I2C总线上,主设备即I2C控制器,一般由i2c_adapter对其进行描述,一般有nr描述它是第几个I2C控制器(第几条总线),而大家都知道I2C控制器提供读写能力,它内部一定会有数据传输的函数(包含在i2c_algorithm算法结构体中)。

struct i2c_adapter {struct module *owner;unsigned int class;		  /* classes to allow probing for */const struct i2c_algorithm *algo; /* the algorithm to access the bus */void *algo_data;/* data fields that are valid for all devices	*/const struct i2c_lock_operations *lock_ops;struct rt_mutex bus_lock;struct rt_mutex mux_lock;int timeout;			/* in jiffies */int retries;struct device dev;		/* the adapter device */unsigned long locked_flags;	/* owned by the I2C core */
#define I2C_ALF_IS_SUSPENDED		0
#define I2C_ALF_SUSPEND_REPORTED	1int nr;char name[48];struct completion dev_released;struct mutex userspace_clients_lock;struct list_head userspace_clients;struct i2c_bus_recovery_info *bus_recovery_info;const struct i2c_adapter_quirks *quirks;struct irq_domain *host_notify_domain;
};
struct i2c_algorithm {/** If an adapter algorithm can't do I2C-level access, set master_xfer* to NULL. If an adapter algorithm can do SMBus access, set* smbus_xfer. If set to NULL, the SMBus protocol is simulated* using common I2C messages.** master_xfer should return the number of messages successfully* processed, or a negative value on error*/int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);int (*master_xfer_atomic)(struct i2c_adapter *adap,struct i2c_msg *msgs, int num);int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union i2c_smbus_data *data);int (*smbus_xfer_atomic)(struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union i2c_smbus_data *data);/* To determine what the adapter supports */u32 (*functionality)(struct i2c_adapter *adap);#if IS_ENABLED(CONFIG_I2C_SLAVE)int (*reg_slave)(struct i2c_client *client);int (*unreg_slave)(struct i2c_client *client);
#endif
};

而从设备也用到了一些结构体如i2c_client,它其中包括设备地址addr,以及它挂在哪条I2C总线上(在i2c_adapter *adapter中被记录)

struct i2c_client {unsigned short flags;		/* div., see below		*/
#define I2C_CLIENT_PEC		0x04	/* Use Packet Error Checking */
#define I2C_CLIENT_TEN		0x10	/* we have a ten bit chip address *//* Must equal I2C_M_TEN below */
#define I2C_CLIENT_SLAVE	0x20	/* we are the slave */
#define I2C_CLIENT_HOST_NOTIFY	0x40	/* We want to use I2C host notify */
#define I2C_CLIENT_WAKE		0x80	/* for board_info; true iff can wake */
#define I2C_CLIENT_SCCB		0x9000	/* Use Omnivision SCCB protocol *//* Must match I2C_M_STOP|IGNORE_NAK */unsigned short addr;		/* chip address - NOTE: 7bit	*//* addresses are stored in the	*//* _LOWER_ 7 bits		*/char name[I2C_NAME_SIZE];struct i2c_adapter *adapter;	/* the adapter we sit on	*/struct device dev;		/* the device structure		*/int init_irq;			/* irq set at initialization	*/int irq;			/* irq issued by device		*/struct list_head detected;
#if IS_ENABLED(CONFIG_I2C_SLAVE)i2c_slave_cb_t slave_cb;	/* callback for slave mode	*/
#endif
};

另外在i2c_algorithm并没有包含i2c_adapter结构体,那它又是如何找到设备地址信息的呢?这就得提到i2c_msg结构体了,其中包含了I2C设备的设备地址等信息。flag表示设备是读还是写。

struct i2c_msg {__u16 addr;	/* slave address			*/__u16 flags;
#define I2C_M_RD		0x0001	/* read data, from slave to master *//* I2C_M_RD is guaranteed to be 0x0001! */
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_DMA_SAFE		0x0200	/* the buffer of this message is DMA safe *//* makes only sense in kernelspace *//* userspace buffers are copied anyway */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */__u16 len;		/* msg length				*/__u8 *buf;		/* pointer to msg data			*/
};

总的来说就是,i2c_adapter与i2c_client间传输i2c_msg,并且i2c_adapter中有一个i2c_algorithm定义了一些传输函数。

i2c_transfer

有如下函数i2c_transfer:该函数会从i2c_adapter中找到根本的传输函数:algo.master_xfer进行调用,然后从i2c_msg中找到设备的设备地址以及设备读写标志位信息,num则是传输多少个数据消息。

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{int ret;if (!adap->algo->master_xfer) {dev_dbg(&adap->dev, "I2C level transfers not supported\n");return -EOPNOTSUPP;}/* REVISIT the fault reporting model here is weak:**  - When we get an error after receiving N bytes from a slave,*    there is no way to report "N".**  - When we get a NAK after transmitting N bytes to a slave,*    there is no way to report "N" ... or to let the master*    continue executing the rest of this combined message, if*    that's the appropriate response.**  - When for example "num" is two and we successfully complete*    the first message but get an error part way through the*    second, it's unclear whether that should be reported as*    one (discarding status on the second message) or errno*    (discarding status on the first one).*/ret = __i2c_lock_bus_helper(adap);if (ret)return ret;ret = __i2c_transfer(adap, msgs, num);i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);return ret;
}

I2C_Tools

源代码文件自取,这里用的是4.2版本的I2C_Tools

链接:https://pan.baidu.com/s/1iHfuwMQwFppnCzdmo76DQA 
提取码:1234 
 

访问硬件的方式最普遍的思路是通过编写自己的驱动程序进而访问I2C设备,而I2C_Tools可以直接对I2C控制器上的I2C设备进行访问,我们可以通过编写APP(应用程序)来操作I2C_Tools进而来访问I2C设备,对I2C设备进行驱动。

在这里,大家可以参考这位大佬的博客:【全志T113-S3_100ask】6-编写IIC驱动GY-302(twi)_t113 i2c_第四维度4的博客-CSDN博客

 在这里不多赘述,因为他写的真的很好,这里也主要是涉及一个操作的过程。

后续可能贴出I2C_Tools的命令:

i2cdetect //i2c检测命令
//命令示例:
i2cdetect -y 0 //检测第0号总线
i2cdetect -l   //列出设备中有多少条I2C总线

使用SMBus协议:

i2cset //I2C写操作命令(SMBus)命令示例:
i2cset -f -y 0 0x1e 0 0x4 //-f强制访问I2C设备,-y不提示是否访问,0号总线,0x1e设备地址,0号寄存器地址,写入0x4
i2cset -f -y 0 0x1e 0 0x3i2cget //I2C读操作命令(SMBus)命令示例:
i2cget -f -y 0 0x1e 0xc w //-f强制访问I2C设备,-y不提示是否访问,0号总线,0x1e设备地址,0xc寄存器地址,w模式(read word data读取两个字节),b模式(read byte data读取一个字节),c模式(write byte/read byte)

 使用I2C协议:

i2ctransfer//I2C写操作命令使用示例:
i2ctransfer -f -y 0 w2@0x1e 0 0x4 //-f强制访问I2C设备,-y不提示是否访问,0号总线,w2@0x1e为描述符,w是写操作,表示写两个字节,0x1e是设备地址,0号寄存器,写入0x4i2ctransfer//I2C读操作命令使用示例:
i2ctransfer -f -y 0 w1@0x1e 0xc r2 //-f强制访问I2C设备,-y不提示是否访问,0号总线,w1@0x1e为描述符,w是写操作,表示写1个字节,0x1e是设备地址,0xc寄存器地址,r2读出两个字节,(因为读取数据需要指定寄存器地址,所以需要先写才能读)

基于I2C_Tools编写I2C驱动程序

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "i2cbusses.h"
#include //应用程序的使用格式
/* ./at24c02  w "100ask.taobao.com"* ./at24c02  r*/int main(int argc, char **argv)
{unsigned char dev_addr = 0x50;//设备地址,在这里是以AT24C02为例,且A1,A2,A3都接地设备地址为1010000=0x50unsigned char mem_addr = 0;//存储空间的地址,从0开始读unsigned char buf[32];//数据缓冲区int file;char filename[20];unsigned char *str;int ret;struct timespec req;//如果用户输入的参数不正确,则打印一下用法if (argc != 3 && argc != 4){printf("Usage:\n");printf("write eeprom: %s  w string\n", argv[0]);printf("read  eeprom: %s  r\n", argv[0]);return -1;}//打开I2C设备file = open_i2c_dev(argv[1][0]-'0', filename, sizeof(filename), 0);if (file < 0){printf("can't open %s\n", filename);return -1;}if (set_slave_addr(file, dev_addr, 1)){printf("can't set_slave_addr\n");return -1;}//如果第二个参数是wif (argv[2][0] == 'w'){// write str: argv[3]str = argv[3];req.tv_sec  = 0;req.tv_nsec = 20000000; /* 20ms */while (*str){// mem_addr, *str// mem_addr++, str++ret = i2c_smbus_write_byte_data(file, mem_addr, *str);if (ret){printf("i2c_smbus_write_byte_data err\n");return -1;}// wait tWR(10ms)nanosleep(&req, NULL);mem_addr++;str++;}ret = i2c_smbus_write_byte_data(file, mem_addr, 0); // string end charif (ret){printf("i2c_smbus_write_byte_data err\n");return -1;}}else{// readret = i2c_smbus_read_i2c_block_data(file, mem_addr, sizeof(buf), buf);if (ret < 0){printf("i2c_smbus_read_i2c_block_data err\n");return -1;}buf[31] = '\0';printf("get data: %s\n", buf);}return 0;}

因为编译是用到了别的依赖库,光是上面的代码无法运行,完整代码如下:

链接:https://pan.baidu.com/s/1vGiLMWplEYwmkx2X8otLUQ 
提取码:1234 
 

相关内容

热门资讯

江西第一封高考录取通知书送达!... 来源:江南都市报 江南都市报全媒体记者章娜前几日,江西省教育考试院发布了2025年普通高校招生提前本...
大城县举办听力健康公益义诊活动  栏目名称:《廊坊新闻》首播频道:新闻综合频道首播时间:19:40重播时间:22:00 次日10:0...
恋爱谈多久,可以谈婚论嫁? 恋爱谈多久,可以谈婚论嫁?大半年。这样的时间是很合理的。可以让你了解对方,可以保证婚姻的稳定。两年左...
一年关店1078家!这个曾经暴... 来源:品牌观察官营收涨了、利润也涨了,但门店却“哗哗”关掉了上千家!曾经门店狂飙、开店比便利店还快的...
资深专业机构投资者认定标准细化...   7月13日,上交所发布《发行上市审核规则适用指引第8号——资深专业机构投资者》(简称《资深专业机...
清凉书海度盛夏,南京江北图书馆... 转自:扬子晚报七月的周末热浪翻涌,南京江北图书馆内却坐满了读者,近2000个阅览座席在一座难求。家长...
我国最大盆地,超高压电力环网贯... 转自:中国能源报4197公里“能量环”!我国最大盆地超高压电力环网贯通。历时15年建设,总长4197...
上交所就发布实施进一步深化科创...   来源:上交所发布  为了落实《中国证监会关于在科创板设置科创成长层 增强制度包容性适应性的意见》...
集齐王牌开战!马斯克Space... 当地时间周六,马斯克旗下航天公司SpaceX向xAI注资20亿美元的消息传出,这已是马斯克近期在AI...