文章
CAN-EtherCAT使用快速指南
refer to EtherCAT MainDevice Application Developers Manual and CAN-EtherCAT/2(-FD)
Demo 系统的搭建

使用esd EtherCAT Workbench 配置 CAN-EtherCAT (obj 6000 and 7000, baudrate 1000k bps)
-
PreOP 状态下, 点击 "Slave -> Process Data -> Assignment -> Recreate PDO lists -> Online by SDO Info Service". 在"All PDOs:"框内,生成了 0x1600 in outputs 和 0x1a00 0x1a85 in inputs。
-
双击 0x1600 可以看到 0x7000 被配置进了 RxPDO 内。双击 0x1a00和 0x1a85,依次可以看到 0x6000 和 0xf108 被配置进了TxPDO。
-
点击 "Sync Manager: -> 2. Outputs 198",查看 "SM2 PDOs:" 中 Assigned 0x1600(Assigned含义为将 0x1600 内包含的 OD entries assign到Process Image中)。 点击 "Sync Manager: -> 3. Inputs 168",查看 "SM3 PDOs:" 中 Assigned 0x1a00,而 Not Assigned 0x1a85,继续双击 0x1a85 将其 Assigned 到 Process Image内。
-
点击 "Process Data/Image" 标签,查看目前加入的Output 和 Input 变量以及其对应的 Offset 和 Logical Address。
-
PreOP 状态下,点击 "Slave -> Mailbox -> CoE", 点击鼠标右键选择 "Append new item",依次填入以下内容来配置 CAN-EtherCAT装置的CAN端口的波特率,将其设置成1000k bit/s。(Index: F800, Sub Index: 2, Data: 00, Transitions: PS)
-
点击 "Export ENI",输入文件名如 eni_only_can-ethercat_11bit_1mbps.xml。
-
使用文本编辑器,打开 eni_only_can-ethercat_11bit_1mbps.xml,将网卡 MAC 地址改为运行 EtherCAT Master 的电脑的MAC地址,修改的位置如下。
<Info><source>...</source></Info>
(Rx) 利用Object 6000h CAN Rx Message Queue 接收11-bit CAN消息
ecmC2EReadCANMsg.c , eni_only_can-ethercat_11bit_1mbps.xml:此程序运行在esd EtherCAT Master端,展示了如何透过 CAN-EtherCAT 装置把其接收到的所有 11 bit CAN消息读取到 Master 端,且展示了如何解析消息中的CAN ID,Length 和 rtr。
程序编译后,将eni_only_can-ethercat_11bit_1mbps.xml放在执行文件的同一目录中。运行程序时,通过esd CANreal或者cantest软件,任意发送11 bit CAN ID的 CAN消息,查看master端的程序output,output中会打印相关解码后的CAN信息。
static int CycleHandler(){
uint8_t * pTemp = pucRxMsg;
uint16_t numOfRxMsgs = *pucNumOfRxMsgs;
uint8_t byteStream[10];
uint16_t id;
uint8_t rtr;
uint8_t len;
if(*pucRxCountGateway == *pucRxCountApp)
return 0;
printf("----------------------------------\n");
printf("Rx Count App: %d \n", *pucRxCountApp);
printf("Rx Count Gateway: %d \n", *pucRxCountGateway);
printf("Number of Rx Msg: %d \n\n", numOfRxMsgs);
for(int i=0;i<numOfRxMsgs;){
printf("Rx Msg No.%d octets (HEX): ", ++i);
for(int j=0;j<10;j++){
byteStream[j] = *pTemp++;
printf("%02x ", byteStream[j]);
}
printf("\n");
id = 0;
id |= (byteStream[1]<<3);
id |= (byteStream[0]&0xf0)>>5;
printf("CAN ID (HEX): %03x \n",id);
len = byteStream[0]&0xf;
printf("CAN Msg Len: %d \n",len);
rtr = (byteStream[0]>>4)&0x1;
printf("RTR: %d \n",rtr);
if(!rtr){
printf("CAN Msg Content: ");
for(int k=0;k<len;k++)
printf("%02x ", byteStream[k+2]);
}
printf("\n\n");
}
printf("\n");
*pucRxCountApp = *pucRxCountApp + 1;
}
使用cantest 工具连续发送7条11 bit CAN-ID的CAN消息。Sample 程序接收到的 Output 如下
cantest 50 3 0x1 0x7 7 10 100 50 5000 0 1 0x22 0x33
ECM_EVENT_STATE_CHANGE: Master state change to OP
----------------------------------
Rx Count App: 3
Rx Count Gateway: 4
Number of Rx Msg: 7
Rx Msg No.1 octets (HEX): 22 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 001
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
Rx Msg No.2 octets (HEX): 42 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 002
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
Rx Msg No.3 octets (HEX): 62 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 003
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
Rx Msg No.4 octets (HEX): 82 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 004
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
Rx Msg No.5 octets (HEX): a2 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 005
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
Rx Msg No.6 octets (HEX): c2 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 006
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
Rx Msg No.7 octets (HEX): e2 00 22 33 00 00 00 00 00 00
CAN ID (HEX): 007
CAN Msg Len: 2
RTR: 0
CAN Msg Content: 22 33
(Rx) 利用 Object 6001h CAN Rx Extended Message Queue 既能接收 29-bit CAN消息,也能接收11-bit CAN消息
-
使用esd EtherCAT Workbench 配置 CAN-EtherCAT。 1.1 进入PreOP状态,进入"Slave - Device Specific",点击"Set to 29 bit mode",可以自动配置,修改内容如下。 a. 双击 0x1600,其中所有的Index 都为 0x7001,且 0x7001.04 - 0x7001.13(共16项)的长度都为 16 bytes。 b. 双击 0x1a00,其中所有的Index 都为 0x6001,且 0x6001.05 - 0x6001.14(共16项)的长度都为 14 bytes。 c. 查看 "Slave - Mailbox - CoE",添加了 0x8000.20 (Set CAN queues to 29-Bit-Mode), value 为 (Hex) 08 00, Transition: PS。
1.2 进入"Slave - Mailbox - CoE, Append new item",设置波特率为 1000k bit/s,具体参数请参见以上章节。 1.3 Export ENI,name: eni_only_can-ethercat_29bit_1mbps.xml 1.4 用文本编辑器修改eni_only_can-ethercat_29bit_1mbps.xml。将网卡 MAC 地址改为运行 EtherCAT Master 的电脑的 MAC地址,修改的位置如下。
<Info><source>...</source></Info>
ecmC2EReadCANMsg29bit.c , eni_only_can-ethercat_29bit_1mbps.xml:此程序运行在esd EtherCAT Master端,展示了如何透过 CAN-EtherCAT 装置把其接收到的所有 29 bit CAN消息以及所有11 bit CAN消息读取到 Master 端,且展示了如何解析消息中的CAN ID,Length 和 rtr。
static int CycleHandler(){
uint8_t * pTemp = pucRxMsg;
uint16_t numOfRxMsgs = *pucNumOfRxMsgs;
uint8_t byteStream[14];
uint32_t id;
uint8_t rtr;
uint8_t len;
uint8_t is29bit;
if(*pucRxCountGateway == *pucRxCountApp)
return 0;
printf("----------------------------------\n");
printf("Rx Count App: %d \n", *pucRxCountApp);
printf("Rx Count Gateway: %d \n", *pucRxCountGateway);
printf("Number of Rx Msg: %d \n\n", numOfRxMsgs);
for(int i=0;i<numOfRxMsgs;){
printf("Rx Msg No.%d octets (HEX): ", ++i);
for(int j=0;j<14;j++){
byteStream[j] = *pTemp++;
printf("%02x ", byteStream[j]);
}
printf("\n");
id = 0;
id |= byteStream[2];
id |= (byteStream[3]<<8);
id |= (byteStream[4]<<16);
id |= (byteStream[5]&0x1f)<<24;
printf("CAN ID ");
is29bit = (byteStream[5]>>7)&0x1;
if(is29bit)
printf("29-Bit (HEX): %08x \n",id);
else
printf("11-Bit (HEX): %03x \n",id);
len = byteStream[0]&0xf;
printf("CAN Msg Len: %d \n",len);
rtr = (byteStream[5]>>6)&0x1;
printf("RTR: %d \n",rtr);
if(!rtr){
printf("CAN Msg Content (HEX): ");
for(int k=0;k<len;k++)
printf("%02x ", byteStream[k+6]);
}
printf("\n\n");
}
printf("\n");
*pucRxCountApp = *pucRxCountApp + 1;
}
----------------------------------
Rx Count App: 560
Rx Count Gateway: 561
Number of Rx Msg: 1
Rx Msg No.1 octets (HEX): 08 00 45 32 fd 9f 78 89 90 00 33 22 34 21
CAN ID 29-Bit (HEX): 1ffd3245
CAN Msg Len: 8
RTR: 0
CAN Msg Content (HEX): 78 89 90 00 33 22 34 21
(Tx) 利用Object 7001h CAN Tx Extended Message Queue 既能发送 29-bit CAN消息,也能发送11-bit CAN消息
利用上一章节使用过的,一样的 ENI 文件 eni_only_can-ethercat_29bit_1mbps.xml
参考ecmC2ESendCANMsg.c,运行此程序将先发送所有11-bit CAN-ID的消息,再发送所有11-bit CAN-ID的消息。
int8_t byteStream[16];
uint32_t canid = 0;
uint8_t len = 8;
uint8_t content[8] = {0x1f,0x2e,0x3d,0x4c,0x5b,0x6a,0x79,0x88};
uint8_t rtr = 0;
uint8_t is29bit = 0;
// Send all 11-bit CAN-ID (0-7ff) msg
while (1)
{
ECM_INIT(byteStream);
printf("can-id 11-bit (Hex): %03x \n", canid);
printf("len: %d \n", len);
printf("rtr: %d \n", rtr);
byteStream[0] = 0;
byteStream[1] = 0;
byteStream[2] |= len;
byteStream[3] = 0;
byteStream[4] = (canid & 0xff);
byteStream[5] = ((canid & 0xff00) >> 8);
byteStream[6] = ((canid & 0xff0000) >> 16);
byteStream[7] = ((canid & 0x1f000000) >> 24);
byteStream[7] |= (rtr<<6);
byteStream[7] |= (is29bit<<7);
for (int i=0;i<len;i++)
byteStream[i+8] = content[i];
for (int k=0;k<16;k++)
printf("%02x ", byteStream[k]);
printf("\n\n");
for (int j=0;j<16;j++){
*pucTxMsg = byteStream[j];
pucTxMsg++;
}
*pusTxTransNum = 0;
*pusNumOfTxMsgs = 1;
*pusTxCountApp = *pusTxCountApp + 1;
pucTxMsg=pucTxMsg-16;
ecmSleep(10);
canid++;
if (canid==0x800)
{
canid = 0;
is29bit=1;
break;
}
}
// Send all 29-bit CAN-ID (0-1fffffff) msg
while (1)
{
ECM_INIT(byteStream);
printf("can-id 29-bit (Hex): %08x \n", canid);
printf("len: %d \n", len);
printf("rtr: %d \n", rtr);
byteStream[0] = 0;
byteStream[1] = 0;
byteStream[2] |= len;
byteStream[3] = 0;
byteStream[4] = (canid & 0xff);
byteStream[5] = ((canid & 0xff00) >> 8);
byteStream[6] = ((canid & 0xff0000) >> 16);
byteStream[7] = ((canid & 0x1f000000) >> 24);
byteStream[7] |= (rtr<<6);
byteStream[7] |= (is29bit<<7);
for (int i=0;i<len;i++)
byteStream[i+8] = content[i];
for (int k=0;k<16;k++)
printf("%02x ", byteStream[k]);
printf("\n\n");
for (int j=0;j<16;j++){
*pucTxMsg = byteStream[j];
pucTxMsg++;
}
*pusTxTransNum = 0;
*pusNumOfTxMsgs = 1;
*pusTxCountApp = *pusTxCountApp + 1;
pucTxMsg=pucTxMsg-16;
ecmSleep(10);
canid++;
if (canid==0x20000000)
{
break;
}
}