跳到主要内容

API

1. 介绍

1.1 什么是C小程序

C 小程序是用 C/C++ 语言编写、可在 ETStudio 中运行的小型程序。通过 ETStudio 提供的 API,可方便实现定时器、CAN/LIN 报文收发、数字/模拟信号读写、电源控制与系统变量访问等功能。

1.2 文档说明

本文档描述 C 小程序提供的 API 接口与用法示例。

2. 初始化函数与主函数

2.1 简单示例

title="./sample.cpp"
#include "BaseMiniProgram.h"

void OnStart()
{
uint8_t data[8] = {0};
CAN_Tx(1, 1, 8, data);
}

void OnExit()
{
}

2.2 返回码定义

typedef enum
{
ErrCode_Success = 0,
ErrCode_NullArgument,
ErrCode_NotImplemented,
ErrCode_ChannelDisabled,
ErrCode_DriverNotSupport = 254,
ErrCode_DriverError = 255,
} KAPI_ErrCode;

2.3 小程序初始化函数

  1. OnStart:小程序启动后调用一次,可在此注册周期函数或启动定时器。
void OnStart()
{
}
  1. OnExit:小程序结束时调用。
void OnExit()
{
}

3. 全局变量

3.1 GetCurrentChannelMappingID

  • int GetCurrentChannelMappingID();
  • 说明
    • Channel Mapping ID 用于标识当前节点所属的通道映射,该 ID 在 ETStudio 中配置。

alt text

4. 定时器

4.1 start_timer

void* start_timer(uint64_t interval, boolean onceTimer, void (*onTimer)(void* pTimer)); 说明

  • 启动一个定时器

参数

  • interval 定时器间隔,单位为毫秒
  • onceTimer
    • TRUE 单次定时器(超时后自动停止)
    • FALSE 周期定时器(超时后自动重启)
  • onTimer 定时器到时回调函数

返回

  • void* 定时器句柄

示例

// 创建一个 1 秒定时器
void onTimer(void* pTimer)
{
// 执行操作
}
start_timer(1000, FALSE, onTimer);

参考

4.2 stop_timer

void stop_timer(void* pTimer); 说明

  • 停止指定定时器

参数

示例

void onTimer(void* pTimer)
{
// 执行操作
}
void* timer = start_timer(1000, FALSE, onTimer);
...
stop_timer(timer);

参考

5. 系统变量

5.1 访问系统变量

  1. 在 ETStudio 系统变量界面创建系统变量
    • alt text
  2. 读取系统变量值
    int32_t varValue = namespace_example::int32value;
  3. 设置系统变量值
    namespace_example::int32value = 30;

5.2 SetOnChange

void SetOnChange(void (*onChange)()) 说明

  • 注册系统变量变更时的回调函数

参数

  • onChange 系统变量变更时的回调函数

示例

void on_namespace_example_int32valueChange()
{
int32_t varValue = namespace_example::int32value;
}
void OnStart()
{
namespace_example::int32value.SetOnChange(on_namespace_example_int32valueChange);
}

注意: 当前版本中新增或修改的系统变量在 Code Editor 中可能不会立即被识别,若 Code Editor 未检测到新变量,请重启 ETStudio。

6. 通过接口发送 DBC/LDF 定义的报文

6.1 发送报文

  1. void Transmit(); 说明

    • 根据 Simulation Node 配置发送 CAN、CAN FD 或 LIN 报文。 示例
    • 假设已将 dbc/ldf 文件导入到 Simulation Network(LIN/CANBus),其中包含名为 Gateway_1 的报文,以下代码可用于发送该报文:
    CANNetwork::Gateway_1 msg;
    msg.Gear = 1;
    msg.EngineRunning = 2;
    msg.Ig_15 = 3;
    msg.Ig_15R = 4;
    msg.StarterKey = 5;
    msg.Transmit();
    • 发送到指定 Channel Mapping ID:
    CANNetwork::Gateway_1 msg(2);
    msg.Gear = 1;
    msg.EngineRunning = 2;
    msg.Ig_15 = 3;
    msg.Ig_15R = 4;
    msg.StarterKey = 5;
    msg.Transmit();
    • 发送到指定 BusType(例如 BUS_TYPE_CAN):
    CANNetwork::Gateway_1 msg;
    msg.Gear = 1;
    msg.EngineRunning = 2;
    msg.Ig_15 = 3;
    msg.Ig_15R = 4;
    msg.StarterKey = 5;
    msg.BusType = BUS_TYPE_CAN;
    msg.Transmit();
    • CANNetwork 为仿真网络名
    • Gateway_1 为帧名
    • BusType 可为 BUS_TYPE_CANBUS_TYPE_CANFDBUS_TYPE_LIN
  2. void TransmitHeader(); 说明

    • 根据 Simulation Node 配置发送 LIN 帧头。 示例
    LINBus::LIN_Test_message msg;
    msg.TransmitHeader();
    • LINBus 为仿真网络名
    • LIN_Test_message 为 LIN 帧名

6.2 通过面板设置的信号值发送报文

static int StaticTransmit(int channelMappingID = 0); 说明

  • 发送 CAN/CANFD/LIN 报文,报文中的信号值由面板(Panel)配置。

参数

  • channelMappingID 通道映射 ID,0 表示当前节点的默认通道 ID
  • busType BUS_TYPE_CANBUS_TYPE_CANFDBUS_TYPE_LIN 示例
CANNetwork::Gateway_1::StaticTransmit();

6.3 接收报文回调

void on_recv_message(<NetworkName>::<FrameName> *msg) 说明

  • 在接收到 CAN/CANFD/LIN 报文时注册回调函数

参数

  • msg 指向接收报文的指针,类型由导入的 dbc/ldf 文件决定

示例

void on_recv_message(CANNetwork::Gateway_1 *msg)
{
// 处理接收报文
}
void OnStart()
{
CANNetwork::Gateway_1::OnMessage = on_recv_message;
}

7. CAN

类型定义(保持原样以便调用方使用)

typedef struct
{
uint32_t timestamp_us;
uint8_t bus_type;
uint8_t event_type;
uint8_t channel;
uint8_t dir;
uint8_t dlc;
uint8_t extended_frame;
uint8_t subDeviceNumber;
uint8_t reserved;
uint32_t id;
uint8_t data[64];
} EM_ReceiveFrame_t;

typedef struct
{
uint32_t can_id;
bool rtr_frame;
bool extended_frame;
uint8_t can_dlc;
uint8_t channel;
uint8_t data[64];
uint32_t timestamp_us;
} EM_CANSendFrame_t;

7.1 发送 CAN 报文

KAPI_ErrCode CAN_Tx(uint32_t channelMappingID, uint32_t id, uint8_t dlc, uint8_t* data); 说明

  • 发送一条 CAN 报文

参数

  • channelMappingID 通道映射 ID,0 表示当前节点的默认通道 ID
  • id CAN ID
  • dlc 数据长度
  • data 指向数据缓冲区的指针

返回值

  • 0 成功
  • 其他 失败

示例

uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
CAN_Tx(0, 0x123, 8, data);

7.2 注册 CAN 接收回调

KAPI_ErrCode register_CANRxEvent(uint32_t channelMappingID, uint32_t id, ReceiveFrameHandler callback);

说明

  • 注册 CAN 报文接收回调

参数

  • channelMappingID 通道映射 ID,0 表示当前节点的默认通道 ID
  • id 待过滤的 CAN ID
  • callback 接收处理函数(typedef void (ReceiveFrameHandler)(EM_ReceiveFrame_t const))

返回

  • 0 成功
  • 其他 失败

示例

void onCANRx(EM_ReceiveFrame_t const* frame)
{
// 处理接收帧
}

uint32_t channelMappingID = 0;
uint32_t id = 0x123;
register_CANRxEvent(channelMappingID, id, onCANRx);

7.3 注册 CAN 发送完成回调

KAPI_ErrCode register_CANTxEvent(uint32_t channelMappingID, uint32_t id, CANSendFrameHandler callback);

说明

  • 注册 CAN 报文发送完成回调

参数

  • channelMappingID 通道映射 ID,0 表示当前节点的默认通道 ID
  • id 待过滤的 CAN ID
  • callback 发送完成处理函数(typedef void (CANSendFrameHandler)(EM_CANSendFrame_t))

返回

  • 0 成功
  • 其他 失败

示例

void onCANTx(EM_CANSendFrame_t* frame)
{
// 处理发送完成事件
}
uint32_t channelMappingID = 0;
uint32_t id = 0x123;
register_CANTxEvent(channelMappingID, id, onCANTx);

7.4 注册 CAN 预发送回调

KAPI_ErrCode register_CANPreTxEvent(uint32_t channelMappingID, uint32_t id, CANSendFrameHandler callback);

说明

  • 注册 CAN 报文即将发送时的回调

参数

  • channelMappingID 通道映射 ID,0 表示当前节点的默认通道 ID
  • id 待过滤的 CAN ID
  • callback 预发送处理函数(typedef void (CANSendFrameHandler)(EM_CANSendFrame_t))

返回

  • 0 成功
  • 其他 失败

示例

void onCANPreTx(EM_CANSendFrame_t* frame)
{
// Do something
}
uint32_t channelMappingID = 0;
uint32_t id = 0x123;
register_CANPreTxEvent(channelMappingID, id, onCANPreTx);

8. CANFD

8.1 发送 CANFD 报文

KAPI_ErrCode CANFD_Tx(uint32_t channelMappingID, uint32_t id, uint8_t dlc, uint8_t* data); 说明

  • 发送一条 CANFD 报文

参数

  • channelMappingID CANFD 通道 ID,0 表示当前节点的默认通道 ID(参见 GetCurrentChannelMappingID
  • id CANFD ID
  • dlc 数据长度码(Data Length Code)
  • data 指向数据缓冲区的指针

返回

  • 0 成功
  • 其他 失败

示例

uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
CANFD_Tx(0, 0x123, 8, data);

8.2 注册 CANFD 接收回调

KAPI_ErrCode register_CANFDRxEvent(uint32_t channelMappingID, uint32_t id, ReceiveFrameHandler callback);

说明

  • 当接收到 CANFD 帧时注册回调函数

参数

  • channelMappingID CANFD 通道 ID,0 表示当前节点的默认通道 ID
  • id 待过滤的 CANFD ID
  • callback 接收处理函数(typedef void (ReceiveFrameHandler)(EM_ReceiveFrame_t const))

返回

  • 0 成功
  • 其他 失败

示例

void onCANFDRx(EM_ReceiveFrame_t const* frame)
{
// 处理接收帧
}

uint32_t channelMappingID = 0;
uint32_t id = 0x123;
register_CANFDRxEvent(channelMappingID, id, onCANFDRx);

8.3 注册 CANFD 发送完成回调

KAPI_ErrCode register_CANFDTxEvent(uint32_t channelMappingID, uint32_t id, CANSendFrameHandler callback);

说明

  • 当 CANFD 帧发送完成时注册回调函数

参数

  • channelMappingID CANFD 通道 ID,0 表示当前节点的默认通道 ID
  • id 待过滤的 CANFD ID
  • callback 发送完成处理函数(typedef void (CANSendFrameHandler)(EM_CANSendFrame_t))

返回

  • 0 成功
  • 其他 失败

示例

void onCANFDTx(EM_CANSendFrame_t* frame)
{
// 处理发送完成事件
}
uint32_t channelMappingID = 0;
uint32_t id = 0x123;
register_CANFDTxEvent(channelMappingID, id, onCANFDTx);

8.4 注册 CANFD 预发送回调

KAPI_ErrCode register_CANFDPreTxEvent(uint32_t channelMappingID, uint32_t id, CANSendFrameHandler callback);

说明

  • 当 CANFD 帧即将发送时注册回调函数

参数

  • channelMappingID CANFD 通道 ID,0 表示当前节点的默认通道 ID
  • id 待过滤的 CANFD ID
  • callback 预发送处理函数(typedef void (CANSendFrameHandler)(EM_CANSendFrame_t))

返回

  • 0 成功
  • 其他 失败

示例

void onCANFDPreTx(EM_CANSendFrame_t* frame)
{
// 处理预发送事件
}
uint32_t channelMappingID = 0;
uint32_t id = 0x123;
register_CANFDPreTxEvent(channelMappingID, id, onCANFDPreTx);

9. LIN

类型定义

typedef struct
{
uint8_t lin_head;
uint8_t lin_dlc;
uint8_t channel;
uint8_t data[8];
uint32_t timestamp_us;
} EM_LINSendFrame_t;

9.1 LIN 主站发送帧头

KAPI_ErrCode LinMaster_TxHeader(uint32_t channelMappingID, uint8_t header);

说明

  • 发送 LIN 帧头

参数

  • channelMappingID LIN 通道 ID,0 表示当前节点的默认通道 ID
  • header LIN 帧头

返回

  • 0 成功
  • 其他 失败

示例

LinMaster_TxHeader(0, 0x3C);

9.2 LIN 主站发送帧头与数据

KAPI_ErrCode LinMaster_Tx(uint32_t channelMappingID, uint8_t header, uint8_t dlc, uint8_t* data); 说明

  • 发送一条 LIN 报文

参数

  • channelMappingID LIN 通道 ID,0 表示当前节点的默认通道 ID
  • header LIN 帧头
  • dlc 数据长度码
  • data 指向数据缓冲区的指针

返回

  • 0 成功
  • 其他 失败

示例

uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
LinMaster_Tx(0, 0x3C, 8, data);

9.3 注册 LIN 主站接收回调

KAPI_ErrCode register_LinMasterRxEvent(uint32_t channelMappingID, uint8_t header, ReceiveFrameHandler callback);

说明

  • 当接收到 LIN 报文时注册回调函数

参数

  • channelMappingID LIN 通道 ID,0 表示当前节点的默认通道 ID
  • header 待过滤的 LIN 帧头
  • callback 接收处理函数(typedef void (ReceiveFrameHandler)(EM_ReceiveFrame_t const))

返回

  • 0 成功
  • 其他 失败

示例

void onLinMasterRx(EM_ReceiveFrame_t const* frame)
{
// 处理接收帧
}

uint32_t channelMappingID = 0;
uint8_t header = 0x3C;
register_LinMasterRxEvent(channelMappingID, header, onLinMasterRx);

9.4 注册 LIN 主站发送完成回调

KAPI_ErrCode register_LinMasterTxEvent(uint32_t channelMappingID, uint8_t header, LINSendFrameHandler callback);

说明

  • 当 LIN 报文发送完成时注册回调函数

参数

  • channelMappingID LIN 通道 ID,0 表示当前节点的默认通道 ID
  • header 待过滤的 LIN 帧头
  • callback 发送完成处理函数(typedef void (LINSendFrameHandler)(EM_LINSendFrame_t))

返回

  • 0 成功
  • 其他 失败

示例

void onLinMasterTx(EM_LINSendFrame_t* frame)
{
// 处理发送完成事件
}

uint32_t channelMappingID = 0;
uint8_t header = 0x3C;
register_LinMasterTxEvent(channelMappingID, header, onLinMasterTx);

9.5 注册 LIN 主站预发送回调

KAPI_ErrCode register_LinMasterPreTxEvent(uint32_t channelMappingID, uint8_t header, LINSendFrameHandler callback);

说明

  • 当 LIN 报文即将发送时注册回调函数

参数

  • channelMappingID LIN 通道 ID,0 表示当前节点的默认通道 ID
  • header 待过滤的 LIN 帧头
  • callback 预发送处理函数(typedef void (LINSendFrameHandler)(EM_LINSendFrame_t))

返回

  • 0 成功
  • 其他 失败

示例

void onLinMasterPreTx(EM_LINSendFrame_t* frame)
{
// 处理预发送事件
}

uint32_t channelMappingID = 0;
uint8_t header = 0x3C;
register_LinMasterPreTxEvent(channelMappingID, header, onLinMasterPreTx);

10. Digital

10.1 设置数字输出电平

KAPI_ErrCode Do_Set(uint32_t channelMappingID, boolean lvl);

说明

  • 设置数字输出电平

参数

  • channelMappingID 数字输出通道 ID
  • lvl
    • 0 低电平
    • 1 高电平

返回

  • 0 成功
  • 其他 失败

示例

Do_Set(0, 1);

10.2 获取数字输入状态

KAPI_ErrCode Di_Get(uint32_t channelMappingID, boolean* value);

说明

  • 获取数字输入状态

参数

  • channelMappingID 数字输入通道 ID
  • value 存储输入状态的指针
    • 0 低电平
    • 1 高电平

返回

  • 0 成功
  • 其他 失败

示例

boolean value;
Di_Get(0, &value);

11. Analog

11.1 获取模拟输入电压

KAPI_ErrCode Ai_Get(uint32_t channelMappingID, double* value);

说明

  • 获取模拟输入电压值

参数

  • channelMappingID 模拟输入通道 ID
  • value 存储电压值的指针

返回

  • 0 成功
  • 其他 失败

示例

double value;
Ai_Get(0, &value);

12. 其他

12.1 注册键盘按键回调

void (*resgister_onKey)(char key, void (*onKey)(void));

说明

  • 注册按键按下时的回调函数

参数

  • key 键字符
  • onKey 回调函数(typedef void (*onKey)(void))

返回

  • void

示例

void onKey(void)
{
// 处理按键事件
}

resgister_onKey('a', onKey);

12.2 系统消息输出(到宿主应用)

void show_system_message(const char* str);

说明

  • 向宿主应用输出一条系统消息

参数

  • str 消息内容

返回

  • void

示例

show_system_message("Hello World");

12.3 控制台消息输出(到小程序控制台)

void show_console_message(const char* str);

说明

  • 向小程序控制台输出一条消息

参数

  • str 消息内容

返回

  • void

示例

show_console_message("Hello World");

12.4 微秒级延时(忙等待)

void delay_us(uint32 delaytime_us);

说明

  • 以忙等待方式延时指定时间(以微秒为单位)

参数

  • delaytime_us 延时时间(微秒)

返回

  • void

示例

delay_us(1000);

注意: 此函数会阻塞当前线程直到延时结束,建议优先使用 start_timer 来实现定时功能。

12.5 获取工程绝对路径

const char* GetAbsProjectPath();

说明

  • 获取当前工程的绝对路径

参数

  • void

返回

  • const char* 当前工程的绝对路径

示例

const char* path = GetAbsProjectPath();

const wchar_t* GetAbsProjectPathW();

说明

  • 获取当前工程的绝对路径(宽字符版本)

参数

  • void

返回

  • const wchar_t* 当前工程的绝对路径(宽字符)

示例

const wchar_t* path = GetAbsProjectPathW();