I2C-controller在硬件的构造上是一个独立的设备,可以完成I2C的总线操作。然而换个角度,当BUS上没有从设备时,I2C-controller是虚无存在的。因此,总线从计算机体系结构上看,是虚拟的概念,只有总线上挂载设备后,总线的存在才有意义。
针对linux编写驱动时,adapter需要/dev下面的设备节点嘛?通常“不”!
adapter驱动的任务是提供bus支持,而不是针对某一个具体设备,所以完全没有必要提供设备节点。
当在I2c bus上挂载24c02 eeprom后,可以通过eeprom的驱动提供的/dev/设备节点访问。
有时候,为了方便调试,或者在设备驱动没有编写情况下访问设备,那么就必须提供adapter设备节点。
adapter驱动由于没有提供register_char节点的功能,因此,这部分需要drivers/i2c/i2c-dev.c完成。
i2c-dev.c提供了一个虚拟设备节点,也就是adapter的节点。主设备号89
测试EEPROM AT24C02及AD-DA PCF8591T
参考chenzhufly的博文
说明:
I2C_BOARD_INFO("24c02", 0x54)这句里的"24c02"不是随便给的,当注册了该设备,总线会根据"24c02"匹配driver,如果找到对应的driver,用i2cdetect检测出0x54上会出现UU,否则就出现0x54。
之后我在i2c-3下挂了一个AD/DA芯片PCF8591T,地址0x48,i2cdetect -r 3后显示的不是UU,是48,就是因为总线没有为设备"pcf8591t"找到对应的驱动,它的驱动内核没有提供,需要自己完成该驱动的编写。
如果没有"pcf8591t"的驱动,是不是就不能访问它呢?不是的!一般通过adapter设备节点访问,即i2c-1、i2c-2、i2c-3...
pcf8591t测试
0x41-0x44地址里的值分别是AIN0-AIN3 AD转换后的数字值,这些地址可读;
0x40地址可写,写入的数字值为数模转换的数字值。
编写应用程序测试:
fd = open("/dev/i2c-3", O_RDWR);
//DA转换
unsigned char wrbuf[2] = {0x40, 0x10};//DA转换需要的数字值0x10
ret = write(fd, wrbuf, 2);
ADEBUG("write ret: %d\n", ret);
ADEBUG("errno = %d\n", errno);
usleep(10000);//!!!!!!
//读通道0
unsigned char rdaddr[1] = {0x40};//AIN0
unsigned char rddata = 0x00;
write(fd, rdaddr, 1);
read(fd, &rddata, 1);
read(fd, &rddata, 1);//为什么要读两次?不明白!参考下javascript:;
ADEBUG("AIN0 rddata: %d\n", rddata);
//&0x41
//读通道1
rdaddr[0] = 0x41;
write(fd, rdaddr, 1);
read(fd, &rddata, 1);
read(fd, &rddata, 1);
ADEBUG("AIN1 rddata: %d\n", rddata);//&0x42
//读通道2
rdaddr[0] = 0x42;
write(fd, rdaddr, 1);
read(fd, &rddata, 1);
read(fd, &rddata, 1);
ADEBUG("AIN2 rddata: %d\n", rddata);//&0x43
//读通道3
rdaddr[0] = 0x43;
write(fd, rdaddr, 1);
read(fd, &rddata, 1);
read(fd, &rddata, 1);
ADEBUG("AIN3 rddata: %d\n", rddata);//&0x44