2011-09-21 1682 views
6

幾天前我在Microchip論壇發佈了這個消息(here),但唯一的迴應是蟋蟀。 下面的I2C代碼大部分時間工作,但偶爾在上電時會出現總線衝突(BCLIF),I2C模塊無法在BCLIF後恢復。 I2C線上拉3.3K歐姆。 使用REALICE和斷點我可以看到i2c_write()重置BCLIF並在BCLIF置位時返回FALSE。 我已經使用示波器來驗證I2C總線是否平整。 當i2c_write()返回FALSE時,重新初始化PIC18F25K20 I2C模塊(請參閱下面的init_i2c())不會有幫助。 PIC18F25K20 I2C連接到單個從器件(MCP4018 I2C數字POT)。 我在以前的PIC18項目中使用了相同的代碼而沒有問題,所以我更換了MCP4018懷疑壞的部分,但沒有看到任何區別。 PIC18F25K20 I2C模塊在鎖定時是否有復位的方法?如何恢復I2C總線衝突BCLIF?

void init_i2c(I2C_BAUD_RATE baud_rate, float freq_mhz) 
{ 
    UINT32 freq_cycle; 
    /* Reset i2c */ 
    SSPCON1 = 0; 
    SSPCON2 = 0; 
    PIR2bits.BCLIF = 0; 
    /* Set baud rate */ 
    /* SSPADD = ((Fosc/4)/Fscl) - 1 */ 
    freq_cycle = (UINT32) ((freq_mhz * 1e6)/4.0); 
    if (baud_rate == I2C_1_MHZ) 
    { 
     SSPADD = (UINT8) ((freq_cycle/1000000L) - 1); 
     SSPSTATbits.SMP = 1;  /* disable slew rate for 1MHz operation */ 
    } 
    else if (baud_rate == I2C_400_KHZ) 
    { 
     SSPADD = (UINT8) ((freq_cycle/400000L) - 1); 
     SSPSTATbits.SMP = 0;  /* enable slew rate for 400kHz operation */ 
    } 
    else /* default to 100 kHz case */ 
    { 
     SSPADD = (UINT8) ((freq_cycle/100000L) - 1); 
     SSPSTATbits.SMP = 1;  /* disable slew rate for 1MHz operation */ 
    } 
    /* Set to Master Mode */ 
    SSPCON1bits.SSPM3 = 1; 
    SSPCON1bits.SSPM2 = 0; 
    SSPCON1bits.SSPM1 = 0; 
    SSPCON1bits.SSPM0 = 0; 
    /* Enable i2c */ 
    SSPCON1bits.SSPEN = 1; 
} 
BOOL i2c_write(UINT8 addr, const void *reg, UINT16 reg_size, const void *data, UINT16 data_size) 
{ 
    UINT16 i; 
    const UINT8 *data_ptr, *reg_ptr; 

    /* convert void ptr to UINT8 ptr */ 
    reg_ptr = (const UINT8 *) reg; 
    data_ptr = (const UINT8 *) data; 
    /* check to make sure i2c bus is idle */ 
    while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)) 
     ; 
    /* initiate Start condition and wait until it's done */ 
    SSPCON2bits.SEN = 1; 
    while (SSPCON2bits.SEN) 
     ; 
    /* check for bus collision */ 
    if (PIR2bits.BCLIF) 
    { 
     PIR2bits.BCLIF = 0; 
     return(FALSE); 
    } 
    /* format address with write bit (clear last bit to indicate write) */ 
    addr <<= 1; 
    addr &= 0xFE; 
    /* send out address */ 
    if (!write_byte(addr)) 
     return(FALSE); 
    /* send out register/cmd bytes */ 
    for (i = 0; i < reg_size; i++) 
    { 
     if (!write_byte(reg_ptr)) 
      return(FALSE); 
    } 
    /* send out data bytes */ 
    for (i = 0; i < data_size; i++) 
    { 
     if (!write_byte(data_ptr)) 
      return(FALSE); 
    } 
    /* initiate Stop condition and wait until it's done */ 
    SSPCON2bits.PEN = 1; 
    while(SSPCON2bits.PEN) 
     ; 
    /* check for bus collision */ 
    if (PIR2bits.BCLIF) 
    { 
     PIR2bits.BCLIF = 0; 
     return(FALSE); 
    } 
    return(TRUE); 
} 
BOOL write_byte(UINT8 byte) 
{ 
    /* send out byte */ 
    SSPBUF = byte; 
    if (SSPCON1bits.WCOL)  /* check for collision */ 
    { 
     return(FALSE); 
    } 
    else 
    { 
     while(SSPSTATbits.BF) /* wait for byte to be shifted out */ 
      ; 
    } 
    /* check to make sure i2c bus is idle before continuing */ 
    while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)) 
     ; 
    /* check to make sure received ACK */ 
    if (SSPCON2bits.ACKSTAT) 
     return(FALSE); 
    return(TRUE); 
} 
+1

我看不到將SDA和SCL引腳配置爲輸入的代碼。 –

+0

您是否可以嘗試交換啓動條件啓動並首先檢查i2c_write()中的總線衝突,並在出現此問題之間連續幾次執行此功能,並且有一些小的延遲時間?然後會發生什麼? –

+0

另外,如果您的示波器帶有自動觸發器,它可能非常方便,因此您可以監視上電後SDA線的行爲。數據表說明:*如果在開始條件開始時,SDA和SCL引腳已經採樣爲低電平,或者如果在啓動條件期間,SCL線在SDA線驅動爲低電平之前被採樣爲低電平,則會發生總線衝突總線衝突中斷標誌BCLIF置1,中斷啓動條件並將I2C模塊復位到空閒狀態*。 –

回答

7

This Errata需要添加到PIC18F25K20勘誤表。

PIC18F2455/2550 /四千五百五十零分之四千四百五十五啓A3芯片勘誤表

17模塊:MSSP

已經觀察到的是以下一個上電覆位,I2C模式可能無法正確 通過初始化只需將SCL和SDA引腳配置爲 輸入或輸出即可。這隻能在幾個獨特的系統環境中看到。

試生產系統的統計顯著樣品的測試,在整個電壓和電流範圍 應用的電源的,應說明如果一個系統是易受 這個問題。

周圍

工作在配置模塊,用於I2C 操作:

  1. 配置SCL和SDA引腳爲輸出通過清除其 對應TRIS位。
  2. 通過清零相應的LAT位強制SCL和SDA爲低電平。
  3. 在保持LAT位清零的同時,通過設置它們的TRIS位將SCL和SDA配置爲輸入 。

完成此操作後,使用SSPCON1和 SSPCON2寄存器像以前一樣配置正確的I2C模式。

+0

那麼,這個序列對你有用嗎? –

+0

@AndrejsCainikovs:是的。有效。直到明天才能接受這個答案。 – jacknad

2

PIC18F26K20/SS(版本B3)也出現同樣的錯誤,也需要添加到它的勘誤表中。

2

我不知道你的具體情況,但我遇到了一個問題,一旦其中微控制器被出來的方式早(VDD穩定I2C總線上多之前)復位。因此,uController開始在目標可以正常工作之前讀取/寫入數據,導致各種I2C操作問題。