1. 程式人生 > >基於CCP協議的CAN匯流排

基於CCP協議的CAN匯流排

CCP通訊協議:主從式,主裝置通過CAN匯流排與多臺從裝置相連,主裝置室測量標定系統 ,從裝置是需要標定的ECU,主裝置首先與其中一個從裝置建立邏輯連線,主、從裝置之間的所有的資料傳遞均由主機控制,從裝置執行主裝置命令後返回包含命令響應值或錯誤程式碼等資訊的報文,同時從裝置可以根據主裝置通過控制命令設定的列表資訊來定時地向主裝置傳送變數資訊,資料的傳遞是由主裝置初始化並且從裝置來執行的,並且是由固定的迴圈取樣頻率或者事件觸發的。

主裝置通過USB-CAN介面與從裝置連線,符合CAN2.0協議。

通訊過程中,所有報文均為8個位元組,包括命令、資料、資料長度、地址等資訊

該通訊協議參照CCP協議,可以與INCA等標定軟體介面。

CAN通訊:採用兩個報文資料物件 CRO和DTO (命令接收物件)(命令傳送物件)每個物件根據其資料流向,都有一個唯一的ID標示符進行標示,ID識別符號可以由使用者自己設定。

命令接收物件(CRO):

用於傳遞指令程式碼和內部功能碼或主、從裝置之間交換的儲存區資料

 

表1

CMD (1 Byte):

命令程式碼。

CTR (1 Byte):

命令計數器。

Parameter and Data(6 Byte):

引數和資料場,命令相關的資料或引數

資料接收物件(DTO):

資料傳輸物件(DTO)指由從裝置反饋的報文。DTO根據報文首位元組PID的值可以由三種形式,見表2:

PID值

資料傳輸型別

備註

0xFF

CRM(Command Return Message)

由從裝置傳送,反饋CRO命令的報文

0xFE

Event Message

當從裝置檢測到內部發生錯誤機制時,由從裝置自行向主裝置傳送,報告其當前的執行狀態,並請求主裝置暫停當前工作程序以處理髮生的錯誤

0-0xFD

DAQ-DTO(Data Acquisition-DTO)

用於DAQ模式,由從裝置定期向主裝置傳送。

根據物件描述表(ODT),確定需要上傳的變數

 


       CRM-Event Message報文幀格式

表3:場說明

PID(1 Byte)

其值代表了DTO的型別

ERR(1 Byte)

命令返回錯誤程式碼

CTR(1 Byte)

命令計數器,與接收的相等。

Parameter and Data Field

引數和資料場,命令相關的資料或引數

(2). DAQ-DTO(Data Acquisition-DTO)的報文幀:

 

3. 協議命令列表及說明(標註綠色字型部分逐步補充完整)

3.1  命令列表:

命令名稱

程式碼

說明

CONNECT

0x01

建立一個ECU的連線

0x02

設定MTA地址

0x03

下載最多5個位元組資料到ECU

DNLOAD_6

0x23

下載6個位元組資料到ECU

UPLOAD

0x04

從ECU上載最多5個位元組資料

SHORT_UP

0x0F

從ECU上載最多5個數據(不用MTA)

DISCONNECT

0x07

斷開到該ECU的連線

GET_DAQ_SIZE

0x14

得到指定DAQ列表大小

SET_DAQ_PTR

0x15

選中某指定DAQ列表中某ODT的某元素

WRITE_DAQ

0x16

設定該元素指定的地址

START_STOP

0x06

開始/停止採集指定的DAQ列表

EXCHANGE_ID

0x17

得到該ECU的識別符號

GET_SEED

0x12

得到計算金鑰的種子(SEED

UNLOCK

0x13

要求ECU釋放某種功能

SET_S_STATUS

0x0C

設定當前會話狀態

GET_S_STATUS

0x0D

得到當前會話狀態

BUILD_CHKSUM

0x0E

計算指定區域的校驗和

CLEAR_MEMORY

0x10

清除某記憶體區域

0x18

FLASH程式設計(最多5個位元組)

PROGRAM_6

0x22

FLASH程式設計(6個位元組)

MOVE

0x19

從MTA0處拷貝指定長度的位元組到MTA1處

TEST

0x05

測試當前線上的從裝置

GET_ACTIVE_CAL_PAGE

0x09

得到當前標定頁(RAM or FLASH

DIAG_SERVICE

0x20

ACTION_SERVICE

0x21

3.2命令返回錯誤程式碼

程式碼

描述

種類

狀態改變

0x00

正確接收,無錯誤

0x01

DAQ處理器過載

0x10

命令處理器忙

0x11

DAQ處理器忙

。。。

待續

3.3命令詳細說明

3.3.1CONNECT命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x01)

1

位元組

命令計數器

2

站地址

4-7

位元組

填0(不關心)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

程式:connect命令

UINT8 Connect(UINT16 wStationAddr) {

        UINT8pbCROData[8];

       pbCROData[0] = CC_CONNECT;

       pbCROData[1] = m_bCTR ++;

        // intel format

        pbCROData[2] = (UINT8)(wStationAddr &0xFF);

       pbCROData[3] = (UINT8)(wStationAddr >> 8);

        // don't care

       pbCROData[4] = 0x00;

       pbCROData[5] = 0x00;

       pbCROData[6] = 0x00;

       pbCROData[7] = 0x00;

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 don't care

        if (CRC_OK == pbDTOData[1]) {

           m_bConnected = TRUE;

        }

        return pbDTOData[1];

    }

3.3.2SET_MTA命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x02)

1

位元組

命令計數器

2

位元組

存貯器傳輸地址(MTA0,MTA1)

3

位元組

地址擴充套件

4-7

無符號長整形

地址

資料傳送物件(DTO):

0

位元組

命令程式碼(0x01)

1

位元組

命令計數器

2

站地址

4-7

位元組

填0(不關心)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

3.3.2SET_MTA命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x02)

1

位元組

命令計數器

2

位元組

存貯器傳輸地址(MTA0,MTA1)

3

位元組

地址擴充套件

4-7

無符號長整形

地址

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

    UINT8SetMTA(UINT8 bMTANumber, UINT8 bAddrExt, UINT32 dwAddr) {

        UINT8pbCROData[8];

        pbCROData[0]= CC_SET_MTA;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bMTANumber;

       pbCROData[3] = bAddrExt;

       pbCROData[4] = (UINT8)(dwAddr >> 24);

       pbCROData[5] = (UINT8)(dwAddr >> 16);

       pbCROData[6] = (UINT8)(dwAddr >> 8);

       pbCROData[7] = (UINT8)(dwAddr >> 0);

        UINT8bRlt;

        UINT8pbDTOData[8];

       // if (CRC_OK != (bRlt = SendMessage(pbCROData, pbDTOData,TRANSMIT_TIMEOUT))) {

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, 2000))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 don't care 

        return pbDTOData[1];

    }

3.3.3 DNLOAD命令:

0

位元組

命令程式碼(0x03)

1

位元組

命令計數器

2

位元組

需下傳的資料長度

3-7

位元組

資料

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3

位元組

MTA0擴充套件位

4-7

位元組

執行後MTA0地址(即地址加上長度)

   UINT8Download(UINT8 &bSize, PUINT8 pbData, UINT8 &bExtAddr, UINT32&dwAddr) {

        UINT8pbCROData[8];

        UINT8i;

       pbCROData[0] = CC_DNLOAD;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bSize;

        if ((NULL == pbData)) {

            return CRC_CMD_SYNTAX;

        }

        if (bSize > 5) {

           bSize = 5;

        }

        for (i = 0; i < bSize; i ++) {

           pbCROData[3 + i] = pbData[i];

        }

        for (; i < 5; i ++) {

           pbCROData[3 + i] = 0x00;

        }

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3 MTA0 extension (after post-increment)

        // 4..7 MTA0 address (after post-increment)

       bExtAddr = pbDTOData[3];

        dwAddr= (((UINT32)pbDTOData[4]) << 24) ||

           (((UINT32)pbDTOData[5]) << 16) ||

           (((UINT32)pbDTOData[6]) << 8) ||

           (((UINT32)pbDTOData[7]) << 0);

        return pbDTOData[1];

    }

3.3.4UPLOAD命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x04)

1

位元組

命令計數器

2

位元組

需上傳的資料長度

3-7

位元組

填0

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

上傳的資料

UINT8 Upload(UINT8 &bSize, PUINT8 pbData) {

        UINT8pbCROData[8];

        UINT8i;

        if ((NULL == pbData)) {

            return CRC_CMD_SYNTAX;

        }

        if (bSize > 5) {

           bSize = 5;

        }

        pbCROData[0]= CC_UPLOAD;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bSize;

        // don't care

       pbCROData[3] = 0x00;

       pbCROData[4] = 0x00;

       pbCROData[5] = 0x00;

       pbCROData[6] = 0x00;

       pbCROData[7] = 0x00;

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 requested data bytes

        for (i = 0; i < bSize; i ++) {

           pbData[i] = pbDTOData[3 + i];

        }

        return pbDTOData[1];

    }

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x0F)

1

位元組

命令計數器

2

位元組

需上傳的資料長度

3

位元組

地址擴充套件

4-7

位元組

地址

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

上傳的資料

3.3.6DISCONNECT命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x07)

1

位元組

命令計數器

2

位元組

0x00 暫時斷開, 0x01 斷開

3

位元組

不關心

4-5

位元組

站地址(低位在前)

6-7

位元組

填0(不關心)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

UINT8 ShortUpload(UINT8 bSize, UINT8 bAddrExt, UINT32dwAddr, PUINT8 pbData) {

        UINT8pbCROData[8];

        UINT8i;

        if ((NULL == pbData)) {

            return CRC_CMD_SYNTAX;

        }

        if (bSize > 5) {

           bSize = 5;

        }

       pbCROData[0] = CC_SHORT_UPLOAD;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bSize;

       pbCROData[3] = bAddrExt;

       pbCROData[4] = (UINT8)(dwAddr >> 24);

       pbCROData[5] = (UINT8)(dwAddr >> 16);

       pbCROData[6] = (UINT8)(dwAddr >> 8);

       pbCROData[7] = (UINT8)(dwAddr >> 0);

        UINT8bRlt;

        UINT8pbDTOData[8];

        if(CRC_OK != (bRlt = SendPackage(pbCROData, pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 requested data bytes

        for (i = 0; i < bSize; i ++) {

           pbData[i] = pbDTOData[3 + i];

        }

        return pbDTOData[1];

    }

3.3.7GET_DAQ_SIZE命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x14)

1

位元組

命令計數器

2

位元組

DAQ表號(0,1…)

3

位元組

填0(不關心)

4-7

位元組

CAN 識別號(可選,暫不使用)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3

位元組

該DAQ列表中ODT的數目

4

位元組

該列表中第一個ODT表PID值

5-7

位元組

填0(不關心)

   UINT8pbCROData[8];

       pbCROData[0] = CC_GET_DAQ_SIZE;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bListNum;

        // don't care

        pbCROData[3]= 0x00;

       pbCROData[4] = (UINT8)(dwCANId >> 24);

       pbCROData[5] = (UINT8)(dwCANId >> 16);

       pbCROData[6] = (UINT8)(dwCANId >> 8);

       pbCROData[7] = (UINT8)(dwCANId >> 0);

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3 DAQ list size (= number of ODTs in this list)

        // 4 Fisrt PID of DAQ list

        // 5..7 don't care

       bDAQListSize = pbDTOData[3];

       bFirstPID = pbDTOData[4];

        return pbDTOData[1];

    }

3.3.8SET_DAQ_PTR命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x15)

1

位元組

命令計數器

2

位元組

DAQ表號(0,1…)

3

位元組

QDT表號(0,1…)

4

位元組

ODT表裡的元素(0,1…)

5-7

位元組

填0(不關心)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

        UINT8pbCROData[8];

       pbCROData[0] = CC_SET_DAQ_PTR;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bListNum;

       pbCROData[3] = bODTNum;

       pbCROData[4] = bElementNum;

        pbCROData[5]= 0x00;

       pbCROData[6] = 0x00;

       pbCROData[7] = 0x00;

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 don't care 

        return pbDTOData[1];

3.3.9WTITE_DAQ命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x16)

1

位元組

命令計數器

2

位元組

DAQ表中元素的長度(1,2,4)

3

位元組

表中元素的擴充套件地址

4-7

位元組

表中元素的地址

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

UINT8 pbCROData[8];

       pbCROData[0] = CC_WRITE_DAQ;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bElementSize;

       pbCROData[3] = bAddrExt;

       pbCROData[4] = (UINT8)(dwAddr >> 24);

       pbCROData[5] = (UINT8)(dwAddr >> 16);

       pbCROData[6] = (UINT8)(dwAddr >> 8);

       pbCROData[7] = (UINT8)(dwAddr >> 0);

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 don't care 

        return pbDTOData[1];

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x06)

1

位元組

命令計數器

2

位元組

停止:0x00;啟動:0x01;準備:0x02

3

位元組

DAQ 列表數

4

位元組

該DAQ列表中最後一張ODT表數

5

位元組

觸發事件數

6-7

傳送速率分頻係數

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

UINT8 pbCROData[8];

       pbCROData[0] = CC_START_STOP;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bMode;

       pbCROData[3] = bDAQNum;

       pbCROData[4] = bLastODTNum;

       pbCROData[5] = bEventChannelNo;

       pbCROData[6] = (UINT8)(wTransmissionRatePrescaler >> 8);

       pbCROData[7] = (UINT8)(wTransmissionRatePrescaler >> 0);

        UINT8bRlt;

        UINT8pbDTOData[8];

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, TRANSMIT_TIMEOUT))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 don't care 

        return pbDTOData[1];

3.3.11CLEAR_MEMORY命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x10)

1-7

位元組

填0(不關心)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

3.3.12PROGRAM命令:

命令接收物件(CRO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0x18)

1-7

位元組

填0(不關心)

資料傳送物件(DTO):

位(bit)

資料型別

描述

0

位元組

命令程式碼(0xFF)

1

位元組

命令返回程式碼

2

位元組

命令計數器

3-7

位元組

填0(不關心)

4、標定實現(舉例)

建立完善的匹配標定具體流程為:與底層ECU進行連線,監控、線上標定,上載和下載map圖,斷開連線等操作。對於匹配標定的2個最主要的任務,就是線上標定和實時監控,它是通過協議命令的組合,來實現的,下面舉例說明如何實現:

4.1監控命令解析:(假設有n張DAQ列表,每張列表中有m張ODT表)

序號

上位機

CCP

CAN

備註

1

設定監控變數列表,選擇取樣速率

(.A2L)

2

GET_DAQ_SIZE

傳送

重複n次

3

CRM-DTO

接收

重複n次

4

SET_DAQ_PTR

傳送

list 0~list m-1

5

CRM-DTO

接收

list 0~list m-1

6

WRITE_DAQ

傳送

list 0~list m-1

7

CRM-DTO

接收

list 0~list m-1

8

START_STOP

傳送

list 0~list n-1

9

CRM-DTO

接收

list 0~list n-1

10

START_STOP_ALL

傳送

開始監控

11

CRM-DTO

接收

12

DAQ-DTO

接收

接收多次

13

顯示

解碼顯示

14

START_STOP_ALL

傳送

停止顯示

15

CRM-DTO

接收

4.2  線上標定

標號

上位機

CCP

CAN

備註

1

修改資料

可能有n次

2

SET_MTA

傳送

3

CRM-DTO

接收

4

DNLOAD

傳送

5

CRM-DTO

接收

6

SHORT_UP

傳送

7

CRM-DTO

接收

SETMTA 命令:

    UINT8SetMTA(UINT8 bMTANumber, UINT8 bAddrExt, UINT32 dwAddr) {

        UINT8pbCROData[8];

        pbCROData[0]= CC_SET_MTA;

       pbCROData[1] = m_bCTR ++;

       pbCROData[2] = bMTANumber;

       pbCROData[3] = bAddrExt;

       pbCROData[4] = (UINT8)(dwAddr >> 24);

       pbCROData[5] = (UINT8)(dwAddr >> 16);

       pbCROData[6] = (UINT8)(dwAddr >> 8);

       pbCROData[7] = (UINT8)(dwAddr >> 0);

        UINT8bRlt;

        UINT8pbDTOData[8];

       // if (CRC_OK != (bRlt = SendMessage(pbCROData, pbDTOData,TRANSMIT_TIMEOUT))) {

        if (CRC_OK != (bRlt = SendPackage(pbCROData,pbDTOData, 2000))) {

            return bRlt;

        }

        // Response

        // 0 Packet ID: 0xFF

        // 1 Command Return Code

        // 2 Command Counter = CTR

        // 3..7 don't care 

        return pbDTOData[1];

    }