NXP

I2C(TCA9545APWR+PLL(CDCM6208))

2019-07-12 11:42发布

DEVICE: &i2c1 {


#address-cells = <0x1>;
#size-cells = <0x0>;


i2c-switch@70 {
compatible = "nxp,pca9545";    /* I2C switch pca9545 */


#address-cells = <0x1>;
#size-cells = <0x0>;
reg = <0x70>;


i2c@0 {
reg = <0x0>;
#address-cells = <0x1>;
#size-cells = <0x0>;


};


i2c@1 {
reg = <0x1>;
#address-cells = <0x1>;
#size-cells = <0x0>;


};


i2c@2 {
reg = <0x2>;
#address-cells = <0x1>;
#size-cells = <0x0>;


};
i2c@3 {
reg = <0x2>;
#address-cells = <0x1>;
#size-cells = <0x0>;


};
};
};

测试code: #include
#include
#include
#include
#include
#include
#include


using namespace std;


#define SLAVE_ADDR 0x54
#define MUX_ADDR   0x70


class cdcm6208
{
public:
static cdcm6208 &get_instance();
void init_cdcm6208();
void write_buf();
void read_buf();
void IicMuxEnable(void);
private:
int file_i2c;
};
/******************************************************************
 *  函数名: get_instance
 *  功能:
 *  输入参数: 
 *  输出参数: 无
 *  返回值:  无
 *  作者:zhiwei
 *  更改:
 *  备注:
 *******************************************************************/
cdcm6208 & cdcm6208::get_instance()
{
static cdcm6208 cdcm6208_instance;
return cdcm6208_instance;
}
/******************************************************************
 *  函数名: write_buf
 *  功能:
 *  输入参数: 
 *  输出参数: 无
 *  返回值:  无
 *  作者:zhiwei
 *  更改:
 *  备注:write data to slave
 *******************************************************************/
void cdcm6208::write_buf()

unsigned short WriteBuffer[2] = {0x0300,0x1564};


   if( sizeof(WriteBuffer)!= write(file_i2c,WriteBuffer,sizeof(WriteBuffer)) ) {  
        cout<<"cdcm6208_i2c_write fail!"<         return;  
    } 
}
/******************************************************************
 *  函数名: read_buf
 *  功能:
 *  输入参数: 
 *  输出参数: 无
 *  返回值:  无
 *  作者:zhiwei
 *  更改:
 *  备注:read data to slave
 *******************************************************************/
void cdcm6208::read_buf()
{
unsigned short WriteBuffer[1] = {0x0300};
int i2c_data_size = 2;
    unsigned short read_buffer;
write(file_i2c, WriteBuffer,sizeof(WriteBuffer));
if (read(file_i2c, &read_buffer, i2c_data_size) != i2c_data_size) 
{
cout<<"read error ++++++++"<}
cout<<"read_buffer = "< }
/******************************************************************
 *  函数名: init_cdcm6208
 *  功能:
 *  输入参数: 
 *  输出参数: 无
 *  返回值:  无
 *  作者:zhiwei
 *  更改:
 *  备注:init the slave
 *******************************************************************/
void cdcm6208::init_cdcm6208()
{
const char* filename = "/dev/i2c-5";
file_i2c = open(filename,O_RDWR);
    if (file_i2c < 0) 
    {
cout<<"i2c device open error"<         return;
}
if(ioctl(file_i2c, I2C_SLAVE, SLAVE_ADDR) < 0) 
    {
cout<<"i2c device address set error"<         return;
}
}
/******************************************************************
 *  函数名: IicMuxEnable
 *  功能:
 *  输入参数: control PCA9545 chip
 *  输出参数: 无
 *  返回值:  无
 *  作者:zhiwei
 *  更改:
 *  备注:test
 *******************************************************************/
void cdcm6208::IicMuxEnable(void)
{
unsigned char WriteBuffer[2];/* Buffer to hold location address.*/
unsigned char ReadBuffer = 0x0;/* Buffer to hold data read.*/
unsigned short BytesToRead;
int BytesWritten;
unsigned short Sel_Channel = 0x0;
unsigned long Mux_Reg = 0x1;
int Status;


Status = ioctl(file_i2c, I2C_SLAVE_FORCE, MUX_ADDR);
if(Status < 0)
{
printf(" Unable to set the Mux address ");


return;
}


Sel_Channel = 0x4;


Mux_Reg = Mux_Reg << (Sel_Channel - 1);
WriteBuffer[0] = Mux_Reg;


printf("Selected Channel [%d] Mux Reg Value[%x] ", Sel_Channel, Mux_Reg);


BytesWritten = write(file_i2c, WriteBuffer, 1);
cout<<"BytesWritten = "<if(BytesWritten != 1)
{
printf("Write Mux Reg failed ");
}


BytesToRead = read(file_i2c, &ReadBuffer, 1);
if(BytesToRead != 1)
{
printf("Read Mux Reg failed ");
}
printf("Mux Reg Expected[%x] Actual[%x] ", Mux_Reg, ReadBuffer);


printf(" Mux Enable for EEPROM Succesful ");


return;
}
/******************************************************************
 *  函数名: main
 *  功能:
 *  输入参数: 
 *  输出参数: 无
 *  返回值:  无
 *  作者:zhiwei
 *  更改:
 *  备注:test
 *******************************************************************/
int main()
{
cdcm6208 cdcm_instance = cdcm6208::get_instance();
cdcm_instance.init_cdcm6208();
//cdcm_instance.IicMuxEnable();
cdcm_instance.write_buf();
cdcm_instance.read_buf();
return true;
}
1、虽然I2C控制器通过PCA9545转接,但是理论上,PCA9545和连接在PCA9545通道上的CDCM芯片都可以看做是I2C总线直接挂载的SLAVE.可以使用SLAVE_ADDR+opera方式操作 2、使用PCA9545,我们可以直接使用内核驱动屏蔽它,利用内核PCA的驱动+设备树种指定PCA9545的操作地址。驱动安装后,会生成PCA9545分出的4通道SLAVE的设备文件(i2c-3,i2c-4,i2c-5,i2c-6),可以直接操作这些文件(操作连接在4通道上的SLAVE)。 3、除了使用内核指定的PCA9545驱动外,还可以将PCA9545看做是I2C控制器的一个客户端,通过写该器件的控制寄存器使能各个通道。然后再通过各个通道上挂载器件的地址去操作不同通道上的slave(IicMuxEnable函数,指定第四通道。PCA只有一个控制寄存器,所以不用指定寄存器地址也可以。但是需要将init_cdcm6208函数中的配置PLL从机地址的部分移到该函数后面执行,不然,后面的write和read部分只会对0x70地址的从机进行操作,而不是0x54的从机了。流程:通道选择(利用/dev/i2c-*+配置从机地址为PCA芯片+配置PCA控制寄存器选通通道)-->修改从机地址为通道后的下游从设备 -->读写操作)。 4、I2C的寄存器地址可以当做是数据下发,客户端会识别该地址,然后把地址后面的数据写入到该寄存器中。(寄存器可能是8位也可能是16位。例如:8(reg_add)+8(data)或16(reg_addr)+16(data).这里的8或者16要根据客户端芯片的datasheet来确定)。