前回から時間が空きましたが、実際にI2Cを使ってみます。
I2CとはI2Cの設定(2)もう少し真面目に動かすI2Cの設定(3)関数化I2Cを試してみる通信試験用にI2C仕様のモータドライバを使用します。
秋月:
DRV8830使用DCモータードライブキット色んな事情により、マイコンはSH7125ベースボードを使用します。
取扱説明書によれば
アドレス:0xC8
データ0:0x00
データ1:0x49
の順に送信すればモーターが回ります。
配線
今回は目で見てビットが判別できる超低速でデータ送信を行います。
また、送信状態を把握するためにLEDポート(PE0,PE1)を使用します。
ドライバからのACKの受信を無視して一方的にデータを送信します。
本来バスはプルアップするのですが、今回はプルアップせず、
抵抗を経由して1対1で接続します。
本来の回路
実験用回路
また、スレーブがACKを返した時、マスターH、スレーブLとなる事を視認するため、
LEDを付けてみます。
実際の配線
モータードライバの電力はベースボードから供給しています。
モーターはコンデンサを付けたものを使用します。
プログラム
割込み等を使用せずに出力のON-OFFだけ制御します。
マイコン内で内部カウントをインクリメント(1づつ増加)させていき、内部カウントに応じてSCLとSDAを制御します。
動作確認のため、汎用性を無視してプログラムを作成します。
LEDの制御関数のみ以前作成したものを使います。
汎用IO設定:
io_setup.c、
io_setup.h<設定>
#include "io_setup.h"
main(){
int i=0;
int count=0;
//内部カウント int scl=1,sda=1;
//バス状態は1 int addless;
int data[2];
int stop_f=0;
hardware_setup();
//入出力の初期化 set_LED_R(scl);
//LED赤の初期化(クロック) set_LED_G(sda);
//LED緑の初期化(データ) /*変数の初期化*/
addless=0xC8;
//アドレスの設定 data[0]=0;
//データ0の設定(サブアドレス) data[1]=0x49;
//データ1の設定(電圧、正転逆転) /*メインループ*/
while(1){
i++;
if(i>40000){
//40000カウントごとに処理 i=0;
count++;
//内部カウントを1増加 }
//クロック出力の設定
if(stop_f){
//通信停止中 scl=1;
//バス開放 count=0;
//カウントリセット i=0;
//カウントリセット }
else if((count/2)%2){
//2で割って、更に2で割った余りが0でないとき2,3,6,7,10,11・・・・ scl=0;
}
else{
//それ以外 scl=1;
}
//end count switch(count){
//内部カウントに応じてSDAを設定 case 0:
sda=1;
break;
case 1:
//スタートコンディション sda=0;
break;
case 3+4*0:
//3 アドレスbit7 sda=(addless&0x80)?1:0;
break;
case 3+4*1:
//7 アドレスbit6 sda=(addless&0x40)?1:0;
break;
case 3+4*2:
//11 アドレスbit5 sda=(addless&0x20)?1:0;
break;
case 3+4*3:
//15 アドレスbit4 sda=(addless&0x10)?1:0;
break;
case 3+4*4:
//19 アドレスbit3 sda=(addless&0x08)?1:0;
break;
case 3+4*5:
//23 アドレスbit2 sda=(addless&0x04)?1:0;
break;
case 3+4*6:
//27 アドレスbit1 sda=(addless&0x02)?1:0;
break;
case 3+4*7:
//31 アドレスbit0 sda=(addless&0x01)?1:0;
break;
case 3+4*8:
//35 ACK待ち sda=1;
break;
case 3+36+4*0:
//39 データ0bit7 sda=(data[0]&0x80)?1:0;
break;
case 3+36+4*1:
//43 データ0bit6 sda=(data[0]&0x40)?1:0;
break;
case 3+36+4*2:
//47 データ0bit5 sda=(data[0]&0x20)?1:0;
break;
case 3+36+4*3:
//51 データ0bit4 sda=(data[0]&0x10)?1:0;
break;
case 3+36+4*4:
//55 データ0bit3 sda=(data[0]&0x08)?1:0;
break;
case 3+36+4*5:
//59 データ0bit2 sda=(data[0]&0x04)?1:0;
break;
case 3+36+4*6:
//63 データ0bit1 sda=(data[0]&0x02)?1:0;
break;
case 3+36+4*7:
//67 データ0bit0 sda=(data[0]&0x01)?1:0;
break;
case 3+36+4*8:
//71 ACK待ち sda=1;
break;
case 3+36*2+4*0:
//75 データ0bit7 sda=(data[1]&0x80)?1:0;
break;
case 3+36*2+4*1:
//79 データ0bit6 sda=(data[1]&0x40)?1:0;
break;
case 3+36*2+4*2:
//83 データ0bit5 sda=(data[1]&0x20)?1:0;
break;
case 3+36*2+4*3:
//87 データ0bit4 sda=(data[1]&0x10)?1:0;
break;
case 3+36*2+4*4:
//91 データ0bit3 sda=(data[1]&0x08)?1:0;
break;
case 3+36*2+4*5:
//95 データ0bit2 sda=(data[1]&0x04)?1:0;
break;
case 3+36*2+4*6:
//99 データ0bit1 sda=(data[1]&0x02)?1:0;
break;
case 3+36*2+4*7:
//103 データ0bit0 sda=(data[1]&0x01)?1:0;
break;
case 3+36*2+4*8:
//107 ACK待ち sda=1;
break;
case 3+36*3:
//111 ストップコンディション準備 sda=0;
break;
case 3+36*3+2:
//113 ストップコンディション sda=1;
stop_f=1;
break;
case :
break;
}
//end switch set_LED_R(scl);
//LED赤(クロック)を出力 set_LED_G(sda);
//LED緑(データ)を出力 }
//end while}
//end mainモーターが回れば成功です。
スレーブがACKを返すとブレッドボードのLEDが光ることが分かるはずです。
0x49を変えるとモーターの回り方が変わります。
40000カウントでインクリメントしていますが、1カウントでインクリメントすれば
一瞬で通信が終わるので起動直後からモーターが回るようになります。