Keil Logo

I²C デバイスのシミュレーション

指定したシグナル関数を使用して、I²C バスに接続されているハードウェアコンポーネントを実装できます。以下の例は、I²C メモリ(NXP PCF8570 のように 256 バイト)をシミュレートするシグナル関数を示します。

I²C メモリスレーブアドレスは、SADR 変数を介して設定されます。次に例を示します。

SADR = 0x3F// I²C Memory Slave Address

シグナル関数は、次のように[コマンド](Command)ウィンドウから呼び出されます。

I2C_Memory()

I²C メモリがメモリ領域 V:0 .. V:0xFF にマップされます。

シミュレータが I2C_OUT VTReg で START 状態を検出したら、次のバイトはアドレスバイトとして解釈されます。このアドレスバイトには、ビット 7 .. 1 に 7 ビットのスレーブアドレスが含まれ、ビット 0 に方向 (0 = 書き込み、1 = 読み出し)が含まれます。

  • スレーブメモリがアドレス指定されると、メモリデバイスが ACK をマイクロコントローラに送信します。
  • 方向ビットが '1'(メモリ読み出し)の場合、マイクロコントローラは I2C_IN VTReg を介してメモリから(各読み出しバイトの後に自動的に増加する現在のアドレスから)データバイトを読み出します。マイクロコントローラは、追加のデータバイトを読み出す必要がある場合は各バイトの後に ACK をメモリデバイスに送信します。これが最後のデータバイト読み出しの場合は NACK が送信されます。
  • 方向ビットが '0'(メモリ書き込み)の場合、マイクロコントローラは、新しいメモリアドレスを含むバイトを最初に送信します(メモリは ACK を返す必要があります)。次に、マイクロコントローラは、メモリに書き込まれるデータバイトを(各書き込みバイトの後に自動的に増加する現在のアドレスに)送信します。メモリデバイスは、各バイトの受信後に ACK を返す必要があります。
// Simulation of I²C Memory (Slave): like NXP PCF8570 (256 byte I²C RAM)

MAP V:0,V:0xFF READ WRITE                    // Map User Memory region

DEFINE int SADR                              // Slave Address

signal void I2C_Memory (void) {
  unsigned long adr;

  adr = V:0;
  while (1) {
    wwatch (I2C_OUT);                        // Wait for data from Microcontroller
    while (I2C_OUT == 0x0100) {              // START detected
      wwatch (I2C_OUT);                      // Wait for data from Microcontroller
      if (I2C_OUT > 0xFF) continue;
      if ((I2C_OUT >> 1) != SADR) continue;  // test if Slave is addressed
      I2C_IN = 0xFF00;                       // ACK to Microcontroller
      if (I2C_OUT & 1) {                     // Slave Read
        while (1) {
          I2C_IN = _RBYTE(adr);              // Read Byte from Memory
          adr++;                             // Increment Address
          wwatch (I2C_OUT);                  // Wait for ACK from Microcontroller
          if (I2C_OUT != 0xFF00) break;
        }
      }
      else {                                 // Slave Write
        wwatch (I2C_OUT);                    // Wait for data from Microcontroller
        if (I2C_OUT > 0xFF) continue;
        adr = I2C_OUT | V:0;                 // Set Memory Address
        I2C_IN = 0xFF00;                     // ACK to Microcontroller
        while (1) {
          wwatch (I2C_OUT);                  // Wait for data from Microcontroller
          if (I2C_OUT > 0xFF) break;
          _WBYTE (adr, I2C_OUT);             // Store Byte in Memory
          adr++;                             // Increment Address
          I2C_IN = 0xFF00;                   // ACK to Microcontroller
        }
      }
    }
  }
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.