目录
[五,I2c slave设备syr827的使用,](#五,I2c slave设备syr827的使用,)
一,I2C的理论基础




二,I2C的寄存器和概念
NAK:no ack
I2C_CON = 0x000,
con_bit(0):1表示i2c_en
con_bit(2-1):00表示transmit only
con_bit(2-1):01表示transmit address--> restart --> transmit address --> receive only
con_bit(2-1):10表示receive only
con_bit(5):1表示master不应答
con_bit(6):1表示NAK时停止传输
I2C_CLKDIV = 0x004,
I2C_MRXADDR = 0x008,
I2C_MRXRADDR = 0x00c,
I2C_MTXCNT = 0x010,
I2C_MRXCNT = 0x014,
I2C_IEN = 0x018,
I2C_IPD = 0x01c,
ipd_bit(2):MTXCNT data transmit finished interrupt pending bit
ipd_bit(3):MRXCNT data received finished interrupt pending bit
ipd_bit(6):NAK handshake received interrupt pending bit
I2C_FCNT = 0x020,
I2C_TXDATA_BASE = 0x100,
I2C_RXDATA_BASE = 0x200,
三,I2C的函数
1,rk3288_i2c_start
(1)通过write32(I2C_IPD,0x7f)复位所有中断
(2)通过write32(I2C_CON,(1 << 0)|(1 << 3))使能和start i2c,bit(0):i2c_en,bit(3):i2c_start
(3)在10us内读取I2C_IPD的bit4(startipd)是否为1,若为1则写1复位,否则循环读取,超时则返回
(4)I2C_IPD是写0无效寄存器,所以写1复位只写bit4即可
2,rk3288_i2c_stop
(1)通过write32(I2C_IPD,0x7f)复位所有中断
(2)通过write32(I2C_CON,(1 << 0)|(1 << 4))使能和stop i2c,bit(0):i2c_en,bit(4):i2c_stop
(3)在10us内读取I2C_IPD的bit5(stopipd)是否为1,若为1则写1复位,否则循环读取,超时则返回
(4)I2C_IPD是写0无效寄存器,所以写1复位只写bit5即可
(5)通过write32(I2C_CON,0)停用i2c
3,rk3288_i2c_read
I2C_MRXRADDR寄存器用于存储I2C接收模式下的从机地址(包括读/写位)而 I2C_MRXADDR 寄存器可能用于配置I2C发送模式下的从机地址或作为通用地址寄存器
在I2C读时序中,主设备首先发送从设备地址(通过MRXADDR配置),然后发送寄存器地址(通过MRXRADDR配置),最后重新发送从设备地址(最低位设为1表示读操作),以完成寄存器读取
(1)通过write32(I2C_MRXADDR, (1 << 24) | (msg->addr << 1) | 1)配置从机地址,bit24是address low byte valid,地址左移1bit和协议对上7bit+r/w 位
(2)通过write32(I2C_MRXRADDR,0)发送从设备的寄存器地址,这里是0,有些i2c从设备有寄存器,比如sensor
(3)循环len,len为8bit buf的个数,每次循环最多处理32个字节
(4)循环第一次con_bit(2-1)=01,循环第二次及以后con_bit(2-1)=10
(5)write32(I2C_IPD,0x7f);write32(I2C_CON,con);write32(I2C_MRXCNT, bytes);con_bit0/5/6置1,bit2-1如第四条描述
(6)100ms内循环判断,如果ipd_bit(3)中断产生则ok,如果ipd_bit(6)中断产生或超时则失败返回
(7)通过read32(I2C_RXDATA_BASE)读取data,处理大小端,若len为奇数,大端模式buff[3]是空,不影响数据完整性
4,rk3288_i2c_write
(1)int len = msg->len + 1;表示deviceaddr+regaddr+data,多了一个deviceaddr
(2)write32(I2C_TXDATA_BASE)填充数据,处理大小端,第一次填充带上deviceaddr
(3)write32(I2C_IPD,0x7f);write32(I2C_CON, (1 << 6) | (0 << 1) | (1 << 0));write32(I2C_MTXCNT, bytes);con_bit(2-1):00表示transmit only
(4)100ms内循环判断,如果ipd_bit(2)中断产生则ok,如果ipd_bit(6)中断产生或超时则失败返回
(5)如果len大于32的话循环下一次
5,i2c_rk3288_xfer
(syr82x_read/syr82x_write)->->i2c_transfer->i2c_rk3288_xfer
(1)调用rk3288_i2c_start产生一个start信号
(2)循环msgs,因为xfer支持i2c读和i2c写,i2c读至少需要2个msg,先写地址,再读data,两个msg的flag不一样,所以需要循环
(3)在循环内如果index不等于0,再发送一个start信号
(4)在循环内,如果flag是写则调用rk3288_i2c_write,如果flag是读则调用rk3288_i2c_read,直到循环结束
(5)调用rk3288_i2c_stop产生一个stop信号
6,rk3288_i2c_set_rate
通过配置I2C_CLKDIV分频系数设置i2c的频率,分频系数通过getclk(link-pclk-i2c0)与设备树的频率参数所得
I2c0的parent是link-pclk-i2c0
时钟树是:
(cpll->gate-cpll/gpll->gate-gpll)->mux-pd-bus-src->div-pd-bus-src->div-pd-bus->gate-cpu-pclk->div-cpu-pclk->pclk-bus-pre->gate-pclk-i2c0->link-pclk-i2c0
四,I2C设备读写实例
syr82x_read(pdat->dev, SYR82X_VSEL0, &val);
static bool_t syr82x_read(struct i2c_device_t * dev, u8_t reg, u8_t * val)
{
struct i2c_msg_t msgs[2];
u8_t buf;
msgs[0].addr = dev->addr;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = ®
msgs[1].addr = dev->addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = 1;
msgs[1].buf = &buf;
if(i2c_transfer(dev->i2c, msgs, 2) != 2)
return FALSE;
if(val)
*val = buf;
return TRUE;
}
syr82x_write(pdat->dev, SYR82X_VSEL0, val);
static bool_t syr82x_write(struct i2c_device_t * dev, u8_t reg, u8_t val)
{
struct i2c_msg_t msg;
u8_t buf[2];
buf[0] = reg;
buf[1] = val;
msg.addr = dev->addr;
msg.flags = 0;
msg.len = 2;
msg.buf = &buf[0];
if(i2c_transfer(dev->i2c, &msg, 1) != 1)
return FALSE;
return TRUE;
}
五,I2c slave设备syr827的使用,
1,syr827函数
regulator_syr82x_set_enable
syr82x_read(pdat->dev, SYR82X_VSEL0, &val);
if(enable)
val |= (0x1 << 7);
else
val &= ~(0x1 << 7);
syr82x_write(pdat->dev, SYR82X_VSEL0, val);
syr82x_read(pdat->dev, SYR82X_VSEL1, &val);
if(enable)
val |= (0x1 << 7);
else
val &= ~(0x1 << 7);
syr82x_write(pdat->dev, SYR82X_VSEL1, val);
regulator_syr82x_set_voltage
syr82x_read(pdat->dev, SYR82X_VSEL0, &val);
val &= ~(0x3f << 0);
val |= ((syr82x_vol_to_reg(voltage, 12500, 712500, 1500000) & 0x3f) << 0);
syr82x_write(pdat->dev, SYR82X_VSEL0, val);
syr82x_read(pdat->dev, SYR82X_VSEL1, &val);
val &= ~(0x3f << 0);
val |= ((syr82x_vol_to_reg(voltage, 12500, 712500, 1500000) & 0x3f) << 0);
syr82x_write(pdat->dev, SYR82X_VSEL1, val);
2,syr827重要寄存器
SYR82X_VSEL0 = 0x00,
SYR82X_VSEL1 = 0x01,


SYR82X_CTRL = 0x02,

syr82x_read(pdat->dev, SYR82X_CTRL, &val);
val &= ~(0x7 << 4);val |= (0x4 << 4);配置设置正电压跃变的转换速率10mV/2.4us
slew rate 就是电压转换速率(Slew Rate),简写为SR,简称压摆率其定义是在1微秒或者1纳秒等时间里电压升高的幅度
syr82x_write(pdat->dev, SYR82X_CTRL, val);