I2C思考和check

xiaoxiao2021-02-28  19

 

对于硬件I2C使用的一些思考: 1,硬件IIC会在/dev目录下生成i2c-0 -- i2c-x个节点,这就提供给我一种访问的方法, 我们可以使用open节点的方式去操作IIC设备,但这样我们传递下去的只是地址,寄存器地址和寄存器值; 设备的操作逻辑就要全部放在上层了。 2,使用驱动核心层给出的读写接口xx-read,xx-write。我们在我们自己的设备驱动中去调用II2C模块(在核心层) 开放出来的这些接口,所以我们对设备的操作就在我们的设备驱动中完成了,即操作设备的逻辑组织在驱动中完成, 我们只是利用ioctl或者write,read来给上层给出接口,他们调用的时候就可以按照功能模块来调用。

I2C优化的方向:

1:一次start多次读写字节  2:由查询方式变为中断方式  3:调高时钟频率

I2C时钟设置较大时,如果上拉电阻及电容等不匹配,波形上升比较缓慢,会导致数据误判。

 

i2c的check  9位为ack位,如果此时(clk为高)data为0表示从设备有回应;  在刚开始发的时候,要有一个开始信号,即clk为1,data为0;  data信号只有在clk低电平的时候才可以发生变化,高电平时data要保持稳定

仲裁丢失的案例:

仲裁丢失是出现在 主机正在发送地址或数据的时候,发送高电平(XI2C1_SDA_OUT = 1),但同时接收到的却是低电平(XI2C1_SDA_IN = 0)(XI2C1_SDA是双向口),

在这种情况下,主机会认为是有另外一个主机把XI2C1_SDA拉低了,于是就会出现仲裁丢失。

请重点关注:  1. XI2C1_SDA这个管脚有没有上拉(必须上拉)

2. 连接到XI2C1_SDA这个管脚除了 I2C slave以外还有没有别的器件; 3. I2C slave是否会把XI2C1_SDA拉低(一般I2C slave在接收到地址或数据之后会拉低SDA,表示接收成功的ACK,查看这个ACK是否在传输尚未完成之前就产生了;或者还有没有别的原因会把SDA拉低); 4. 主机发送的地址与I2C slave的地址是否匹配; 5. 除了仲裁丢失中断,是否同时还有别的中断产生;

i2c使用总结:

i2c使用总结:

起始信号:clk 高时,da 由高变低  结束信号:clk 高时,da 由低变高  数据的有效性:当clk为低时,允许da变化,但是只在clk高时保持稳定,所以看波形时,需要看clk高时候的da位  数据只有在clk高的时候有效,在clk为低的时候才能发生变化,所以ack的响应在clk第八位后的低电平拉低data线为有ack信号  对于8位数据的读写,无论是地址还是数据,第9位均为ack位,若ack为高表示从机未响应  起始信号开始后的前7位为从机地址,第8位为读写位,第九位为ack。中间多少个字节的数据无限制,指导发出结束信号  写数据:从机地址的读写位为0  读数据:从机地址的读写位为1  一个单独的写过程为start --device addr & 0xfe(保证为写)ack----数据(addr or data )ack---stop(最后的ack为从机告诉主机已经写成功)  一个单独的读过程为start --device addr | 0x01 (保证为写) ack----要读的寄存器 ack----stop ----数据(addr or data )nack---stop?(nack为主机告诉从机已经读完) 

http://blog.csdn.net/xukai871105/article/details/15028117  写:向设备的寄存器地址0x18写入0x20  data[2]={0x18,0x20};  slv_addr = 0xc0;  struct i2c_msg msgs = { .addr = slv_addr>>1, .flags = 0, .len = 2, .buf = data };

slv_addr = 0xc0;设备地址  .flags = 0,写标志  .len = 2 写入的长度为2个byte  .buf = data 写入数据,因为此时已经是写标志,所以第一个数据是寄存器地址,第二个是写入寄存器的值

读:读出从设备的寄存器0x18的值  slv_addr = 0xc0;  struct i2c_msg msgs[] = {{ .addr = slv_addr>>1, .flags = 0, .len = 1, .buf = 0x18 },先写寄存器地址  { .addr = slv_addr>>1, .flags = I2C_M_RD, .len = 1, .buf = data } };再读出该寄存器的值  i2c_transfer(adapter, msgs, 2))

1:先写寄存器地址  slv_addr = 0xc0;设备地址  .flags = 0,写标志  .len = 1 写入的长度为一个byte  .buf = 0x18 写入寄存器地址  2:再读出该寄存器的值  slv_addr = 0xc0;设备地址  .flags = I2C_M_RD  .len = 1 读出一个byte  .buf = data,data为读出的值。

上述填入的读写长度均不包含写入的从设备地址长度,对于bus而言,除了首个发出的为从设备地址外,其余均为读写的数据。

转载请注明原文地址: https://www.6miu.com/read-2596089.html

最新回复(0)