はじめまして、こんにちは。
H8/3687FとH8 Tiny Series BB64E Evaluation Boardを使用して、温度測定をするC言語のプログラムをコーディングしています。 その温度測定でIIC2通信を使用するのですが、その通信がどうにもうまくいきません。
途中MOV命令を使いI2Cバスコントロールレジスタ2(ICCR2)のBBSYとSCPを書き換えるのですが、ICCR2には書き込もうと思っているデータとは異なるデータが格納されます。
MOV命令につかう汎用レジスタ(今回使用するのはR4L)には正しい値が格納されているため、MOV命令がおかしいと踏んでいるのですが、どう対処すればよいのかわかりません。
そのため、どのように修正すればよいか教えてください。
宜しくお願い致します。
以下、プログラムのIIC2通信部分の関数です。
void reception_t(void) { unsigned int dmy;
IIC2.ICCR1.BYTE = 0x81; // ICE=1,CKS3~0 IIC2.ICMR.BIT.MLS = 0; // MLS IIC2.ICMR.BIT.WAIT = 0; // WAIT IIC2.SAR.BYTE = 0xF8; //スレーブアドレス:(1111100)+ I2C: (0)
while(IIC2.ICCR2.BIT.BBSY == 1){ ; }
IIC2.ICCR1.BIT.MST = 1; //マスタ IIC2.ICCR1.BIT.TRS = 1; //送信モード
#pragma asm //MOV開始条件発行 MOV #H'BD,R4L MOV R4L,@H'F749 #pragma endasm
while(IIC2.ICSR.BIT.TDRE == 0){} //TDRE=1まで待機 //3 IIC2.ICDRT = 0xF8; //スレーブアドレス(1111100)とR/W(0)を指定
while(IIC2.ICSR.BIT.TEND == 0){} // TEND=1 while(IIC2.ICIER.BIT.ACKBR == 1){ IO.PDR6.BIT.B7 = 1; } IIC2.ICCR1.BIT.MST = 1; //マスタ IIC2.ICCR1.BIT.TRS = 0; //受信モード
//***********************************************************//
IIC2.ICSR.BIT.TEND = 0; /* TENDクリア */ IIC2.ICCR1.BIT.MST = 0; /* マスタ受信モード切替, 500kHz */ IIC2.ICSR.BIT.TDRE = 0; /* TDREクリア */ IIC2.ICIER.BIT.ACKBT = 0; /* ACKBT=0を設定 */
dmy = IIC2.ICDRR; /* ダミーリード 受信開始 */
while(IIC2.ICSR.BIT.RDRF == 0){ /* データの受信完了待ち(受信データ転送時、RDRF=1) */ IO.PDR6.BIT.B6 = 1; } IIC2.ICIER.BIT.ACKBT = 1; /* 次の受信動作を禁止 */ IIC2.ICCR1.BIT.RCVD = 1;
temp_1 = IIC2.ICDRR; /* データリード(上位ビット、整数値) */
while(IIC2.ICSR.BIT.RDRF == 0){ /* データの受信完了待ち */ }
IIC2.ICSR.BIT.STOP = 0; /* STOPフラグクリア */
#pragma asm //MOV停止条件発行 MOV #H'3D,R4L MOV R4L,@H'F749 #pragma endasm
while(IIC2.ICSR.BIT.STOP == 0){ /* 停止条件生成待ち */ }
temp_2 = IIC2.ICDRR; /* データリード(下位ビット、小数値) */ IIC2.ICCR1.BIT.RCVD = 0; /* RCVDクリア */
IIC2.ICCR1.BYTE = 0xC1; /* スレーブ受信モード切替, 500kHz */ }
追記
インラインアセンブラはハードウェアマニュアルの「17.3.2 I 2 C バスコントロールレジスタ 2(ICCR2)」に従いインラインアセンブラを使用しています。
ハードウェアマニュアル: http://japan.renesas.com/products/mpumcu/h8/h8300h_tiny/h83687_h83687n/Documentation.jsp
チョコです。
H8は使ったことはありませんが、マニュアルのICCR2レジスタの
SCPビットの説明を見ると、「本ビットはリードすると常に1 が読み出されます。」
とありますが。
MOV命令ですが、無理してアセンブラで書かなくても良い気がします。
マニュアルにはMOV命令を使えと書いてありますが、意味を考えると同時に更新してねという捉え方だと思います。
逆の言い方をすれば、BIT操作命令で個別に設定しないでねという事です。
スタートコンディション発行のだめな例は
IIC2.ICCR2.BIT.BBSY = 1;
IIC2.ICCR2.BIT.SCP = 0;
で
IIC2.ICCR2.BYTE = (IIC2.ICCR2.BYTE & 0x3F) | 0x80);
のようにすれば、読み出された時にSCP(Bit6)が1なのを強制的に0にして、
たぶんアセンブラの最後の展開形がMOVになると思います。
インラインアセンブラを使用する意図がわかりませんが、
と
でレジスタの R4L の内容をぶっ壊してますが問題ないのでしょうか?
また、『H8S、H8/300シリーズ C/C++コンパイラ、アセンブラ、最適化リンケージエディタ コンパイラパッケージVer.7.00 ユーザーズマニュアル』の301頁に #pragma asm の備考として、
・コンパイル時に code=asmcode オプションを用いてアセンブリプログラムの出力を指定してください。指定がない場合は#pragma asm、#pragma endasm を含むアセンブラ命令列を無視します。
とありますが、このコンパイルオプションは指定されてますか?
あと、インラインアセンブラを使用する特別な理由がないのであれば、上記の箇所はそれぞれ
IIC2.ICCR2.BYTE = 0xbd;
IIC2.ICCR2.BYTE = 0x3d;
で良いと思います。
>チョコさん
失念しておりました、ご指摘ありがとうございます。
いもけんぴ-さん
こんにちは、
IIC通信をデバッグするのであれば、SCLとSDAの波形を確認しながら行った方がいいですよ。
プログラムだけではなく、実際の通信で上手出来ているか確認が必要です。
ご参考までに。
>Higetakaさん
ご回答ありがとうございます。
そのようにとらえることができるんですね、知りませんでした。
参考にさせていただきます。
>fujita nozomuさん
追記に記載いたしました通り、MOV命令を使うようにとの記載があるため使用しております。
また、コンパイルオプションについては書かれている通りのことを実施しております。
>SAさん
そういう手段も必要なのですね、勉強になります。
> インラインアセンブラはハードウェアマニュアルの「17.3.2 I 2 C バスコントロールレジスタ 2(ICCR2)」に従いインラインアセンブラを使用しています。
『H8/3687 グループ ハードウェアマニュアル ルネサス16ビットシングルチップマイクロコンピュータ H8ファミリ/ H8/300H Tiny シリーズ』の「17.3.2 I2C バスコントロールレジスタ 2(ICCR2)」の説明に「なお開始条件/停止条件の発行は、MOV 命令を用いてください。」とありますが、これはビット操作命令などのリードモディファイライト動作をする命令を使うなと言ってるだけで、インラインアセンブラを使えという意味ではないですよ。
勉強不足で、インラインアセンブラを使わなければならないと思い込んでいました、ありがとうございました。