I2CでLEDピカピカ ユーザ・ドライバ版 [ColdFire V2]
ユーザ・ドライバが使えるようになったので、「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月号 [雑誌]
- 作者:
- 出版社/メーカー: CQ出版
- 発売日: 2008/10/25
- メディア: 雑誌
Interface (インターフェース) 2008年 09月号 [雑誌]
- 作者:
- 出版社/メーカー: CQ出版
- 発売日: 2008/07/25
- メディア: 雑誌
コメント 0