Ixxat CAN 接口状态
CAN 接口状态的获取
canControlGetStatus
周期性调用canControlGetStatus API
HRESULT EXTERN_C canControlGetStatus (
HANDLE hCanCtl,
PCANLINESTATUS pStatus
);
pStatus 指针指向一个CANLINESTATUS 结构体
typedef struct _CANLINESTATUS
{
UINT8 bOpMode;
UINT8 bBtReg0;
UINT8 bBtReg1;
UINT8 bBusLoad;
UINT8 dwStatus;
} CANLINESTATUS, *PCANLINESTATUS;
应用程序可根据返回的指针指向一个CANLINESTATUS 中的各属性进行CAN接口状态的判断
bOpMode 当前CAN控制器的模式
- CAN_OPMODE_STANDARD: 接收11位标识符
- CAN_OPMODE_EXTENDED: 接收29位标识符
- CAN_OPMODE_ERRFRAME: 错误消息通过特殊的CAN消息传递给应用程序
- CAN_OPMODE_LISTONLY: 只听模式
- CAN_OPMODE_LOWSPEED: 使用低速CAN模式
- CAN_OPMODE_AUTOBAUD: 自动检测波特率
bBtReg0 和 bBtReg1 分别对应Philips SJA 1000 CAN控制器的BTR0和BTR1 寄存器(16MHz 时钟频率),可换算为CAN总线的波特率
bBusLoad 表示当前CAN总线的负载率的百分比(需要使用的CAN 接口型号支持该功能,可通过canControlGetCaps 获取控制器支持的功能特性CANCAPABILITIES中的dwFeatures)
typedef struct _CANCAPABILITIES { UINT16 wCtrlType; UINT16 wBusCoupling; UINT32 dwFeatures; UINT32 dwClockFreq; UINT32 dwTscDivisor; UINT32 dwCmsDivisor; UINT32 dwCmsMaxTicks; UINT32 dwDtxDivisor; UINT32 dwDtxMaxTicks; } CANCAPABILITIES, *PCANCAPABILITIES;dwStatus 当前CAN 控制器的状态
- CAN_STATUS_TXPEND: 正在传输一条CAN报文
- CAN_STATUS_OVRRUN: 接收缓存器过载,需要Reset CAN控制器
- CAN_STATUS_ERRLIM: CAN 错误计数器溢出
- CAN_STATUS_BUSOFF: CAN 控制器 bus-off
- CAN_STATUS_ININIT: CAN 控制器处于stopped状态
- CAN_STATUS_BUSCERR: CAN 总线耦合错误
CAN 消息中的CANMSGINFO
在使用canChannelPeekMessage,canChannelPeekMsgMult,canChannelReadMessage,canChannelReadMsgMult 等API 读取CAN总线上接收到的消息时,可首先判断PCANMSG 中的uMsgInfo bType 属性,用于判断接收到的CAN消息是数据报文还是状态或错误报文
typedef struct _CANMSG
{
UINT32 dwTime;
UINT32 dwMsgId;
CANMSGINFO uMsgInfo;
UINT8 abData[8];
} CANMSG, *PCANMSG;
typedef struct _CANMSGINFO
{
UINT8 bType;
UINT8 bFlags2;
UINT8 bFlags;
UINT8 bAccept;
} CANMSGINFO, *PCANMSGINFO;
- bType
CAN_MSGTYPE_DATA: 正常数据帧CAN_MSGTYPE_INFO: 信息帧,如控制器状态变化等CAN_MSGTYPE_ERROR: 控制器检测到的错误帧CAN_MSGTYPE_STATUS: 状态帧,当前CAN 控制器的状态,参见上文dwStatusCAN_MSGTYPE_WAKEUP: 唤醒帧CAN_MSGTYPE_TIMEOVR: 超时帧CAN_MSGTYPE_TIMERST: 时间复位帧
示例代码
hResult = canChannelReadMessage(hCanChn, 100, &sCanMsg);
if (hResult == VCI_OK)
{
if (sCanMsg.uMsgInfo.Bytes.bType == CAN_MSGTYPE_DATA)
{
// show data frames
if (sCanMsg.uMsgInfo.Bits.rtr == 0)
{
UINT8 j;
_tprintf(TEXT("\nTime: %10u ID: %3X DLC: %1u Data:"),
sCanMsg.dwTime, sCanMsg.dwMsgId, sCanMsg.uMsgInfo.Bits.dlc);
for (j = 0; j < sCanMsg.uMsgInfo.Bits.dlc; j++)
{
_tprintf(TEXT(" %.2X"), sCanMsg.abData[j]);
}
}
else
{
_tprintf(TEXT("\nTime: %10u ID: %3X DLC: %1u Remote Frame"),
sCanMsg.dwTime, sCanMsg.dwMsgId, sCanMsg.uMsgInfo.Bits.dlc);
}
}
else if (sCanMsg.uMsgInfo.Bytes.bType == CAN_MSGTYPE_INFO)
{
// show informational frames
switch (sCanMsg.abData[0])
{
case CAN_INFO_START:
_tprintf(TEXT("\nCAN started..."));
break;
case CAN_INFO_STOP:
_tprintf(TEXT("\nCAN stoped..."));
break;
case CAN_INFO_RESET:
_tprintf(TEXT("\nCAN reseted..."));
break;
}
}
else if (sCanMsg.uMsgInfo.Bytes.bType == CAN_MSGTYPE_ERROR)
{
// show error frames
switch (sCanMsg.abData[0])
{
case CAN_ERROR_STUFF:
_tprintf(TEXT("\nstuff error..."));
break;
case CAN_ERROR_FORM:
_tprintf(TEXT("\nform error..."));
break;
case CAN_ERROR_ACK:
_tprintf(TEXT("\nacknowledgment error..."));
break;
case CAN_ERROR_BIT:
_tprintf(TEXT("\nbit error..."));
break;
case CAN_ERROR_CRC:
_tprintf(TEXT("\nCRC error..."));
break;
case CAN_ERROR_OTHER:
default:
_tprintf(TEXT("\nother error..."));
break;
}
}
else if (sCanMsg.uMsgInfo.Bytes.bType == CAN_MSGTYPE_STATUS)
{
// show status frames
switch (sCanMsg.abData[0])
{
case CAN_STATUS_TXPEND:
_tprintf(TEXT("\n transmission pending..."));
break;
case CAN_STATUS_OVRRUN:
_tprintf(TEXT("\n data overrun occurred..."));
break;
case CAN_STATUS_ERRLIM:
_tprintf(TEXT("\n error warning limit exceeded..."));
break;
case CAN_STATUS_BUSOFF:
_tprintf(TEXT("\n bus off status..."));
break;
case CAN_STATUS_ININIT:
_tprintf(TEXT("\n init mode active..."));
break;
case CAN_STATUS_BUSCERR:
_tprintf(TEXT("\n bus coupling error..."));
break;
default:
_tprintf(TEXT("\nother error..."));
break;
}
}
}