SSブログ

I2CでLEDピカピカ ユーザ・ドライバ版 [ColdFire V2]このエントリーを含むはてなブックマーク#

2073158

ユーザ・ドライバが使えるようになったので、「I2CでLEDピカピカ」を移植してみました。

元記事

この記事の元になった記事は、以下の通りです。

メイン・プログラム

まずは、 SilentC で記述されたメイン・プログラムを変更しました。

main(){
  int  i;
  char *cmd = MemoryAlloc(4);
  UserDriver(0, 0); // i2c_init
  cmd[0] = 0x20; // address
  cmd[1] = 0x03; // command (DDR)
  cmd[2] = 0x00; // data
  UserDriver(1, cmd); // i2c_send
  #stop 0
  i=0;
  for(;;){
    if(Getc(0)=='q')break;
    Sleep(25);
    cmd[1] = 0x01; // command (DATA)
    cmd[2] = 0xEF << i; // data
    UserDriver(1, cmd); // i2c_send
    i = (i + 1) & 3;
  }
  MemoryFree(cmd);
}

ユーザ・ドライバとして、I2Cモジュールを操作するための二つのベクタを用意しています。

  • #0 - i2c_init : I2C モジュールを初期化します。
  • #1 - i2c_send : I2C モジュールにコマンドをデータを送ります。

コマンドを送るためのデータは、 char 型の配列として渡します。 配列には、I2Cデバイスのアドレス、デバイスへのコマンド、デバイスへのデータの3バイトのデータが格納されます。

ユーザ・ドライバの記述

このメイン・プログラムから呼び出すためのユーザ・ドライバは、こんな風になりました。

#include "support_common.h" /* include peripheral declarations and more */

uint32 i2c_init(uint32 arg);
uint32 i2c_send(uint32 arg);

asm void jump_table(void) {
  jmp i2c_init      // Driver #0   
  jmp i2c_send      // Driver #1   
}

asm void SystemSleep(void) {
  move 0x210,a0
  jmp (a0)
}

uint32 i2c_init(uint32 arg) {
  #pragma unused(arg)
  // Configure ports.
  MCF_GPIO_PQSPAR =
    MCF_GPIO_PQSPAR_QSPI_CLK_SCL |
    MCF_GPIO_PQSPAR_QSPI_CS0_SDA;
  // Specify I2C clock rate.
  MCF_I2C_I2FDR =
    MCF_I2C_I2FDR_IC(0x38); // (x640)
  // Configure I2C module
  MCF_I2C_I2CR =
    MCF_I2C_I2CR_MTX |  // Transmit
    MCF_I2C_I2CR_IEN;   // I2C enable
}

uint32 i2c_send(uint32 arg) {
  uint8  address = ((uint8*)arg)[0];
  uint8  command = ((uint8*)arg)[1];
  uint8  data    = ((uint8*)arg)[2];

  while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) {
    SystemSleep(); // Wait for BUS idle
  }
  MCF_I2C_I2SR = 0x00; // Clear flags
  MCF_I2C_I2CR |= MCF_I2C_I2CR_MSTA; // START
  do {
    MCF_I2C_I2DR = (uint8)(address << 1); // WRITE for 0100000
    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) {
      SystemSleep(); // Wait for IIF
    }
    if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) {
      break; // Quit if no ACK
    }
    MCF_I2C_I2SR = 0x00; // Clear flags
    MCF_I2C_I2DR = command; // command code
    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) {
      SystemSleep(); // Wait for IIF
    }
    if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) {
      break; // Quit if no ACK
    }
    MCF_I2C_I2SR = 0x00; // Clear flags
    MCF_I2C_I2DR = data; // data to be sent
    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) {
      SystemSleep(); // Wait for IIF
    }
  } while (0);
  MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA; // STOP
}

CodeWarrior 純正のシンボルを使っているので、かなり長ったらしくなりました。

ユーザ・ドライバから呼び出している "SystemSleep" 関数は、アセンブラで記述された分岐命令になっており、 SilentMoon オペレーティングシステムを呼び出します。 また、 I2C の通信は、機械語の実行に比べて長い時間を要します。 このため、通信終了待ちループでは "SystemSleep" 関数を呼び出して、他のスレッドに実行権を明け渡しています。

メイン・プログラムを実行すると、LEDが点滅を始めます。

プロジェクト・アーカイブ

ユーザ・ドライバのプロジェクトは、これを CFCQ05.zip という名前で保存すると再現できます。

参考文献

Interface (インターフェース) 2008年 12月号 [雑誌]

Interface (インターフェース) 2008年 12月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/10/25
  • メディア: 雑誌
Interface (インターフェース) 2008年 09月号 [雑誌]

Interface (インターフェース) 2008年 09月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/07/25
  • メディア: 雑誌

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。