[I2C]pca9555应用层测试代码

https://www.cnblogs.com/aaronLinux/p/6896573.html


注意点:

  • 如果在设置I2C_SLAVE的时候,提示device_busy,可以使用I2C_SLAVE_FORCE, 在驱动里面二者对应同一个case语句
  • 应用层可以调用接口:i2c_smbus_write_word_data(fd, __, __);和i2c_smbus_read_word_data(fd,__);

分享

问题如下

1. 应用程序中直接fd句柄是整个I2C0总线的文件句柄,而只是在set地址的时候,将I2C address设置下去,后面操作该芯片还是操作全局I2C0总线上这个文件,并没有指定去操作该芯片,这其中是怎么做到的?这样的话,如果在一个main程序中, 操作同一总线上不同i2c设备,而文件句柄是同一个,这要如何操作?

--------------------------------------------------------------------------------------------

驱动方面

首先配置I2C内核驱动,将pca9555的源码built-in进入(这里根据需要可能要配thermal的驱动),然后在devicetree中根据pca9555硬件I2C地址配置节点。

测试源码

复制代码
// I2C test program for a PCA9555

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

// I2C Linux device handle
int g_i2cFile;

// open the Linux device
void i2cOpen()
{
    g_i2cFile = open("/dev/i2c-0", O_RDWR);
    if (g_i2cFile < 0) {
        perror("i2cOpen");
        exit(1);
    }
}

// close the Linux device
void i2cClose()
{
    close(g_i2cFile);
}

// set the I2C slave address for all subsequent I2C device transfers
void i2cSetAddress(int address)
{
    if (ioctl(g_i2cFile, I2C_SLAVE, address) < 0) {
        perror("i2cSetAddress");
        exit(1);
    }
}

// write a 16 bit value to a register pair
// write low byte of value to register reg,
// and high byte of value to register reg+1
void pca9555WriteRegisterPair(uint8_t reg, uint16_t value)
{
    uint8_t data[3];
    data[0] = reg;
    data[1] = value & 0xff;
    data[2] = (value >> 8) & 0xff;
    if (write(g_i2cFile, data, 3) != 3) {
        perror("pca9555SetRegisterPair");
    }
}

// read a 16 bit value from a register pair
uint16_t pca9555ReadRegisterPair(uint8_t reg)
{
    uint8_t data[3];
    data[0] = reg;
    if (write(g_i2cFile, data, 1) != 1) {
        perror("pca9555ReadRegisterPair set register");
    }
    if (read(g_i2cFile, data, 2) != 2) {
        perror("pca9555ReadRegisterPair read value");
    }
    return data[0] | (data[1] << 8);
}

// set IO ports to input, if the corresponding direction bit is 1,
// otherwise set it to output
void pca9555SetInputDirection(uint16_t direction)
{
    pca9555WriteRegisterPair(6, direction);
}

// set the IO port outputs
void pca9555SetOutput(uint16_t value)
{
    pca9555WriteRegisterPair(2, value);
}

// read the IO port inputs
uint16_t pca9555GetInput()
{
    return pca9555ReadRegisterPair(0);
}

int main(int argc, char** argv)
{
    // test output value
    int v = 3;

    // direction of the LED animation
    int directionLeft = 1;

    // open Linux I2C device
    i2cOpen();

    // set address of the PCA9555
    i2cSetAddress(0x20);

    // set input for IO pin 15, rest output
    pca9555SetInputDirection(1 << 15);

    // LED animation loop
    while (1) {
        // if button is pressed, invert output
        int xor;
        if (pca9555GetInput() & 0x8000) {
            xor = 0;
        } else {
            xor = 0xffff;
        }
        
        // set current output
        pca9555SetOutput(v ^ xor);

        // animate LED position
        if (directionLeft) {
            v <<= 1;
        } else {
            v >>= 1;
        }
        if (v == 0x6000) {
            directionLeft = 0;
        }
        if (v == 3) {
            directionLeft = 1;
        }

        // wait 100 ms for next animation step
        usleep(100000);
    }

    // close Linux I2C device
    i2cClose();

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunjing_/article/details/79818269
I2C