APIプログラミングインターフェース

Alius USB2CANデュアルチャンネルデバッガーは、オープンソースのCANAL API DLLを提供し、開発者がプログラミング方式でデバイスを制御できるようにします。このドキュメントでは、APIの使用方法、関数説明、コード例を詳細に紹介し、Alius USB2CANデバッガーをアプリケーションに迅速に統合するのに役立ちます。

CANAL API概要

CANAL(CAN Abstraction Layer)は、さまざまなCANインターフェースデバイスにアクセスするための統一されたインターフェース関数セットを提供するオープンソースのCANバス抽象化レイヤーAPIです。Alius USB2CANデバッガーは、CANAL APIを完全にサポートしているため、開発者はハードウェアに依存しないアプリケーションを作成できます。

APIの特徴

  • クロスプラットフォーム:WindowsとLinuxオペレーティングシステムをサポート
  • 多言語サポート:C/C++、C#、Python、Java、LabVIEWなど、複数のプログラミング言語をサポート
  • オープンソース:ソースコードは開放されており、必要に応じて変更およびカスタマイズ可能
  • 使いやすさ:シンプルで直感的なAPI関数を提供

インストールと設定

Windows環境

  1. CANAL API DLL(通常はcanal.dll)をアプリケーションディレクトリまたはシステムディレクトリ(例:C:\Windows\System32)にコピーします
  2. プロジェクトにCANAL APIヘッダーファイル(canal.h)を追加します
  3. プロジェクトがCANAL APIライブラリにリンクするように設定します

Linux環境

  1. CANAL API共有ライブラリ(通常はlibcanal.so)をインストールします
  2. プロジェクトにCANAL APIヘッダーファイルを含めます
  3. コンパイル時にCANAL APIライブラリにリンクします(-lcanalオプションを使用)

API関数説明

1. 接続を開く

long CanalOpen(char *pDevice, unsigned long flags);

機能:CANデバイスへの接続を開く

パラメーター

  • pDevice:デバイス名またはパス(例:COMポート番号)
  • flags:オープンフラグ(通常は0に設定)

戻り値

  • 成功:デバイスハンドル(> 0)を返します
  • 失敗:0を返します

long hDevice = CanalOpen("COM3", 0);
if (0 == hDevice) {
    printf("デバイスを開けません\n");
    return -1;
}

2. 接続を閉じる

int CanalClose(long handle);

機能:CANデバイスへの接続を閉じる

パラメーター

  • handle:デバイスハンドル(CanalOpenが返したもの)

戻り値

  • 成功:1を返します
  • 失敗:0を返します

if (0 == CanalClose(hDevice)) {
    printf("デバイスを閉じることができません\n");
}

3. デバイスステータスを取得する

int CanalGetStatus(long handle, canalsystemstatus *pStatus);

機能:デバイスの現在のステータスを取得する

パラメーター

  • handle:デバイスハンドル
  • pStatuscanalsystemstatus構造体へのポインター

戻り値

  • 成功:1を返します
  • 失敗:0を返します

4. 統計情報を取得する

int CanalGetStatistics(long handle, canalstatistics *pStatistics);

機能:デバイスの通信統計情報を取得する

パラメーター

  • handle:デバイスハンドル
  • pStatisticscanalstatistics構造体へのポインター

戻り値

  • 成功:1を返します
  • 失敗:0を返します

5. CANメッセージを送信する

int CanalSend(long handle, canalmsg *pCanMsg);

機能:CANメッセージを送信する

パラメーター

  • handle:デバイスハンドル
  • pCanMsgcanalmsg構造体へのポインター

戻り値

  • 成功:1を返します
  • 失敗:0を返します

canalmsg canMsg;
memset(&canMsg, 0, sizeof(canalmsg));

canMsg.id = 0x100;          // CANメッセージID
canMsg.flags = 0;            // 標準フレーム、RTRなし
canMsg.sizeData = 8;         // データ長
canMsg.data[0] = 0x01;      // データバイト0
canMsg.data[1] = 0x02;      // データバイト1
// ... 他のデータバイトを設定

if (0 == CanalSend(hDevice, &canMsg)) {
    printf("メッセージの送信に失敗しました\n");
}

6. CANメッセージを受信する

int CanalReceive(long handle, canalmsg *pCanMsg);

機能:CANメッセージを受信する

パラメーター

  • handle:デバイスハンドル
  • pCanMsgcanalmsg構造体へのポインター

戻り値

  • 成功:1を返します
  • 失敗:0を返します
  • メッセージなし:0を返します(pCanMsg->sizeDataを確認する必要があります)

canalmsg canMsg;
memset(&canMsg, 0, sizeof(canalmsg));

if (CanalReceive(hDevice, &canMsg)) {
    printf("メッセージを受信しました:ID=0x%X, DLC=%d\n", canMsg.id, canMsg.sizeData);
    for (int i = 0; i < canMsg.sizeData; i++) {
        printf("%02X ", canMsg.data[i]);
    }
    printf("\n");
} else {
    printf("メッセージの受信に失敗するか、メッセージがありません\n");
}

7. フィルターを設定する

int CanalSetFilter(long handle, unsigned long filter);

機能:ハードウェア受信フィルターを設定する

パラメーター

  • handle:デバイスハンドル
  • filter:フィルター値

戻り値

  • 成功:1を返します
  • 失敗:0を返します

8. マスクを設定する

int CanalSetMask(long handle, unsigned long mask);

機能:受信マスクを設定する

パラメーター

  • handle:デバイスハンドル
  • mask:マスク値

戻り値

  • 成功:1を返します
  • 失敗:0を返します

データ構造

canalmsg構造体

typedef struct {
    unsigned long id;        // CANメッセージID
    unsigned char flags;     // フラグビット
    unsigned char sizeData;  // データ長(0-8)
    unsigned char data[8];   // データバイト
    unsigned long timestamp; // タイムスタンプ(ms)
} canalmsg;

フラグビット定義

  • 0x00:標準フレーム(11ビットID)
  • 0x01:拡張フレーム(29ビットID)
  • 0x02:リモートフレーム(RTR)

canalsystemstatus構造体

typedef struct {
    unsigned long channel_status;  // チャンネルステータス
    unsigned long lasterrorcode;  // 最後のエラーコード
    unsigned long lasterrorsource;// 最後のエラーソース
    unsigned long errorcounter;   // エラーカウンター
} canalsystemstatus;

canalstatistics構造体

typedef struct {
    unsigned long cntReceiveFrames;  // 受信フレームカウント
    unsigned long cntTransmitFrames; // 送信フレームカウント
    unsigned long cntReceiveData;    // 受信データバイトカウント
    unsigned long cntTransmitData;   // 送信データバイトカウント
    unsigned long cntOverruns;       // オーバーランカウント
    unsigned long cntBusWarnings;    // バス警告カウント
    unsigned long cntBusOff;         // バスオフカウント
} canalstatistics;

コード例

C++例

#include <stdio.h>
#include "canal.h"

int main() {
    // デバイスを開く
    long hDevice = CanalOpen("COM3", 0);
    if (0 == hDevice) {
        printf("デバイスを開けません\n");
        return -1;
    }
    
    printf("デバイスが正常に開きました、ハンドル:%ld\n", hDevice);
    
    // メッセージを送信する
    canalmsg txMsg;
    memset(&txMsg, 0, sizeof(canalmsg));
    txMsg.id = 0x100;
    txMsg.sizeData = 8;
    for (int i = 0; i < 8; i++) {
        txMsg.data[i] = i;
    }
    
    if (CanalSend(hDevice, &txMsg)) {
        printf("メッセージが正常に送信されました\n");
    } else {
        printf("メッセージの送信に失敗しました\n");
    }
    
    // メッセージを受信する(1秒待つ)
    canalmsg rxMsg;
    memset(&rxMsg, 0, sizeof(canalmsg));
    
    for (int i = 0; i < 100; i++) {
        if (CanalReceive(hDevice, &rxMsg)) {
            printf("メッセージを受信しました:ID=0x%X, DLC=%d, データ:", rxMsg.id, rxMsg.sizeData);
            for (int j = 0; j < rxMsg.sizeData; j++) {
                printf("%02X ", rxMsg.data[j]);
            }
            printf("\n");
        }
        Sleep(10);  // 10 ms待つ
    }
    
    // デバイスを閉じる
    CanalClose(hDevice);
    
    return 0;
}

Python例

import ctypes
import time

# CANAL DLLをロードする
canal = ctypes.CDLL("canal.dll")

# データ構造を定義する
class CanalMsg(ctypes.Structure):
    _fields_ = [
        ("id", ctypes.c_ulong),
        ("flags", ctypes.c_ubyte),
        ("sizeData", ctypes.c_ubyte),
        ("data", ctypes.c_ubyte * 8),
        ("timestamp", ctypes.c_ulong)
    ]

# デバイスを開く
hDevice = canal.CanalOpen("COM3", 0)
if 0 == hDevice:
    print("デバイスを開けません")
    exit(-1)

print(f"デバイスが正常に開きました、ハンドル:{hDevice}")

# メッセージを送信する
txMsg = CanalMsg()
txMsg.id = 0x100
txMsg.sizeData = 8
for i in range(8):
    txMsg.data[i] = i

if canal.CanalSend(hDevice, ctypes.byref(txMsg)):
    print("メッセージが正常に送信されました")
else:
    print("メッセージの送信に失敗しました")

# メッセージを受信する
rxMsg = CanalMsg()
for i in range(100):
    if canal.CanalReceive(hDevice, ctypes.byref(rxMsg)):
        print(f"メッセージを受信しました:ID=0x{rxMsg.id:X}, DLC={rxMsg.sizeData}, データ:", end="")
        for j in range(rxMsg.sizeData):
            print(f"{rxMsg.data[j]:02X} ", end="")
        print()
    time.sleep(0.01)

# デバイスを閉じる
canal.CanalClose(hDevice)

高度な機能

1. マルチチャンネル操作

Alius USB2CANデバッガーは、2つの独立したCANチャンネルをサポートしています。複数のデバイスハンドルを開くことで、両方のチャンネルを同時に操作できます。

2. エラー処理

使用中に、バスオフ、受信オーバーフローなどのさまざまなエラーが発生する可能性があります。デバイスのステータスを定期的に確認し、エラーの種類に応じて適切な措置を講じることをお勧めします。

3. 性能最適化

  • ハードウェアフィルターを使用して、不必要なデータ受信を減らす
  • より大きな受信バッファーを使用する
  • 別のスレッドで受信したデータを処理する

よくある質問

質問1:CANAL DLLをロードできない

解決方法:DLLファイルが正しいパスにあることを確認し、DLLの依存関係が満たされているか確認してください。

質問2:メッセージの送信に失敗した

解決方法:デバイスが開いているか、CANバスが正しく接続されているか、ボーレートが一致しているか確認してください。

質問3:受信メッセージが失われた

解決方法:受信バッファーサイズを大きくする、受信したメッセージを適時に処理する、ボーレートを下げる。

技術サポート

使用中に問題が発生した場合は、Alius技術サポートチームにお問い合わせください。喜んで対応いたします。