• 検索結果がありません。

サンプリング

ドキュメント内 Linuxデバイスドライバチュートリアル (ページ 164-171)

第 9 章 CAN 133

10.3 チュートリアル

10.3.2 サンプリング

unsigned long dwLowCount;

UCNTSMPLCONFIG SmplConfig;

// デバイス番号 1 のデバイスを制御 nDevice = 1;

// デバイスをオープン nRet = UcntOpen(nDevice);

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

// 周期測定モードに設定

// 基準クロック 1usでHigh, Lowパルス幅を測定 nChannel = 1;

dwCountType = IFUCNT_CYCLE_HIGH_LOW;

dwClock = 10;

nRet = UcntSetCycleMode(nDevice, nChannel, dwCountType, dwClock);

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

// サンプリング設定

SmplConfig.dwSmplNum = 100;

SmplConfig.dwSmplEventNum = 0;

SmplConfig.dwSmplRepeat = 1;

SmplConfig.dwStatusMode = IFUCNT_ADD_STATUS;

SmplConfig.dwErrCtrl = IFUCNT_FREERUN;

nRet = UcntSetSamplingConfig(nDevice, nChannel, &SmplConfig);

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

// カウントを開始

dwChSel = 0x01 << (nChannel - 1);

nRet = UcntStartCount(nDevice, dwChSel,

IFUCNT_CMD_START | IFUCNT_CMD_SAMPLING);

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

// サンプリング完了まで待機

printf("Wait for the completion of the sampling.¥n");

do {

nRet = UcntGetSamplingStatus(nDevice, nChannel, &dwSmplStatus,

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

} while ((dwSmplStatus == IFUCNT_SMPL_START) || (dwSmplCount < 100));

// カウントを停止

nRet = UcntStopCount(nDevice, dwChSel, IFUCNT_CMD_STOP);

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

// サンプリングデータを取得 dwDataNum = 100;

nRet = UcntGetSamplingData(nDevice, nChannel, &dwCounter[0][0], &dwDataNum);

if (nRet != IFUCNT_ERROR_SUCCESS) { goto EXIT_CLOSE;

}

dwHighCount = 0;

dwLowCount = 0;

for (i = 0; i < (int)dwDataNum; i++) {

if ((dwCounter[i][1] & 0x2500) == 0x2100) {

// LA立ち下りエッジでのカウント値 (Highパルス幅) if (dwHighCount == 0) {

dwHighCount = dwCounter[i][0];

dwLowCount = 0;

}

} else if ((dwCounter[i][1] & 0x2500) == 0x2400) {

// LA立ち上がりエッジでのカウント値 (Lowパルス幅) if ((dwLowCount == 0) && (dwHighCount != 0)) { dwLowCount = dwCounter[i][0];

} }

// Highパルス幅とLowパルス幅からデューティ比を計算し、表示 if ((dwHighCount != 0) && (dwLowCount != 0)) {

printf("%03ld:(%%)¥n", (dwHighCount * 100) / (dwHighCount + dwLowCount));

dwHighCount = 0;

dwLowCount = 0;

} }

EXIT_CLOSE:

// デバイスをクローズ UcntClose(nDevice);

if (nRet != IFUCNT_ERROR_SUCCESS) { exit(EXIT_FAILURE);

}

return 0;

Makefileの作成

下記ソースを「Makefile」という名前で、ソースファイルと同一のディレクトリに保存してください。

all: pulsedutysampling

pulsedutysampling: pulsedutysampling.o

$(CC) pulsedutysampling.o -o pulsedutysampling -lgpg6320u pulsedutysampling.o: pulsedutysampling.c

$(CC) -Wall -c pulsedutysampling.c -o pulsedutysampling.o clean:

rm -f *.o pulsedutysampling

Step2 コンパイル/実行

ソースコード・Makefileを保存したディレクトリに移動し、コマンドラインから下記コマンドを実行します。下記コマンドを 実行することでコンパイルを行う事が出来ます。

make

コンパイルが成功すると、オブジェクトファイル「pulsedutysampling.o」と実行ファイル「pulsedutysampling」が作られま す。

ErrorやWarningが表示された場合はコードの記述に誤りがあります。内容を見直してください。

プログラムを実行するには、以下のコマンドを実行します。

./pulsedutysampling

プログラムの実行に成功すれば、以下の出力が行なわれます。

050:(%%) 050:(%%) 050:(%%)

Step3 プログラムの解説

カウンタ製品を制御する前段階として、カウンタ製品をオープンするUcntOpen関数を呼び出しています。

以下に引数と対応を示します。

int UcntOpen(

int nDevice, /* デバイス番号 */

);

引数名 内 容

nDevice オープンするデバイス番号を指定します。

この引数を与えて関数を呼び出すと、ドライバは引数に適合するカウンタ製品を検索し、合致した製品がある場合は、

戻り値として0を返します。

プログラマは、このデバイス番号を使って以降のAPIの呼び出しを行います。

カウンタ製品を制御するためには、まずカウンタのモード設定を行ないます。

カウンタのモードには様々な種類があり、パルスカウントモード、平均周波数測定モード、周期測定モード、位相差幅測 定モード、タイマモード、分周器モード、パルスジェネレーターモードがあります。

これらの設定を行なうには、以下の関数を使用します。

カウンタモード 関数

パルスカウントモード UcntSetPulseCountMode関数 平均周波数測定モード UcntSetFreqAvgMode関数 周期測定モード UcntSetCycleMode関数 位相差幅測定モード UcntSetPhaseDiffMode関数 タイマモード UcntSetTimerMode関数 分周器モード UcntSetFreqDividerMode関数 パルスジェネレーターモード UcntSetPulseGeneratorMode関数

ここでは、サンプリングモードの設定を行なうためのUcntSetCycleMode関数を使用します。

この関数はサンプリング周期の設定を行います。ここでは、設定するチャンネルを1に指定し、周期測定モード、基準ク ロックを1usとしHigh/Lowパルス幅の測定、の設定を行なっています。

サンプリング周期の設定が終わると、次にサンプリング条件の設定を行ないます。

サンプリング条件の設定を行なうには、UcntSetSamplingConfig関数を使用します。

設定はUCNTSMPLCONFIG構造体で指定します。

構造体のメンバーで、サンプリング件数、イベント通知サンプリング件数、サンプリング繰り返し回数、サンプリングス テータスへのステータス付加の有無、サンプリングエラー発生時の処理をそれぞれ指定します。

ここでは、設定するチャンネルを1に指定し、サンプリング件数を100件、、イベント通知サンプリング件数を0件、サ ンプリング繰り返し回数を1回、サンプリングステータスへのステータス付加を有効、サンプリングエラー発生時は何 も処理をしない、に設定しています。

サンプリングの設定が終わると、サンプリングを開始させます。サンプリングを開始するには、UcntStartCount 関数を 使用します。開始するチャンネル、スタートモードを指定します。

開始するチャンネルは複数のチャンネルを一度に指定することができ、bit1~bit4にそれぞれCH1~CH4が割り当て られています。

ここでは、サンプリングを開始するチャンネルを 1 のみとし、スタートモードをソフトスタート・サンプリングスタートとし ています。

UcntStartCount関数を実行すると、サンプリングが開始され、指定されたサンプリング周期で100件のカウントを開始

します。

サンプリングは非同期で実行されるため、関数を実行するとサンプリング開始処理を行い、すぐに処理を返します。

このため、サンプリング完了を確認する必要があり、サンプリング完了を確認するには、UcntGetSamplingStatus関数 を使用します。

この関数は、取得するチャンネルを指定することで、サンプリングステータス、サンプリングが完了した件数、現在の サンプリング繰り返し回数を取得する事が出来ます。

ここでは、do/while 文を使用し、ループ条件にサンプリングステータスがサンプリング動作中であること、またはサン プリング完了件数が100件未満である事を指定しています。

サンプリングが完了すると、サンプリングステータスはサンプリング停止中となり、サンプリング完了件数は 100 件と なるため、do/while文を抜けます。

サンプリングの完了を確認出来たら、サンプリングを停止させます。サンプリングを停止させるには、UcntStopCount 関数を使用します。UcntStartCount関数同様、停止するチャンネルは複数同時に指定することができます。

ここでは、チャンネル1を指定してサンプリング停止を行なっています。

次に、サンプリングデータの取得を行ないます。サンプリングデータの取得を行なうには、UcntGetSamplingData関数 を使用します。取得するチャンネル番号、取得するサンプリング件数を指定し、サンプリング結果は、第3引数で渡さ れた配列のポインタに結果を返します。

第4引数で、取得するサンプリング件数を指定しますが、変数のポインタを渡しています。これは、関数を実行したと きにサンプリングしている件数が変数のポインタに格納されます。

したがって、サンプリングを100件しか行なっていないのに、取得件数を200件と指定した場合、実際に取得したサン プリング件数は100件となるため、変数のポインタには100が格納されます。

High/Low パルス幅測定モードでは、LA信号の全ての立ち上がりと立ち下りのエッジでカウンタ値をラッチ、クリアし

ます。取得したサンプリングデータがHighパルスとLowパルスのどちらを示しているのかを確認するために、ステー タス情報を確認する必要があります。UcntSetSamplingConfig 関数でサンプリングデータにステータス情報を付加す るように設定しています。ステータス情報からラッチ直前のLAの状態(LABEF)がHighの場合、そのときのサンプリ ングデータがHigh パルス幅となり、ラッチ直後の LAの状態(LAAFT)がHigh の場合、Lowパルス幅となります。

Highパルス幅とLowパルス幅から、デューティ比を計算し、printf関数で表示を行なっています。

最後にカウンタ製品の制御を終了するためには、UcntClose関数を用います。

オープンしたカウンタ製品は、使用後は必ずクローズしてください。

★UcntClose関数を呼ばないと、どうなるか?

UcntClose関数を呼び出さないと、カウンタ製品はオープンしたままの状態になります。

オープン状態なので、UcntOpen関数を呼び出した場合、エラーが返ります。

オープンしたら必ずクローズしてください。

ドキュメント内 Linuxデバイスドライバチュートリアル (ページ 164-171)