I2C

1:
       i2c总线(串行总线),用于CPU与外设直接进行通信。只有两条线:数据线SDA总线),用于CPU与外设直接进行通信。只有两条线:数据线SDA, 控制线SCL。 具有简单性,有效性,"最主要优点"是:多主控,即可以连接多个设备,但同一时刻只有一个设备成为主设备与CPU通信。为主设备时,可以自己控制当前总线的时钟频率及数据传输。

2:

2.1 总线的构成及信号类型 
       I2C 总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,最高传送速率 100kbps。各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,在信息的传输过程 中,I2C总线上并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能。CPU发出的控制信号分为地址码和控制 量两部分,地址码用来选址,即接通需要控制的电路,确定控制的种类;控制量决定该调整的类别(如对比度、亮度等)及需要调整的量。这样,各控制电路虽然挂 在同一条总线上,却彼此独立,互不相关。

      I2C总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
      开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
      结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。 
      应 答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元 发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。 
  目前有很多半导体集成电路上都集成了I2C接口。

 2.2
       i2c总线是两条线连接多个设备,inter ic. 
       寻址是通过在scl线上发出寻址信号: 起始,7/10位 地址 + 1位(读/写),(多个后续的数据),终止位。  而地址是由设备的脚决定,一般会有几个固定脚与几个可编程脚。通过编程可以确定设备的地址。当设备收到寻址信号后,判断是不是其地址。

7位寻址,被I2C协会保留,所以一般用10位寻址:s,1111 0xx (R/W) ACK xxxxxxxx  
若(R/W) = 0, 则为从MASTER > slave,写 所以10个x为地址
若(R/W) = 1,则为 从 SLAVE > MASTER, 读, 此时先前被寻址了的SLAVE就会发送数据给MASTER。

2.3
i2c是基于8位的
SCL时钟线,由主机提供时钟。
起始位: sda下降,scl保持高
结束位: sda上升,scl保持高。
地址位,一般是10位,被拆分为 xx (r/w) ack xxxxxxxx
数据: 每个字节必须是8位,先传MSB。每个字节后必须跟一个响应位(从机发)
每次从机接收时,可以使SCL为低,从而让主机进入等待状态。


3:"linuxi2c体系结构"
三个层次:
1,i2c核心,内核完成 i2c-core.c
2, i2c总线驱动, 实现 i2c_adapter(总线适配器),i2c_algorithm(通信方法)
3, i2c设备驱动,实现 i2c_driver, i2c_client
通信方法:
通过i2c_msg来表示每次的通信。每次可以收发多个i2c_msg.



//adapter注册,当成是一个platform_bus总线下的设备。
int i2c_add_adapter(struct i2c_adapter *adapter)
res = idr_get_new_above(&i2c_adapter_idr, adapter,__i2c_first_dynamic_bus_num, &id);
i2c_register_adapter(adapter);
static int i2c_register_adapter(struct i2c_adapter *adap)
{
if (adap->dev.parent == NULL) 
adap->dev.parent = &platform_bus;
adap->dev.release = &i2c_adapter_dev_release;
adap->dev.class = &i2c_adapter_class;
res = device_register(&adap->dev);
}
//i2c_add_adapter()而言,它使用的是动态总线号,即由系统给其分析一个总线号,而i2c_add_numbered_adapter()则是自己指定总线号,


//i2c_driver注册, 即driver先匹配所有adapter,找到正确的,然后检测硬件,生成对应的i2c_client, 然后把i2c_client注册到adapter上。
当 i2c_driver向内核注册时,会被调用attach_adatper,先匹配当前系统中所有adapter,再去检测硬件,当确定硬件存在,则会生 成匹配i2c_client?, 把i2c_client的driver指针指向自己(driver),adapter指针指向其adapter.然后会让这个adapter调用 其client_register. 

注册:
static inline int i2c_add_driver(struct i2c_driver *driver)
{
return i2c_register_driver(THIS_MODULE, driver);
}
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
res = driver_register(&driver->driver); //注册代表本 i2c_driver的 内部 driver
class_for_each_device(&i2c_adapter_class, NULL, driver, __attach_adapter); //从目前系统中所的adapter中去匹配 对应的 adapter.
}
static int __attach_adapter(struct device *dev, void *da ta)
{
struct i2c_adapter *adapter = to_i2c_adapter(dev);
struct i2c_driver *driver = da ta;

i2c_detect(adapter, driver); //检测硬件

/* Legacy drivers scan i2c busses directly */
if (driver->attach_adapter)
driver->attach_adapter(adapter); //生成client 并加入到adapter 中。
return 0;
}
而一般 i2c_driver的实现时是:
static int yy_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_da ta, yy_detect);
}

static int yy_detect (struct i2c_adapter * adapter, int address, int kind)
{
struct yy_da ta da ta = kzalloc(sizeof(struct yy_da ta), GFP_KERNEL);
i2c_client new_client = da ta->client;
err = i2c_attach_client(new_client);
}

/*
 * The following structs are for those who like to implement new bus drivers:
 * i2c_algorithm is the interface to a class of hardware solutions which can
 * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
 * to name two of the most common.
 */
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,   "i2c传输函数"
  int num);
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, "smbus传输函数"
  unsigned short flags, char read_write,
  u8 command, int size, union i2c_smbus_da ta *da ta);

/* To determine what the adapter supports */
u32 (*functionality) (struct i2c_adapter *);   "返回适配器支持的功能"
};
/*
 * i2c_adapter is the structure used to identify a physical i2c bus along
 * with the access algorithms necessary to access it.
 */
struct i2c_adapter {  "代表 一个物理的I2C总线"
struct module *owner;
unsigned int id;
unsigned int class;  /* classes to allow probing for */
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
void *algo_da ta;

/* --- administration stuff. */
int (*client_register)(struct i2c_client *);
int (*client_unregister)(struct i2c_client *);

/* da ta fields that are valid for all devices */
u8 level; /* nesting level for lockdep */
struct mutex bus_lock;
struct mutex clist_lock;

int timeout; /* in jiffies */
int retries;
struct device dev; /* the adapter device */

int nr;
struct list_head clients; /* DEPRECATED */
char name[48];
struct completion dev_released;
};

/**
 * struct i2c_driver - represent an I2C device driver
 * @id: Unique driver ID (optional)
 * @class: What kind of i2c device we instantiate (for detect)
 * @attach_adapter: Callback for bus addition (for legacy drivers)
 * @detach_adapter: Callback for bus removal (for legacy drivers)
 * @detach_client: Callback for device removal (for legacy drivers)
 * @probe: Callback for device binding (new-style drivers)
 * @remove: Callback for device unbinding (new-style drivers)
 * @shutdown: Callback for device shutdown
 * @suspend: Callback for device suspend
 * @resume: Callback for device resume
 * @command: Callback for bus-wide signaling (optional)
 * @driver: Device driver model driver
 * @id_table: List of I2C devices supported by this driver
 * @detect: Callback for device detection
 * @address_da ta: The I2C addresses to probe, ignore or force (for detect)
 * @clients: List of detected clients we created (for i2c-core use on ly)
 *
 * The driver.owner field should be set to the module owner of this driver.
 * The driver.name field should be set to the name of this driver.
 *
 * For automatic device detection, both @detect and @address_da ta must
 * be defined. @class should also be set, otherwise on ly devices forced
 * with module parameters will be created. The detect function must
 * fill at least the name field of the i2c_board_info structure it is
 * handed upon successful detection, and possibly also the flags field.
 *
 * If @detect is missing, the driver will still work fine for enumerated
 * devices. Detected devices simply won't be supported. This is expected
 * for the many I2C/SMBus devices which can't be detected reliably, and
 * the on es which can always be enumerated in practice.
 *
 * The i2c_client structure which is handed to the @detect callback is
 * not a real i2c_client. It is initialized just enough so that you can
 * call i2c_smbus_read_byte_da ta and friends on it. Don't do anything
 * else with it. In particular, calling dev_dbg and friends on it is
 * not allowed.
 */
struct i2c_driver {
int id;
unsigned int class;

/* Notifies the driver that a new bus has appeared. This routine
* can be used by the driver to test if the bus meets its conditions
* & seek for the presence of the chip(s) it supports. If found, it
* registers the client(s) that are on the bus to the i2c admin. via
* i2c_attach_client.  (LEGACY I2C DRIVERS ON LY)
*/
int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);

/* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private da ta. Also, if the client struct
* has been dynamically allocated by the driver in the function above,
* it must be freed here.  (LEGACY I2C DRIVERS ON LY)
*/
int (*detach_client)(struct i2c_client *) __deprecated;

/* Standard driver model interfaces, for "new style" i2c drivers.
* With the driver model, device enumeration is NEVER done by drivers;
* it's done by infrastructure.  (NEW STYLE DRIVERS ON LY)
*/
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);

/* driver model interfaces that don't relate to enumeration  */
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(struct i2c_client *);

/* a ioctl like command that can be used to perform specific functions
* with the device.
*/
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);  "类似ioctl"

struct device_driver driver;
const struct i2c_device_id *id_table;    "与本驱动 匹配的 设备id"

/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *); "设备检测"
const struct i2c_client_address_da ta *address_da ta;
struct list_head clients;
};

/**
 * struct i2c_client - represent an I2C slave device
 * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
 * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
 * @addr: Address used on the I2C bus connected to the parent adapter.
 * @name: Indicates the type of the device, usually a chip name that's
 * generic enough to hide second-sourcing and compatible revisions.
 * @adapter: manages the bus segment hosting this I2C device
 * @driver: device's driver, hence pointer to access routines
 * @dev: Driver model device node for the slave.
 * @irq: indicates the IRQ generated by this device (if any)
 * @list: list of active/busy clients (DEPRECATED)
 * @detected: member of an i2c_driver.clients list
 * @released: used to synchronize client releases & detaches and references
 *
 * An i2c_client identifies a single device (i.e. chip) connected to an
 * i2c bus. The behaviour exposed to Linux is defined by the driver
 * managing the device.
 */
struct i2c_client {
unsigned short flags; /* div., see below */
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 i2c_driver *driver; /* and our access routines */
struct device dev; /* the device structure */
int irq; /* irq issued by device */
struct list_head list; /* DEPRECATED */
struct list_head detected;
struct completion released;
};


/**
 * struct i2c_board_info - template for device creation
 * @type: chip type, to initialize i2c_client.name
 * @flags: to initialize i2c_client.flags
 * @addr: stored in i2c_client.addr
 * @platform_da ta: stored in i2c_client.dev.platform_da ta
 * @archdata: copied into i2c_client.dev.archdata
 * @irq: stored in i2c_client.irq
 *
 * I2C doesn't actually support hardware probing, although controllers and
 * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
 * a device at a given address.  Drivers commonly need more information than
 * that, such as chip type, configuration, associated IRQ, and so on.
 *
 * i2c_board_info is used to build tables of information listing I2C devices
 * that are present.  This information is used to grow the driver model tree
 * for "new style" I2C drivers.  For mainboards this is done statically using
 * i2c_register_board_info(); bus numbers identify adapters that aren't
 * yet available.  For add-on boards, i2c_new_device() does this dynamically
 * with the adapter already known.
 */
struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
void *platform_da ta;
struct dev_archdata *archdata;
int irq;
};
struct i2c_devinfo {
struct list_head list;
int busnum;
struct i2c_board_info board_info;
};

//***************************************************************//
struct i2c_msg {
__u16 addr; /* slave address */
__u16 flags;
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
#define I2C_M_RD 0x0001 /* read da ta, from slave to master */
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg da ta */
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值