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来确定)。