API Programming Interface

The Alius USB2CAN Dual-Channel Debugger provides an open-source CANAL API DLL, allowing developers to control the device through programming. This document details the API usage, function descriptions, and code examples to help you quickly integrate the Alius USB2CAN Debugger into your application.

CANAL API Overview

CANAL (CAN Abstraction Layer) is an open-source CAN bus abstraction layer API that provides a unified set of interface functions for accessing various CAN interface devices. The Alius USB2CAN Debugger fully supports the CANAL API, enabling developers to write hardware-independent applications.

API Features

  • Cross-Platform: Supports Windows and Linux operating systems
  • Multi-Language Support: Supports C/C++, C#, Python, Java, LabVIEW, and other programming languages
  • Open Source: Source code is open and can be modified and customized as needed
  • Easy to Use: Provides simple and intuitive API functions

Installation and Configuration

Windows Environment

  1. Copy the CANAL API DLL (usually canal.dll) to your application directory or system directory (e.g., C:\Windows\System32)
  2. Add the CANAL API header file (canal.h) to your project
  3. Configure the project to link to the CANAL API library

Linux Environment

  1. Install the CANAL API shared library (usually libcanal.so)
  2. Include the CANAL API header file in your project
  3. Link to the CANAL API library when compiling (use the -lcanal option)

API Function Description

1. Open Connection

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

Function: Open a connection to the CAN device

Parameters:

  • pDevice: Device name or path (e.g., COM port number)
  • flags: Open flags (usually set to 0)

Return Value:

  • Success: Returns device handle (> 0)
  • Failure: Returns 0

Example:

long hDevice = CanalOpen("COM3", 0);
if (0 == hDevice) {
    printf("Unable to open device\n");
    return -1;
}

2. Close Connection

int CanalClose(long handle);

Function: Close the connection to the CAN device

Parameters:

  • handle: Device handle (returned by CanalOpen)

Return Value:

  • Success: Returns 1
  • Failure: Returns 0

Example:

if (0 == CanalClose(hDevice)) {
    printf("Failed to close device\n");
}

3. Get Device Status

int CanalGetStatus(long handle, canalsystemstatus *pStatus);

Function: Get the current status of the device

Parameters:

  • handle: Device handle
  • pStatus: Pointer to canalsystemstatus structure

Return Value:

  • Success: Returns 1
  • Failure: Returns 0

4. Get Statistics

int CanalGetStatistics(long handle, canalstatistics *pStatistics);

Function: Get communication statistics of the device

Parameters:

  • handle: Device handle
  • pStatistics: Pointer to canalstatistics structure

Return Value:

  • Success: Returns 1
  • Failure: Returns 0

5. Send CAN Message

int CanalSend(long handle, canalmsg *pCanMsg);

Function: Send a CAN message

Parameters:

  • handle: Device handle
  • pCanMsg: Pointer to canalmsg structure

Return Value:

  • Success: Returns 1
  • Failure: Returns 0

Example:

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

canMsg.id = 0x100;          // CAN message ID
canMsg.flags = 0;            // Standard frame, no RTR
canMsg.sizeData = 8;         // Data length
canMsg.data[0] = 0x01;      // Data byte 0
canMsg.data[1] = 0x02;      // Data byte 1
// ... set other data bytes

if (0 == CanalSend(hDevice, &canMsg)) {
    printf("Failed to send message\n");
}

6. Receive CAN Message

int CanalReceive(long handle, canalmsg *pCanMsg);

Function: Receive a CAN message

Parameters:

  • handle: Device handle
  • pCanMsg: Pointer to canalmsg structure

Return Value:

  • Success: Returns 1
  • Failure: Returns 0
  • No message: Returns 0 (need to check pCanMsg->sizeData)

Example:

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

if (CanalReceive(hDevice, &canMsg)) {
    printf("Received message: 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("Failed to receive message or no message\n");
}

7. Set Filter

int CanalSetFilter(long handle, unsigned long filter);

Function: Set hardware acceptance filter

Parameters:

  • handle: Device handle
  • filter: Filter value

Return Value:

  • Success: Returns 1
  • Failure: Returns 0

8. Set Mask

int CanalSetMask(long handle, unsigned long mask);

Function: Set acceptance mask

Parameters:

  • handle: Device handle
  • mask: Mask value

Return Value:

  • Success: Returns 1
  • Failure: Returns 0

Data Structures

canalmsg Structure

typedef struct {
    unsigned long id;        // CAN message ID
    unsigned char flags;     // Flag bits
    unsigned char sizeData;  // Data length (0-8)
    unsigned char data[8];   // Data bytes
    unsigned long timestamp; // Timestamp (ms)
} canalmsg;

Flag Bit Definitions:

  • 0x00: Standard frame (11-bit ID)
  • 0x01: Extended frame (29-bit ID)
  • 0x02: Remote frame (RTR)

canalsystemstatus Structure

typedef struct {
    unsigned long channel_status;  // Channel status
    unsigned long lasterrorcode;  // Last error code
    unsigned long lasterrorsource;// Last error source
    unsigned long errorcounter;   // Error counter
} canalsystemstatus;

canalstatistics Structure

typedef struct {
    unsigned long cntReceiveFrames;  // Receive frame count
    unsigned long cntTransmitFrames; // Transmit frame count
    unsigned long cntReceiveData;    // Receive data byte count
    unsigned long cntTransmitData;   // Transmit data byte count
    unsigned long cntOverruns;       // Overrun count
    unsigned long cntBusWarnings;    // Bus warning count
    unsigned long cntBusOff;         // Bus off count
} canalstatistics;

Code Examples

C++ Example

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

int main() {
    // Open device
    long hDevice = CanalOpen("COM3", 0);
    if (0 == hDevice) {
        printf("Unable to open device\n");
        return -1;
    }
    
    printf("Device opened successfully, handle: %ld\n", hDevice);
    
    // Send message
    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("Message sent successfully\n");
    } else {
        printf("Failed to send message\n");
    }
    
    // Receive messages (wait 1 second)
    canalmsg rxMsg;
    memset(&rxMsg, 0, sizeof(canalmsg));
    
    for (int i = 0; i < 100; i++) {
        if (CanalReceive(hDevice, &rxMsg)) {
            printf("Received message: ID=0x%X, DLC=%d, Data: ", rxMsg.id, rxMsg.sizeData);
            for (int j = 0; j < rxMsg.sizeData; j++) {
                printf("%02X ", rxMsg.data[j]);
            }
            printf("\n");
        }
        Sleep(10);  // Wait 10 ms
    }
    
    // Close device
    CanalClose(hDevice);
    
    return 0;
}

Python Example

import ctypes
import time

# Load CANAL DLL
canal = ctypes.CDLL("canal.dll")

# Define data structure
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)
    ]

# Open device
hDevice = canal.CanalOpen("COM3", 0)
if 0 == hDevice:
    print("Unable to open device")
    exit(-1)

print(f"Device opened successfully, handle: {hDevice}")

# Send message
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("Message sent successfully")
else:
    print("Failed to send message")

# Receive messages
rxMsg = CanalMsg()
for i in range(100):
    if canal.CanalReceive(hDevice, ctypes.byref(rxMsg)):
        print(f"Received message: ID=0x{rxMsg.id:X}, DLC={rxMsg.sizeData}, Data: ", end="")
        for j in range(rxMsg.sizeData):
            print(f"{rxMsg.data[j]:02X} ", end="")
        print()
    time.sleep(0.01)

# Close device
canal.CanalClose(hDevice)

Advanced Features

1. Multi-Channel Operation

The Alius USB2CAN Debugger supports two independent CAN channels. You can operate both channels simultaneously by opening multiple device handles.

2. Error Handling

During use, you may encounter various errors, such as bus off, receive overflow, etc. It is recommended that you regularly check the device status and take appropriate measures based on the error type.

3. Performance Optimization

  • Use hardware filters to reduce unnecessary data reception
  • Use larger receive buffers
  • Process received data in a separate thread

Frequently Asked Questions

Question 1: Unable to Load CANAL DLL

Solution: Ensure the DLL file is in the correct path and check if the DLL dependencies are satisfied.

Question 2: Failed to Send Message

Solution: Check if the device is opened, if the CAN bus is connected correctly, and if the baud rate matches.

Question 3: Lost Received Messages

Solution: Increase the receive buffer size, process received messages in time, and lower the baud rate.

Technical Support

If you encounter any problems during use, please contact the Alius technical support team. We are dedicated to serving you.