ведомые устройства мешают при совместном использовании линии шины i2c

Я новичок в микроконтроллерах и использую PIC18F4620 (ведущий) для связи с датчиком цвета TCS34725 (ведомый) и часами реального времени DS1307 (ведомый, на плате) через I2C. Прямо сейчас я испытываю какое-то вмешательство между этими двумя. Если я запускаю любой из них по отдельности, а другой не подключен к порту, то он работает нормально. Если другой подключен, даже не проинициализировавшись, то зависает в процессе чтения. Их подчиненные адреса не совпадают, поэтому я не понимаю, почему это происходит. Это код датчика цвета.

 /* Initialize LCD. */
initLCD();

I2C_Master_Init(100000); //Initialize I2C Master with 100 kHz clock

while(1){
    /*read the id */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10010010);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    id = I2C_Master_Read(NACK);
    I2C_Master_Stop();   
    __delay_ms(200);

    /* Configure the RGBC Time register */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10000001);
    I2C_Master_Write(0);
    I2C_Master_Stop();
    __delay_ms(200);

    /* Configure the Control register */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10001111);
    I2C_Master_Write(0);
    I2C_Master_Stop();
    __delay_ms(200);

    /* Configure the Control register */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10000000);
    I2C_Master_Write(0b00001011);
    I2C_Master_Stop();
    __delay_ms(200);

    /* Read red data */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10010110);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    tmp[0] = I2C_Master_Read(ACK);
    tmp[1]= I2C_Master_Read(NACK);
    I2C_Master_Stop();
    __delay_ms(1000);
    rC = (tmp[0])|(tmp[1]<<8);

    /* Read green data */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10011000);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    tmp[0] = I2C_Master_Read(ACK);
    tmp[1]= I2C_Master_Read(NACK);
    I2C_Master_Stop();
    __delay_ms(1000);
    gC = (tmp[0])|(tmp[1]<<8);

    /* Read blue data */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10011010);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    tmp[0] = I2C_Master_Read(ACK);
    tmp[1]= I2C_Master_Read(NACK);
    I2C_Master_Stop();
    __delay_ms(1000);
    bC = (tmp[0])|(tmp[1]<<8);

    /* Display data on the LCD */
    __lcd_home();
    __lcd_clear();
    printf("id: %d", id);
    __delay_ms(500);


    __lcd_clear();
    printf("r:%u,b:%u", rC, bC);
    __lcd_newline();
    printf("g:%u", gC);
    __delay_ms(1000);

    id = 0;
    rC = 0;
    bC = 0;
    gC = 0;
}

Это код для RTC

void main(void) {
   /* Write outputs to LATx, read inputs from PORTx. Here, all latche (LATx)
    * are being cleared (set low) to ensure a controlled start-up state. */  
    LATA = 0x00;
    LATB = 0x00; 
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;

    /* After the states of LATx are known, the data direction registers, TRISx
     * are configured. 0 --> output; 1 --> input. Default is  1. */
    TRISA = 0xFF; // All inputs (this is the default, but is explicated here for learning purposes)
    TRISB = 0xFF;
    TRISC = 0b10000000; /* RC3 is SCK/SCL (SPI/I2C),
                         * RC4 is SDA (I2C),
                         * RC5 is SDA (SPI),
                         * RC6 and RC7 are UART TX and RX, respectively. */
    TRISD = 0x00; // All output mode on port D for the LCD
    TRISE = 0x00;

    /************************** A/D Converter Module **************************/
    ADCON0 = 0x00;  // Disable ADC
    ADCON1 = 0b00001111; // Set all A/D ports to digital (pg. 222)

    /* Initialize LCD. */
    initLCD();

    I2C_Master_Init(100000); //Initialize I2C Master with 100 kHz clock
    /* Set the time in the RTC.
     * 
     * To see the RTC keep time, comment this line out after programming the PIC
     * directly before with this line included. */

    RTC_setTime();

    /* Declare local variables. */
    unsigned char time[7]; // Create a byte array to hold time read from RTC
    unsigned char i; // Loop counter

    /* Main loop. */
    while(1){
        /* Reset RTC memory pointer. */
        I2C_Master_Start(); // Start condition
        I2C_Master_Write(0b11010000); // 7 bit RTC address + Write
        I2C_Master_Write(0x00); // Set memory pointer to seconds
        I2C_Master_RepeatedStart(); // Start condition
        I2C_Master_Write(0b11010001); // 7 bit RTC address + Read
        for(i = 0; i < 6; i++){
            time[i] = I2C_Master_Read(ACK); // Read with ACK to continue reading
        }
        time[6] = I2C_Master_Read(NACK); // Final Read with NACK
        I2C_Master_Stop(); // Stop condition

        /* Print received data to LCD. */
        __lcd_home();
        printf("%02x/%02x/%02x", time[6],time[5],time[4]); // Print date in YY/MM/DD
        __lcd_newline();
        printf("%02x:%02x:%02x", time[2],time[1],time[0]); // HH:MM:SS
        __delay_ms(1000);
    }
}

void RTC_setTime(void){
    /* Writes the happynewyear array to the RTC memory.*/

    I2C_Master_Start();           // Start condition
    I2C_Master_Write(0b11010000); //7 bit RTC address + Write
    I2C_Master_Write(0x00);       // Set memory pointer to seconds

    /* Write array. */
    for(char i=0; i<7; i++){
        I2C_Master_Write(happynewyear[i]);
    }

    I2C_Master_Stop();            //Stop condition
}
Какое значение имеют ваши подтягивающие резисторы I2C? У вас есть осциллограф или простой логический анализатор, который можно использовать для просмотра шины? А если даже не делать никаких транзакций, а просто мерить напряжение на шине мультиметром? Когда у вас есть подключенное, но неиспользуемое устройство, вы все равно даете ему питание, верно?
@ChrisStratton - диапазон PIC18F имеет внутренние подтяжки, которые, я думаю, составляют ~ 40 тыс., Что, предположительно, используется здесь, учитывая отсутствие упоминания о внешних подтягиваниях. Если это так, то этот вопрос потенциально является дубликатом electronics.stackexchange.com/questions/1849/… (ответ: более низкое сопротивление)
@ChrisStratton Подтягивающие резисторы предварительно встроены в плату разработки, которую я использую, которая составляет 10 тыс. У меня нет доступа к осциллографу, но я могу использовать его в понедельник. Да, я все еще даю неиспользованную мощность устройства.
@Jules Да, есть внутренние подтягивания, но я думаю, что их значение составляет 10 тысяч.
10к это немного. Попробуйте хотя бы в качестве эксперимента добавить еще 2,2К или хотя бы 4,7К.
Основываясь на формуле на electronics.stackexchange.com/questions/1849/… , 10 кОм подходит только для емкостей примерно до 100 пФ, которые вы можете легко получить с помощью нескольких устройств, особенно если вы соединяете отдельные модули с достаточно длинные провода. Для системы 5 В минимальное сопротивление составляет около 1,6 кОм. Попытка 2.2k определенно была бы разумной.
Почему вы говорите «TCS34725 (ведомое устройство) и DS1307 (ведомое устройство на плате)» ? Означает ли это, что TCS34725 не находится на той же плате, а подключен через провода? Тогда какой длины провода?
Рекомендация против использования внутренних подтягивающих резисторов для I2C: что произойдет, если я не буду использовать подтягивающие резисторы на линиях I2C?
Две части информации прольют свет на вашу проблему: (1) Схема. Если у вас нет доступа к пакету EDA, подойдет карандашный набросок. Но фото макетной платы не годится. (2) Скриншот осциллографа транзакции I2C, когда шина не работает. Еще один снимок экрана осциллографа для транзакции I2C, когда шина работает.
@ChrisStratton Большое спасибо, я решил проблему, добавив 1k подтягиваний.
Спасибо всем, я решил проблему, добавив 1к подтягиваний.
@sop: Нет, ты только что создал еще одну проблему, которая, по-видимому, еще не укусила тебя. Перестаньте гадать и беспорядочно тыкать в вещи. Остановитесь и на самом деле поймите , что происходит, что делает каждая часть и какие ограничения указаны в спецификации. Вам задали ряд вопросов, на большинство из которых вы не ответили. Этот веб-сайт работает в обе стороны. Добровольцы здесь помогут, но мы также хотим, в конце концов, понять, в чем на самом деле была проблема, как она была окончательно решена и т. д. Как только вы на самом деле ответите на вопросы, которые вам задавали, я могу объяснить, какую еще проблему вы сейчас создали.

Ответы (1)

Я не смотрел код, потому что, во-первых, это набор высокоуровневых вызовов, не показывающих, что на самом деле происходит на уровне шины.

Однако, скорее всего, это проблема с электрикой. Возможно, вторые слейвы загружают линии шины так, что что-то не работает. Вы ничего не сказали о битрейте или подтягиваниях. Это важно. Возможно, подтяжки имеют слишком высокий импеданс и/или вы пытаетесь использовать слишком высокую скорость передачи данных. Посмотрите на линии с прицелом и посмотрите, что происходит на самом деле. Удостоверьтесь, что когда каждая линия поднимается вверх, она попадает туда надежно в течение небольшого времени.

Большое спасибо, я решил проблему, добавив 1к подтягиваний.