对于硬件I2C使用的一些思考: 1,硬件IIC会在/dev目录下生成i2c-0 -- i2c-x个节点,这就提供给我一种访问的方法, 我们可以使用open节点的方式去操作IIC设备,但这样我们传递下去的只是地址,寄存器地址和寄存器值; 设备的操作逻辑就要全部放在上层了。 2,使用驱动核心层给出的读写接口xx-read,xx-write。我们在我们自己的设备驱动中去调用II2C模块(在核心层) 开放出来的这些接口,所以我们对设备的操作就在我们的设备驱动中完成了,即操作设备的逻辑组织在驱动中完成, 我们只是利用ioctl或者write,read来给上层给出接口,他们调用的时候就可以按照功能模块来调用。
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. 除了仲裁丢失中断,是否同时还有别的中断产生;起始信号: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而言,除了首个发出的为从设备地址外,其余均为读写的数据。