[[FrontPage]]

2008/10/21 からのアクセス回数 &counter;

#contents

I2Cマスターが正常に動作したので、今度はI2Cスレーブの動作確認をします。
マスターのところで、つまずいてHCS08マイコンでIC2マスターを組み立てたので
これを利用してI2C通信のテストをすることにしました。(災い転じて福となす)

** 回路の説明 [#h351ecd4]
ATmega88とHCS08の接続は、以下の通りです。

#ref(0.jpg);

** スレーブのプログラム [#vf1022a5]
スレーブの処理は、TWIによる割り込み処理で行われ、AVRlibでは割り込み時に呼ばれる
コールバックルーチンを登録します。

- i2cSetSlaveReceiveHandlerでスレーブに送られたデータを読み込むコールバックを登録
- i2cSetSlaveTransmitHandlerでマスターに送るデータをセットするコールバックを登録

します。

*** 割り込み処理の間はUARTのデバッグプリントが使えない [#ka7bb08d]
当然のことですが、やはり間違えてしました。割り込み処理は、できるだけ短時間で割り込み
元にリターンする必要があるので、UARTを使ったデバッグプリントが使えません。

そこで、グローバル変数cmdにデバッグプリントの命令をセットし、mainの無限ループで
データのチェックプリントを出力することにしました。

*** プログラムソース [#p2901c2b]
I2Cスレーブの処理は、

+ I2Cの初期化
+ スレーブのアドレスをセット
+ I2C通信の受信と送信時のコールバック関数を登録

だけです。

- 受信コールバック関数では、受信データをローカルバッファにコピー
- 送信コールバック関数では、LM73の温度データと同じ2バイトのデータを送信

することにします。

プログラムソースは以下の通りです。
#pre{{
#include "global.h"		// include our global settings
#include "uart.h"		// include uart function library
#include "rprintf.h"	// include printf function library
#include "i2c.h"		// include i2c support

#define LOCAL_ADDR	(0x05<<1)
#define	CB_W	(0)	// send from master
#define CB_R	(1) // read by master

char	cmd=0;
u08	localBuffer[20];
u08	localBufferLength;

// slave operations
void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
{
	int i;
	
	cmd = 'r';	
	
	// copy the received data to a local buffer
	for(i=0; i<receiveDataLength; i++)
	{
		localBuffer[i] = *receiveData++;
	}
	localBufferLength = receiveDataLength;
}

u08 i2cSlaveTransmitService(u08 transmitDataLengthMax, u08* transmitData)
{
	cmd = 't';
	
	transmitData[0] = 0x0D;
	transmitData[1] = 0xE0;
	localBufferLength = 2;
	
	return localBufferLength;
}

int main(void)
{	
	int i;
	int c;
	
	uartInit();
	uartSetBaudRate(9600);
	rprintfInit(uartSendByte);
	rprintf("Start I2C Salve\n");
	
	i2cInit();
	i2cSetLocalDeviceAddr(LOCAL_ADDR, FALSE);
	i2cSetSlaveReceiveHandler( i2cSlaveReceiveService );
	i2cSetSlaveTransmitHandler( i2cSlaveTransmitService );
	
	rprintf("wait master call\n");
	
	while(1) {
		if (cmd == 'r') {
			rprintf("recieve data: ");
			for(i=0; i<localBufferLength; i++)
			{
				rprintf("%x", localBuffer[i]);
			}
			rprintf("\n");
			cmd = 0;
		}
		else if (cmd == 't') {
			rprintf("transmit dummy data\n");
			cmd = 0;
		}
	}

	return 0;
}
}}

** 操作確認 [#v8c4756a]
実際に接続して動かしてみると

#pre{{
$jerm -b 9600 -p none -s 1 -d 8 /dev/u.usbserial-A5002yHm 
途中省略
Start I2C Salve
wait master call
recieve data: 000400E0
recieve data: 0000
transmit dummy data
}}

と出力される。rprintfの%xは、2バイト分を出力するので、実際には04E0を受信しています。



** コメント  [#c5865721]
この記事は、

#vote(おもしろかった,そうでもない,わかりずらい)

皆様のご意見、ご希望をお待ちしております。

#comment_kcaptcha

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc