I2C会话分为两种
一种是读会话,一种是写会话
这两种会话都有固定的格式,按照数据手册上的时序写就行了
下面提供的是标准的I2C时序
特别注意下面的DELAY(x) 宏,你可以定义为你需要的时间.
时间可以从芯片手册中得知.
注意:I2C可以由内核中I2C框架实现,也可以用GPIO模拟I2C来实现.
两者的切换需要配置复用寄存器
//写会话
EXPORT_SYMBOL(gpio_i2c_write);
void gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char data)
{
i2c_start_bit();
i2c_send_byte(devaddress);
i2c_receive_ack();
i2c_send_byte(address);
i2c_receive_ack();
i2c_send_byte(data);
i2c_receive_ack();
i2c_stop_bit();
}
//这是标准i2c的流程
/* * sends a start bit via I2C rountine. * */
static void i2c_start_bit(void)
{
DELAY(1);
i2c_set(SDA | SCL);
DELAY(1);
i2c_clr(SDA);
DELAY(1);
}
//一般起始位都是在SDA与SCL同时高的时候,拉低SDA,这就开始了.
/* * sends a character over I2C rountine. * * @param c: character to send * */
static void i2c_send_byte(unsigned char c)
{
int i;
local_irq_disable();
for (i=0; i<8; i++)
{
DELAY(1);
i2c_clr(SCL);
DELAY(1);
if (c & (1<<(7-i)))
i2c_set(SDA);
else
i2c_clr(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
}
DELAY(1);
local_irq_enable();
}
//一般发送字节,要不是发送的地址,就是发送的数据,起始都是一样的,都是将字节的字节发送,从最高位到最低位.
/* receives an acknowledge from I2C rountine. * * @return value: 0--Ack received; 1--Nack received * */
static int i2c_receive_ack(void)
{
int nack;
unsigned char regvalue;
DELAY(1);
regvalue = HW_REG(GPIO_0_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_0_DIR) = regvalue;
DELAY(1);
i2c_clr(SCL);
DELAY(1);
i2c_set(SCL);
DELAY(1);
nack = i2c_data_read();
DELAY(1);
i2c_clr(SCL);
DELAY(1);
// i2c_set(SDA);
// DELAY(1);
if (nack == 0)
return 1;
return 0;
}
//在往总线上发送一个字节之后,从机设备会发回一个ack,也就是回应,我们需要捕获这个回应.然后鉴别是否正确
/* * sends a stop bit via I2C rountine. * */
static void i2c_stop_bit(void)
{
/* clock the ack */
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
/* actual stop bit */
DELAY(1);
i2c_clr(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_set(SDA);
DELAY(1);
}
//停止位,一般是在SDA和SCL同时为高的时候拉低SDA,然后代表依次会话结束.
//读会话
EXPORT_SYMBOL(gpio_i2c_read);
unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
{
int rxdata;
i2c_start_bit();
i2c_send_byte(devaddress);
i2c_receive_ack();
i2c_send_byte(address);
i2c_receive_ack();
i2c_start_bit();
i2c_send_byte((unsigned char)(devaddress) | 1);
i2c_receive_ack();
rxdata = i2c_receive_byte();
i2c_send_ack();//注意,这里是读ack
i2c_stop_bit();
return rxdata;
}
//读的周期一般比较长.