I2C速率
NormalSpeed:100Kbps
Fast Speed: 400Kbps
High Speed: 3.5Mbps
I2C数据信号
1、 空闲状态
I2C总线空闲时,SDA和SCL两条信号线同时处于高电平。
因此,通常I2C都会有外接上拉电阻,在I2C空闲时,SCL和SDA处于高电平状态。
这里空闲不是指睡眠状态,在睡眠状态SCL和SDA是低电平的。
2、 启动信号
SCL保持高电平,SDA从高到低变化;
3、 停止信号
SCL保持高电平,SDA从低到高变化;
4、 数据传送
读取SDA电平时,SCL保持高电平
SDA电平变化时,SCL保持低电平
5、 应答信号
应答位,即ACK,I2C总线8位字节传送完成后,有接收器发送一个ACK信号。
即SCL在第9位时,SDA被接收器拉为低电平,发送器读取SDA为低电平时,即应答有效。
每传送一字节都需要应答信号。
I2C数据传送
1、 地址格式
I2C采用7位地址寻址,加上读写标志位。
所以通常slave address = slave chip address << 1;
2、 传送过程
启动信号Slave Address + R/W --> ACK --> Data --> ACK --> Data --> ACK -->*******--> 停止信号
示例代码
代码:
//设置你自己的要配置的GPIO
#define SCL GPIO_SCL
#define SDA GPIO_SDA
#define DELAY 5
/* GPIO 初始化配置 */
/* I2C的gpio 如果外部有上拉电阻的话,就配置成None Pull,如果没有上拉电阻,就配置成Pull-UP */
void gpio_i2c_init(void)
{
s3c_gpio_cfgpin(SCL, S3C_GPIO_INPUT);
s3c_gpio_cfgpin(SDA, S3C_GPIO_INPUT);
s3c_gpio_setpull(SCL, S3C_GPIO_PULL_UP);
s3c_gpio_setpull(SDA, S3C_GPIO_PULL_UP);
s5p_gpio_set_drvstr(SCL, S5P_GPIO_DRVSTR_LV4);
s5p_gpio_set_drvstr(SDA, S5P_GPIO_DRVSTR_LV4);
}
/* 启动信号 */
void i2c_start(void)
{
gpio_direction_output(SDA, 1);
gpio_direction_output(SCL, 1);
udelay(DELAY);
gpio_set_value(SDA, 0);
udelay(DELAY);
gpio_set_value(SCL, 0);
udelay(DELAY);
}
/* 停止信号 */
void i2c_stop(void)
{
gpio_set_value(SCL, 0);
gpio_set_value(SDA, 0);
udelay(DELAY);
gpio_set_value(SCL, 1);
udelay(DELAY);
gpio_set_value(SDA, 1);
udelay(DELAY);
}
/* 发送ACK */
void i2c_send_ack(u8 ack)
{
if(ack)
gpio_direction_output(SDA, 1);
else
gpio_direction_output(SDA, 0);
udelay(DELAY);
gpio_set_value(SCL, 1);
udelay(DELAY);
gpio_set_value(SCL, 0);
udelay(DELAY);
}
/* 接收ACK */
u8 i2c_receive_ack(void)
{
u8 rc = 0;
gpio_direction_input(SDA);
gpio_set_value(SCL, 1);
udelay(DELAY);
if(gpio_get_value(SDA)) {
rc = 1;
}
gpio_set_value(SCL, 0);
gpio_direction_output(SDA, 1);
return rc;
}
/* 发送字节 */
u8 i2c_send_byte(u8 send_byte)
{
u8 rc = 0;
u8 out_mask = 0x80;
u8 value;
u8 count = 8;
while(count > 0) {
value = ((send_byte & out_mask) ? 1 : 0);
if (value == 1) {
gpio_set_value(SDA, 1);
}
else {
gpio_set_value(SDA, 0);
}
udelay(DELAY);
gpio_set_value(SCL, 1);
udelay(DELAY);
gpio_set_value(SCL, 0);
udelay(DELAY);
out_mask >>= 1;
count--;
}
gpio_set_value(SDA, 1);
rc = i2c_receive_ack();
return rc;
}
/* 发送字节 */
void i2c_read_byte(u8 *buffer, u8 ack)
{
u8 count = 0x08;
u8 data = 0x00;
u8 temp = 0;
gpio_direction_input(SDA);
while(count > 0) {
gpio_set_value(SCL, 1);
udelay(DELAY);
temp = gpio_get_value(SDA);
data <<= 1;
if (temp)
data |= 0x01;
gpio_set_value(SCL, 0);
udelay(DELAY);
count--;
}
i2c_send_ack(ack);//0 = ACK 1 = NACK
*buffer = data;
}
/* 使用方法*/
static int gpio_i2c_read_data(struct i2c_client *client,
u16 reg, u8 *values, u16 length)
{
u8 *reg_u8;
u8 rc;
int i,j;
reg_u8 = (u8 *)®
printk("gpio_i2c_read_data:length:%d\n",length);
gpio_i2c_init();//初始化GPIO
i2c_start();//启动信号
rc = i2c_send_byte((client->addr << 1) | 0x00);//Slave Address 写数据
if(rc) {
printk("i2c_send_byte no ack 1\n");
return -1;
}
for(j = 0; j < 2; j++) {
rc = i2c_send_byte(reg_u8[j]);//发送data
if(rc) {
printk("i2c_send_byte no ack 2\n");
return -1;
}
}
i2c_stop();//停止信号
udelay(200);
i2c_start();//启动信号
rc = i2c_send_byte( (client->addr << 1) | 0x01 );//发送从机地址 读命令
if(rc) {
printk("i2c_send_byte no ack 3\n");
return -1;
}
for(i = 0; i < length; i++) {
i2c_read_byte(values++, !(length - i -1));//读取数据
}
i2c_stop();//停止信号
gpio_i2c_init();
return length;
}