Raspberry Pi > C > RPi_i2c_comm_180227: v1.1 > clock stretching 지원(소프트웨어 I2C)

10128 단어 embeddedCI2CRPiAD2
운영 환경
Raspberry Pi 2 Model B (以下RPi)
Raspbian Jessie
gcc (Raspbian 4.9.2-10) 4.9.2
とあるI2Cセンサー (clock strecthingがある通信)
Analog Discovery 2 (以下AD2)

지난번


  • Raspberry Pi > C > RPi_i2c_comm_180227: v1.0 > 센서에서 데이터를 읽을 때까지 | 비 RPi로 이식 및 작동

  • I2C 통신의 센서와의 통신을 RPi로 c 실장했다.

    이번에



    어떤 I2C 센서(clock strecthing이 있는 통신) 대응을 위해, clock strecthing을 고려한 ACK 접수로 변경.

    Clock stretching의 타이밍 다이어그램은 아래 등 참조.
    ぇtps://ぇあrん. s파rk분. 코 m / 쓰리 아 ls / 2c

    GitHub 리포지토리



    v1.1@GitHub

    처리 개요


    RPi_i2c_comm_CLKSTR_180712.c 라는 파일에서 Clock stretching을 고려한 I2C 통신을 하고 있다.

    구체적으로는 send_stopContinuousMeasurement()의 내용이 된다.
    i2c_clockStretching_IsACK() 를 이번에 추가해, 이 함수내에서 SCL=Low 상태를 확인하도록 하고 있다.

    RPi_i2c_comm_CLKSTR_180712.c
    ...
    static void send_stopContinuousMeasurement(int slvAdr)
    {
        // write header
        i2c_SendStartCondition(/* withInit=*/true);
        i2c_SendSlaveAddress(slvAdr, /*bfRead=*/false);
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
        // send command
        i2c_SendData(0x06); // Function Code
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendData(0x00); // Address MSB
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendData(0x37); // Address LSB
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendData(0x00); // Content MSB
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendData(0x01); // Content LSB
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendData(0xF0); // CRC LSB
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendData(0x64); // CRC MSB
        if (i2c_clockStretching_IsACK(kMaxloop_SCL_stretch)) {
            printf("ACK\n");
        };
    
        i2c_SendStopCondition();
    }
    ...
    

    i2c_clockStretching_IsACK()



    i2c_comm_180302.c
    ...
    bool i2c_clockStretching_IsACK(int maxloop)
    {
        bool pinIsH;
        int cnt=0;
    
        i2c_gpio_setSCL_level(GPIO_LOW);
        i2c_gpio_setSDA_direction(GPIO_IN);
        myDelay();
        i2c_gpio_setSCL_level(GPIO_HIGH);
    
        // { clock streching
        i2c_gpio_setSCL_direction(GPIO_IN);
        myDelay();
        while(true) {
            if(i2c_gpio_isSCL_high()) {
                break;
            }
            if(cnt > maxloop) {
                i2c_gpio_setSCL_direction(GPIO_OUT);  // end clock stretching
                return false;
            }
            myDelay();
            cnt++;
        }
        // } clock streching
    
        pinIsH = i2c_gpio_isSDA_high();
        myDelay();
    
        // set after reading SDA
        // (will fail to get ACK when set before reading SDA)
        i2c_gpio_setSCL_direction(GPIO_OUT);  // end clock stretching
    
        return (pinIsH == BOOL_ACK);    
    }
    ...
    

    비고 : 상기에서 i2c_gpio_setSCL_direction(GPIO_OUT);는 SDA 판독 후이다. SDA 읽기 전에 SCL의 방향을 변경하는 구현에서는 ACK를 수신할 수 없었다.

    로직 확인



    상기 커맨드 발행시의 파형을 Analog Discovery 2 (이하 AD2)로 확인했다.



    커맨드 송신 후의 ACK를 받을 수 있다.

    좋은 웹페이지 즐겨찾기