目录
2.2 i2c_add_numbered_adapter()
六、I2C从设备的驱动层的i2c_driver
一、i2c简介
IIC通信有两个线:
一根数据线(SDA) 一根时钟(SCL)
总线物理拓扑:
电容按键--语音模块--AT24C02 符合IIC通信都可以I2C子系统 IIC--同步半双工
主机:
芯片
从机:
外部设备
上拉电阻作用:
1、保护器件 2、当SCL SDA空闲是高电平 3、阻抗(阻抗匹配)
注意:
1、只能由主机发起起始条件(启动数据传输)和停止条件(结束数据的传输)。时钟总线只能有主机控制。
2、传输的基本单位是字节(1个字节),(MSB)高位在前,低位在后(LSB)。
3、每当发送方传输一个字节的数据(8个位),接收方就会产生一个应答信号(ACK位低电平),如果接收方不想继续接收数据,则产生一个非应答信号(ACK位高电平)。
4、每个从设备有唯一的I2C地址,分为两种:7位地址和10位地址(不常用),注意:同一条总线上从设备地址是不同的。
5、主机向从机发起数据传输的请求,必须指定从机的I2C地址和数据传输方向(方向位),对于7位地址来说,I2C的地址在高7位,方向位是最低位,两者组成一个字节的数据。
6、方向位为低电平(方向位为0的时候),表示主机向从机写数据,此时主机是发送方,从机接收方;方向是高电平(1),表示主机向从机读取数据,此时主机是接收方,从机是发送方。
二、操作方法
(1)主设备向从设备中写数据(主机发送数据给从机)。数据传输格式如下:(主机给从机发送数据)
(2)主设备向从设备读取数据(主机请求从机,从机发送数据给主机)。数据传输格式如下:(从机给主机发送数据)
(3)主设备向从设备中写数据,然后重启起始条件,紧接着向从设备中读取数据;或者主设备向从设备读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下:
补充注意事项:第三种在单个主设备系统中,重复的开启起始条件机制要比用STOP终止传输后又再次开启更有效率。
总结:
1、一组I2C总线上只能有1个主机,第一个从机用不同的I2C地址(通常为7位)区分。
2、主机可以读或写从机,用方向位区分读还是写。方向位默认为1表示读,方向位0表示写。
3、一次传输8个比特,一个字节。
三、I2C子系统的框架
3层的基本作用:
(1)i2c设备驱动层:描述从机信息和驱动方式,注册字符设备,提供操作接口给应用层,与应用层交互数据,但是需要调用i2c_adapter层提供的I2C总线发送和接收数据的方法。
(2)I2C核心层:将从机挂载到请求的主机总线上; 维护i2c driver和i2c client 链表 ,实现i2c_client和i2c_driver匹配。
(3)I2C适配层:初始化I2C控制器(适配器),实现i2c时序,实现i2c总线发送和接收数据的方法。
四、I2C适配器层
1.核心数据结构(名字)
struct i2c_adapter{ //i2c适配器的抽象
unsigned int class; //设备分类
const struct i2c_algorithm *algo; //i2c总线发送和接收数据的方法(对数据线和时钟线的操作)
void *algo_data; //i2c总线发送和接收数据的方法可能用到的参数(某个对象的地址)--可以用来进行数据传递
int nr; //i2c物理总线的编号(如i2c0编号通常为0 i2c1编号1)
.....
};
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
* with the access algorithms necessary to access it.
*/
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 */
struct rt_mutex bus_lock;
int timeout; /* in jiffies */
int retries;
struct device dev; /* the adapter device */
int nr; //总线的编号
}
2.相关函数或宏
2.1 i2c_add_adapter()
头文件:
#include <linux/i2c.h>
原型:
int i2c_add_adapter(struct i2c_adapter *adap)
功能:
注册指定的i2c_adapter对象,动态分配该i2c_adapter的总线编号nr成员
参数:
adap:已经定义好的i2c_adapter对象的地址
返回值:
成功:0
失败:负数
内核源码的基本形式:
/**
* i2c_add_adapter - declare i2c adapter, use dynamic bus number
* @adapter: the adapter to add
* Context: can sleep
*
* This routine is used to declare an I2C adapter when its bus number
* doesn't matter or when its bus number is specified by an dt alias.
* Examples of bases when the bus number doesn't matter: I2C adapters
* dynamically added by USB links or PCI plugin cards.
*
* When this returns zero, a new bus number was allocated and stored
* in adap->nr, and the specified adapter became available for clients.
* Otherwise, a negative errno value is returned.
*/
int i2c_add_adapter(struct i2c_adapter *adapter)
{
struct device *dev = &adapter->dev;
int id;
if (dev->of_node) {
id = of_alias_get_id(dev->of_node, "i2c");
if (id >= 0) {
adapter->nr = id;
return __i2c_add_numbered_adapter(adapter);
}
}
mutex_lock(&core_lock);
id = idr_alloc(&i2c_adapter_idr, adapter,