denshikobo’s blog

PICプログラミングやPCの操作で感じた日々の由無し事を綴ります

Oscilogiの大きな課題が解決した

(2016.08.21)
そこそこ動いて、それなりに使えているOscilogi410なんですが、実は大きな課題を抱えていました。

bcmlib_for_javaは1回に送受できるデータ量に1024バイトの制限があります。Oscilogi410の計測データは(オシロとロジアナ合わせて)24kバイトなので、24回に分けて計測データを取り込んでいます。

しかし、1024バイトのデータ読み出しに対して、何故か『PIC側のポインタが1025進んでしまう』という現象を生じていました。やむを得ず、1024バイト読み取る度にOsci_logi_Console(JAVAプログラム)からPICのポインタを一つ戻すコマンドを送って、不具合を回避する処置を講じていたのです。何が悪いのか判らず、少しだけBCM2835ライブラリを疑ったりしていました(ゴメン Mike )。

動き出したOscilogi410を使って、I2Cの動作を調べてみることにしました。
テスト・プログラムはこんな感じです。

(データ受信コマンドを送り、10バイト読み出す)
public class I2c_test {
    public static void main(String args) {
        String send_string = "RCV 0";
        byte
receive_buff = new byte[16];
        
        bcm2835.bi_init(args[0]);
        bcm2835.i2c_begin();
        bcm2835.i2c_setSlaveAddress( (byte)0x31 );
        bcm2835.i2c_set_baudrate( 100000 );
        bcm2835.ope_sync();
        byte ret = bcm2835.i2c_write( send_string, send_string.length() );
        ret = bcm2835.i2c_read( receive_buff, 10 );
        if( ret == 0 )try {
         String rec;
           rec = new String( receive_buff , "UTF-8");
            System.out.print("I2C receive="+rec +"\n");
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(I2c.class.getName()).log(Level.SEVERE, null, ex);
            rec = "";
        }
        System.out.print("i2c_read ="+(int)ret+"\n");
        bcm2835.i2c_end();
        bcm2835.bi_close();
    }
}

計測したI2Cの信号は正しく、5バイト送信し10バイト受信する様子を示していました。
つまりBCM2835ライブラリは正しく動作しているのです。(疑ってゴメン Mike )

自分で書いたPIC側のI2Cドライバの動作をdebug_dumpで調べ・・・

 void __ISR(_I2C_2_VECTOR, ipl1AUTO) _IntHandlerDrvI2CInstance0(void)
{
    static unsigned char i2c_single_buff;
    if( !PLIB_I2C_SlaveReadIsRequested(I2C_ID_2) )
    {
       if( PLIB_I2C_SlaveAddressIsDetected(I2C_ID_2) )
       {
         DRV_I2C0_SetUpByteRead();
         DRV_I2C0_ByteRead();
       }
       else
       {
         DRV_I2C0_SetUpByteRead();
          i2c_single_buff = DRV_I2C0_ByteRead();
          if( i2c_single_buff == 'B')
          {
              break_flag = FLAG_ON;
          }
          put_receive_buff(i2c_single_buff);
       }
       status_from_master();
    }
    else if ( PLIB_I2C_SlaveAddressIsDetected(I2C_ID_2) )
    {
        DRV_I2C0_SetUpByteRead();
        DRV_I2C0_ByteRead();
        DRV_I2C0_ByteWrite( get_send_data() );
        PLIB_I2C_SlaveClockRelease(I2C_ID_2);
        status_to_master();
    }
    else
    {
        if( I2C2STATbits.ACKSTAT == 0 )<==これを追加した
        {
          DRV_I2C0_ByteWrite(get_send_data());
          PLIB_I2C_SlaveClockRelease(I2C_ID_2);
          status_to_master();
        }
    }
    PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_I2C_2_SLAVE);
    PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_I2C_2_ERROR);
}

1バイト送信した後のI2C割込で、I2C2STATbits.ACKSTATが1になったときは次のデータは読み出さない、という処理に替えてようやくデータポインタが一つ余計に進んでしまうという課題が解決しました。

やれやれ