7

数日前にこれをマイクロチップ フォーラム (ここ) に投稿しましたが、反応はコオロギだけでした。以下の I2C コードはほとんどの場合機能しますが、電源投入時にバス衝突 (BCLIF) が発生し、I2C モジュールが BCLIF 後に回復できないことがあります。I2C ラインは 3.3K オームでプルアップされています。REALICE とブレークポイントを使用するとi2c_write()、BCLIF が設定されている場合に BCLIF がリセットされ、FALSE が返されることがわかります。スコープを使用して、I2C バスがフラットラインになっていることを確認しました。PIC18F25K20 I2C モジュール (下記init_i2c()参照)の再初期化i2c_write()FALSE を返しても役に立ちません。PIC18F25K20 I2C は、単一のスレーブ デバイス (MCP4018 I2C デジタル POT) に接続されています。以前の PIC18 プロジェクトでこの同じコードを問題なく使用したので、不良部品を疑って MCP4018 を交換しましたが、違いは見られません。PIC18F25K20 I2C モジュールがロックされたときにリセットする方法はありますか?

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); 
} 
4

4 に答える 4

10

このエラッタは PIC18F25K20 エラッタに追加する必要があります。

PIC18F2455/2550/4455/4550 Rev. A3 シリコン エラッタ

17 モジュール: MSSP

パワーオン リセットの後、SCL および SDA ピンを入力または出力として設定しただけでは、I2C モードが適切に初期化されない場合があることが確認されています。これは、いくつかの固有のシステム環境でのみ見られます。

アプリケーションの電源の電圧と電流の範囲全体で、統計的に有意な試作システムのサンプルをテストすると、システムがこの問題の影響を受けやすいかどうかがわかります。

回避策

I2C 動作用にモジュールを設定する前に:

  1. 対応する TRIS ビットをクリアして、SCL ピンと SDA ピンを出力として設定します。
  2. 対応する LAT ビットをクリアして、SCL と SDA を強制的にローにします。
  3. LAT ビットをクリアしたまま、TRIS ビットをセットして SCL と SDA を入力として設定します。

これが完了したら、SSPCON1 および SSPCON2 レジスタを使用して、以前と同様に適切な I2C モードを設定します。

于 2011-09-21T21:03:13.863 に答える
2

これと同じバグが PIC18F26K20/SS (リビジョン B3) でも発生しているようで、エラッタにも追加する必要があります。

于 2011-09-27T23:08:41.803 に答える
2

私はあなたの詳細を知りませんが、マイクロコントローラが早期にリセットされていた問題に遭遇しました(VddがI2Cバスで安定するずっと前に)。そのため、ターゲットが適切に機能する前に、uController がデータの読み取り/書き込みを開始し、あらゆる種類の I2C 操作上の問題が発生しました。

于 2011-11-14T19:46:25.917 に答える