英創EM335x工控主板,使用的Cortex-A8及WEC7操作系統。本文以EM335x工控主板光盤例程為例,簡單介紹一下C和C#代碼如何調用WEC7平臺下CAN驅動,實現CAN通信的方法。
C代碼
客戶可以在自己工程中添加例程中的EM335X_CAN.h及EM335X_CAN.cpp,使用里面封裝好的EM335X_CAN類。
#include 'EM335X_CAN.h'
EM335X_CAN can;
打開CAN
調用EM335X_CAN類的OpenCAN方法。比如用250Kbps打開CAN1(默認只有CAN1)。
DWORD dwCanNo = 1;
DWORD dwBaudRate = 250000;
can.OpenCAN( dwCanNo, dwBaud );
關閉CAN
調用EM335X_CAN類的CloseCAN方法。
can.CloseCAN( );
發CAN數據包
調用EM335X_CAN類的WriteCAN方法。
can.WriteCAN(&canmsg );
接收CAN數據包
例程中使用了一個獨立的線程來接收。然后將收到的數據傳遞給PackagePro函數處理。參數一為數據buffer指針,參數二為數據的長度。
int EM335X_CAN::PackagePro(char* pBuf , int len)
用戶可以根據應用具體需求,添加相應的邏輯代碼。
CAN發送接收數據包結構體定義
不論是CAN發送,還是CAN接收,都是以數據包為單位發送接收的。單個數據包大小為16字節,結構體定義如下:
typedef struct {
CAN_ID id;
BYTE dlc;
BYTE data[8];
}CAN_MESSAGE,*PCAN_MESSAGE;
id,一個CAN_ID的結構體,該結構體定義在下面說明。
dlc,1字節,數據長度,取值0-8;
data,8字節,傳輸的數據。
注:因為結構體對齊的原因,該結構體大小為16字節。
CAN_ID結構體是一個整型,32位,用來記錄CAN通信所需的ID信息。
typedef struct{
unsigned int id:29;
unsigned int reserved:1;
unsigned int remote:1;
unsigned int extended:1;
}CAN_ID;
id,結構體整型的低29位,表示id號。
reserved,第30位,用來標記是接收的數據包,還是發送的數據包,默認設置為0即可。
remote,第31位,用來設置是數據幀還是遠程幀。0為數據幀,1為遠程幀。
extended,第32位,用來設置是標準幀還是擴展幀。0為標準幀,1為擴展幀。
CAN過濾條件Filter設置
EM335x同樣支持數據包過濾功能,設置Filter可以使得CAN只接收自己需要的數據包。
調用EM335X_CAN類的SetFilter方法,可以添加一個過濾條件,或者刪除一個已有的過濾條件。例如:
bResult = can.SetFilter( &Filter, FALSE );
第一個參數為過濾條件參數,為一個CAN_FILTER的結構體,在下面有說明。第二個參數如果為FALSE,則表示添加該過濾條件,如果為TRUE,則表示刪除已有的該過濾條件。
有多個過濾條件的情況下,只要數據包可以滿足任意一個過濾條件,那么該數據包就可以被接收。
CAN過濾條件Filter結構體定義
CAN_FILTER結構體定義如下:(CAN_ID結構體的定義前面數據包結構體里有說明)
typedef struct {
CAN_ID id;
CAN_ID mask;
}CAN_FILTER,*PCAN_FILTER;
這里的過濾邏輯如下:
假設收到的數據包里的id,我們記為id_message,與過濾條件中的filter參數里的id和mask滿足條件:(id_message&mask) == (id&mask),那么該數據包就可以接收,也就是說,mask表示需要進行對比的位,如果數據包的id這幾位與filter設置里的id的這幾位相同,那么該數據包就可以接收。
比如:
一個filter的mask = 0x03,即2進制的b0000 0011,即需要比較最后的兩位。
filter的id = 0x02,即2進制的b0000 0010。
那么數據包id如果最后兩位為 10,該數據包就可以通過過濾條件被接收。
數據包id = 0xF7,即2進制b1111 0111,無法接收。
數據包id = 0xE6,即2進制b1110 0110,可以接收。
數據包id = 0x2E,即2進制b0010 1110,可以接收。
CAN環回模式設置
環回模式為,可以選擇板子自己發送的數據包,是否自己也能同時接收到。
調用EM335X_CAN類的CAN_Loopback方法,如果希望自己發送的CAN包,自己也能接收到,那么設置第二個參數為TRUE。如果希望關閉環回功能,那么第二個參數設置為FALSE。
CAN其它命令
EM335X_CAN類的CanCommand方法可以控制CAN復位,啟動和停止。
BOOL CanCommand( CAN_COMMAND eCommand);
參數CAN_COMMAND是一個枚舉型,它的定義如下,STOP= 0,START =1,RESET=3:
typedef enum {
STOP,
START,
RESET
} CAN_COMMAND;
1、復位CAN
CAN復位會重置CAN驅動里的各個寄存器值,并執行相關的初始化操作。
在打開CAN的時候,OpenCAN函數里已經調用了該函數實現CAN復位。用戶可以根據自己應用的實際情況,決定在什么時機執行CAN復位。
2、啟動CAN
在設置好CAN波特率,環回,filter等參數后,CAN驅動線程并沒有馬上啟動,需要執行CAN啟動,CAN線程才開始工作。
在打開CAN的時候,OpenCAN函數在設置完參數后調用CAN啟動。用戶可以根據自己應用的實際情況,決定在什么時機執行該函數,例如:當CAN接收線程的接收到錯誤事件時,可以在錯誤處理代碼里添加停止CAN,和重新啟動CAN的調用。
3、停止CAN
停止CAN會關閉CAN驅動線程,在關閉CAN的時候,CloseCAN函數調用CAN停止。
C#代碼
C#代碼參考了C代碼,相對C接口稍微做了調整。我們同樣封裝了一個CAN的類在EM335x_CAN_API.cs中,方便客戶添加到自己工程中。
打開CAN
打開CAN的流程為:打開CAN設備,獲得設備句柄,初始化CAN,然后設置CAN的參數(波特率,環回模式),創建CAN接收線程,最后啟動CAN,然后CAN驅動線程開始工作。
1、打開CAN設備
int CanNo = 1;
hCAN = CAN.OpenCAN(CanNo);
2、重置CAN
執行Reset操作,初始化CAN。
bRet = CAN.CAN_Command(hCAN, (uint)CAN_COMMAND.RESET);
3、設置波特率
設置CAN的波特率,如250Kbps:
uBaud = 250000;
bRet = CAN.CAN_SetBaudRate(hCAN, uBaud);
4、設置CAN環回模式
如果希望自己發送的CAN包,自己也能接收到,那么可以設置第二個參數為1,例程中暫時關閉該功能,所以設置的0。
bRet = CAN.CAN_Loopback(hCAN, 0);
5、創建單獨的接收線程
因為接收時,函數需要等待CAN接收事件,為阻塞狀態,不宜直接寫在主線程中,這里添加一個接收線程,專門處理CAN數據接收。
創建線程:
revThread = new Thread(new ThreadStart(BeginReceive));
threadStop = false;
revThread.Start();//啟動waitforMessage線程
6、啟動CAN
當準備就緒,就可以啟動CAN設備了。
bRet = CAN.CAN_Command(hCAN, (uint)CAN_COMMAND.START);
關閉CAN
主要是結束接收線程,停止CAN,及關閉CAN設備句柄等。
revThread.Abort();//結束線程
revThread.Join();
bRet = CAN.CAN_Command(hCAN, (uint)CAN_COMMAND.STOP);
bRet = CAN.CloseCAN(hCAN);
發CAN數據包
調用WriteFile發送CAN數據包。
bRet = CAN.WriteFile(hCAN, ref pktSend, CAN.sizePacket, ref uLen, 0);
接收CAN數據包
調用ReadFile發送CAN數據包。
bResult = CAN.ReadFile(hCAN, ref pktRev, CAN.sizePacket, ref uLen, 0);
CAN發送接收數據包結構體定義
不論是CAN發送WriteFile,還是CAN接收ReadFile,都是以數據包為單位發送接收的。單個數據包大小為16字節,結構體定義如下:
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct CAN_MESSAGE
{
[FieldOffset(0)]
public uint id;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] data;//數據字節
}
id是一個整型4字節,32位,用來記錄CAN通信所需的ID信息。
id的低29位,表示id號。
id的第30位,用來標記是接收的數據包,還是發送的數據包。
id的第31位,用來設置是數據幀還是遠程幀。該位為0則是數據幀,該位為1則是遠程幀。
id的第32位,用來設置是標準幀還是擴展幀。該位為0則是標準幀,該位為1則是擴展幀。
data為12字節byte數組。
data[0]為CAN數據包內數據的長度,取值0-8;
data[1]-data[8],8字節,為CAN數據包內傳輸的數據。
data[9]-data[11]未使用。
注:結構體這樣設計的主要原因還是因為要和C代碼的驅動接口,做成這樣效率會高些。
例如,我們要發送一個,id為5的標準數據幀,數據長度為3,分別是0x01,0x02,0x03,代碼如下:
CAN_MESSAGE pktSend = new CAN_MESSAGE();
pktSend.id = 5;
//如果是數據幀就不變,如果是遠程幀就
//pktSend.id = pktSend.id | 0x20000000;//remote
//如果是標準幀就不變,如果是擴展幀就
//pktSend.id = pktSend.id | 0x40000000;//extended
pktSend.data[0] = 3;
pktSend.data[1] = 0x01;
pktSend.data[2] = 0x02;
pktSend.data[3] = 0x03;
例如,我們要發送一個,id為55的擴展幀,數據長度為6,分別是0x04,0x04,0x04,0x05,0x05,0x05,代碼如下:
CAN_MESSAGE pktSend = new CAN_MESSAGE();
pktSend.id = 5;
//如果是數據幀就不變,如果是遠程幀就
//pktSend.id = pktSend.id | 0x20000000;//remote
//如果是標準幀就不變,如果是擴展幀就
pktSend.id = pktSend.id | 0x40000000;//extended
pktSend.data[0] = 6;
pktSend.data[1] = 0x04;
pktSend.data[2] = 0x04;
pktSend.data[3] = 0x04
pktSend.data[4] = 0x05;
pktSend.data[5] = 0x05;
pktSend.data[6] = 0x05;
CAN過濾條件Filter設置
EM335x同樣支持數據包過濾功能,設置Filter可以使得CAN只接收自己需要的數據包。
調用EM335X_CAN類的SetFilter方法,可以添加一個過濾條件,或者刪除一個已有的過濾條件。例如:
CAN.CAN_SetFilter (hCAN, Filter, false );
第一個參數為CAN句柄,第二個參數為過濾條件參數,為一個CAN_FILTER的結構體,在下面有說明。第三個參數如果為FALSE,則表示添加該過濾條件,如果為TRUE,則表示刪除已有的該過濾條件。
有多個過濾條件的情況下,只要數據包可以滿足任意一個過濾條件,那么該數據包就可以被接收。
CAN過濾條件Filter結構體定義
CAN_FILTER結構體定義如下:
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct CAN_FILTER
{
[FieldOffset(0)]
public uint id;
[FieldOffset(4)]
public uint mask;
}
這里的過濾邏輯如下:
假設收到的數據包里的id,我們記為id_message,與過濾條件中的filter參數里的id和mask滿足條件:(id_message&mask) == (id&mask),那么該數據包就可以接收,也就是說,mask表示需要進行對比的位,如果數據包的id這幾位與filter設置里的id的這幾位相同,那么該數據包就可以接收。
比如:
一個filter的mask = 0x03,即2進制的b0000 0011,即需要比較最后的兩位。
filter的id = 0x02,即2進制的b0000 0010。
那么數據包id如果最后兩位為 10,該數據包就可以通過過濾條件被接收。
數據包id = 0xF7,即2進制b1111 0111,無法接收。
數據包id = 0xE6,即2進制b1110 0110,可以接收。
詳細信息,可以電話,郵件或論壇提問方式咨詢英創工程師。
-
嵌入式主板
+關注
關注
7文章
6086瀏覽量
35617
發布評論請先 登錄
相關推薦
dsPIC33C Touch-CAN-LIN Curiosity開發板用戶指南
![dsPIC33<b class='flag-5'>C</b> Touch-<b class='flag-5'>CAN</b>-LIN Curiosity<b class='flag-5'>開發</b>板用戶指南](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
液顯ID讀卡器C#小程序開發
![液顯ID讀卡器<b class='flag-5'>C#</b>小程序<b class='flag-5'>開發</b>](https://file1.elecfans.com/web3/M00/05/85/wKgZPGeAw16AYHH-AAPCP23Pv_M129.png)
中科創達榮獲2024年軟件和信息技術服務優秀企業
加速鯤鵬落地!拓維信息信創遷移工具榮獲鯤鵬原生開發技術認證
![加速鯤鵬落地!拓維<b class='flag-5'>信息</b>信<b class='flag-5'>創</b>遷移工具榮獲鯤鵬原生<b class='flag-5'>開發</b><b class='flag-5'>技術</b>認證](https://file.elecfans.com/web2/M00/46/D0/pYYBAGKV5wiAQkFLAAA0HUPKaH4034.jpg)
[can開發板] 一款低價can/obd2總線Linux開發板
如何檢測can通訊電路的好壞
MGMF442L1C7-MINAS A6N系列 介紹 松下
![MGMF442L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介紹</b> 松下](https://file1.elecfans.com/web2/M00/A9/42/wKgaomUwmYKAXjWEAAAsCdY_muE289.png)
MGMF132L1C7-MINAS A6N系列 介紹 松下
![MGMF132L1<b class='flag-5'>C7</b>-MINAS A6N系列 <b class='flag-5'>介紹</b> 松下](https://file1.elecfans.com/web2/M00/A9/42/wKgaomUwmYKAXjWEAAAsCdY_muE289.png)
評論