FrontPage

2008/10/20 からのアクセス回数 9840

エレキジャックNo.8の第2部ではI2Cを使って温度を測る例がありました。 ここでは、AVRlibを使ってこの例題を試してみることにします。

回路

今回テストする回路は、137Pの図2-1

I2C_cirkit.jpg

のMC9S08QG8CPBEをATmega88に置き換えた回路です。

ATmega88のデータシートから、各ピン番号は以下の通りです。

  • TxDは、3番(左上から3番目)
  • RxDは、2番(左上から2番目)
  • SCLは、28番(右上から1番目)
  • SDAは、27番(右上から2番目)
  • VCCは、7番
  • GNDは、8番

です。

温度ICであるLM73は、

  • GNDは、2番
  • VDDは、3番
  • SCLは、4番
  • SDAは、6番

です。

これをブレッドボードで配置したのが以下の写真です。

3.jpg

ISPの線も一緒にセットしたので、ちょっと見にくいですね!

プログラム

I2Cのプログラムも、examples/i2cからコピーして、作ります。

メインのi2ctest.cは、以下のようになります。

#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	I2C_ADDRS_LM73	(0x4C)
#define	CB_W	(0)	// send from master
#define CB_R	(1) // read by master

int	cmd=0;

static u08 buf[2];
void initSensor(void) {	
	rprintf("enter initSensor\r\n");	

	i2cInit();

	buf[0] = 4;
	buf[1] = 0x60|0x80;
	i2cMasterSend(I2C_ADDRS_LM73<<1 | CB_W, 2, buf);

	buf[0] = buf[1] =  0;
	i2cMasterSend(I2C_ADDRS_LM73<<1 | CB_W, 2, buf);
}

void cmdTempRead(void) {
	long	temp10;

	buf[0] = buf[1] = 0;
	i2cMasterReceive(I2C_ADDRS_LM73<<1 | CB_R, 2, buf);

	temp10 = buf[0]*256 + buf[1];
	temp10 = temp10 * 10 / 128;
	rprintf(".M=%d\r\n", temp10);	
}

void serCmdProc(char ch) {
	switch (ch) {
		case '\b':
			rprintf("\b \b");
			break;
		case '\r':
			rprintf("\r\n");
			if (cmd == 'M')
				cmdTempRead();
			cmd = 0;
			rprintf("Command> ");
			break;
		case '\n':
			break;
		default:
			uartSendByte(ch);
			cmd = ch;
	}
}

int main(void)
{
	int	c=0;
	
	uartInit();
	uartSetBaudRate(9600);
	rprintfInit(uartSendByte);
	rprintf("Hello World\n");
	
	initSensor();

	rprintf("Command> ");
	while(1) {
		while(!c) uartReceiveByte(&c);
		serCmdProc(c);
		c = 0;
	}

	return 0;
}

ここで、i2cMasterSend、i2cMasterReceiveのI2Cアドレスには、左に1ビットシフトした値を セットしていることに注意してください。

もし、インタラプトを使用しないのなら、i2cMasterSendNI、i2cMasterReceiveNIに置き換えて ください。

makefileの変更点

makefileは、以下の点を変更します。

  • MCU = atmega88
  • TRG = i2ctest
  • SRC = $(AVRLIB)/buffer.c $(AVRLIB)/uart.c $(AVRLIB)/rprintf.c $(AVRLIB)/i2c.c $(TRG).c

の3カ所です。

最初のつまずき

最初、2cMasterSend、i2cMasterReceiveのI2Cアドレス指定を間違えており、 I2C_ADDRS_LM73をそのままアドレスとして渡していたので、何の値も帰ってきませんでした。

問題の切り分け

そこで、何がわるいのか問題を切り分けることにしました。

  • LM73の使い方
  • I2Cの信号が正しくでているか

使用したLM73ははじめて使うデバイスなので正しく動作しているのかをMC9S08QG8CPBEを使った 例題でチェックすることにしました。

6.jpg

MC9S08QG8CPBEの開発環境であるUSBSPYDER08には、オンチップデバッグ機能があり、ステップ毎に 動作を確認することができます。

この結果LM73は正しく動いていることが確認できました。

次に、I2Cの信号がでているのかどうかです。 そこで、最後の手段としてオシロスコープで波形を見ることにしました。

5.jpg

のように1バイトの信号がでています。 しかし、LM73からは何も返ってきません。

別のライブラリを使ってみる

今度は、別のライブラリを使うことにしました。 http://www.eleki-jack.com/mycom2/avr/avri2c/

この結果、16進数で990Dの2バイトが返ってきますが、値は正しくありません。

そこで、再びオシロスコープでみると

I2C_recieve_data.jpg

となり、最初の99は、LM73のアドレス(R)でその次に0D(温度の最初の1バイト)が 返ってきていることが分かりました。

頭を冷やして!

そこで、最初のオシロスコープの画像と2番目の画像を比べてみるとアドレスビットが1ビット シフトしていることが分かります。

i2cMasterSend、i2cMasterReceiveのI2Cアドレスには、左に1ビットシフトした値をセットしなくてならない ことに気づきました。

結論

AVRlibを使ってI2Cも非常に簡単に使えることが確認できました。

コメント

この記事は、

選択肢 投票
おもしろかった 24  
そうでもない 0  
わかりずらい 0  

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


(Input image string)


添付ファイル: fileI2C_recieve_data.jpg 749件 [詳細] file5.jpg 734件 [詳細] file6.jpg 695件 [詳細] file3.jpg 723件 [詳細] fileI2C_cirkit.jpg 775件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-03-26 (木) 20:01:27 (821d)
SmartDoc