用戶可從英創開發光盤中或聯系英創工程師獲得CAN例程源碼。參考例程使用英創已經封裝好的.h及.cpp庫文件可以使開發更方便。
注冊表設置項說明
CAN驅動設置參數位于注冊表[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\CAN1]及[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\CAN2]下
主要配置參數項:
TxTimeout:發送超時時間,單位ms。
BusErrorReport:錯誤幀上報標記,0:不上報,1:上報錯誤幀
設置程序可以連接英創工程師獲得。
CAN打開及關閉
打開關閉采用標準的流式設備驅動接口CreateFile及CloseHandle,設備名為”CAN1:”及”CAN2:”
調用示例如下:
//打開CAN1
HANDLE hCan;
hCan = CreateFile( L”CAN1:”, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
//關閉CAN
CloseHandle(hCan);
CAN波特率設置
參考CAN例程,對驅動的DeviceIoCon trol操作已封裝在SetBaud函數中。
BOOLSetBaud(HANDLE hCan, DWORD dwBaud)
參數hCan:CreateFile打開CAN返回的設備句柄
參數dwBaud:波特率,單位bps
返回值:TRUE 設置成功,FALSE 設置失敗
調用示例如下:
//設置波特率250bps CAN
SetBaud(m_hCan, 250000);
CAN過濾設置
調用方法
參考CAN例程,對驅動的DeviceIoCon trol操作已封裝在SetFilter函數中。
BOOLSetFilter(HANDLE hCan, PCAN_FILTER pFilter, DWORD num)
參數hCan:CreateFile打開CAN返回的設備句柄
參數pFilter:過濾器結構體數組指針
參數num:過濾器結構體數組長度,最大為4
返回值:TRUE 設置成功,FALSE 設置失敗
注:此函數如果重復調用,生效的為最后一次調用設置值。
CAN_FILTER過濾器結構體定義
typedefstruct_can_filter
{
CAN_ID can_id;
CAN_ID can_mask;
} CAN_FILTER, *PCAN_FILTER
過濾器由id和mask組成,設置的過濾器組數最大4個。CAN包能滿足其中一組過濾器以下條件才能接收
CAN包id & 過濾器mask = 過濾器id
即,2進制中,過濾MASK為1的對應位需和過濾ID值一致,示例表
調用示例如下
//設置一組寄存器
CAN_FILTER Filter[4];
memzero(Filter,sizeof(CAN_FILTER));
Filter[0].can_id.id = 5;
Filter[0].can_mask.id = 22;
SetFilter(m_hCan, Filter, 1);
CAN發送/接收
發送接收同樣采用標準的流式設備驅動接口ReadFile及WriteFile
調用方法
參考CAN例程,封裝好的函數定義。
intWriteCAN(HANDLE hCan, PCAN_FRAME pFrame, DWORD num){
DWORD dwLen;
if(!WriteFile( hCan, (char*)pFrame, num*sizeof(CAN_FRAME), &dwLen, 0 ))return0;
returndwLen/sizeof(CAN_FRAME);
}
intReadCAN(HANDLE hCan, PCAN_FRAME pFrame, DWORD num){
DWORD dwLen;
if(!ReadFile( hCan, (char*)pFrame, num*sizeof(CAN_FRAME), &dwLen, 0 ))return0;
returndwLen/sizeof(CAN_FRAME);
}
參數hCan:CreateFile打開CAN返回的設備句柄
參數pFrame:幀結構體數組指針
參數num:幀結構體數組長度,默認值1,可空
返回值:發送/接收的數據包個數
注:發送函數為阻塞函數,超時時間可以在注冊表中設置,默認1000ms。
發送失敗后,應用程序應當自行判斷是否需要重新發送。
接收函數應當單獨開一個接收線程,并配合WaitCANEvent函數使用,參考下一節。
CAN_FRAME數據幀結構體定義
typedefstruct{
unsignedintid:29;
unsignedinterror:1;
unsignedintremote:1;
unsignedintextended:1;
}CAN_ID;
typedefstruct_can_frame
{
CAN_ID can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
BYTE can_dlc; /* frame payload length in byte (0 ..CAN_MAX_DLEN) */
BYTE data[CAN_MAX_DLEN];
} CAN_FRAME, *PCAN_FRAME;
調用示例如下:
DWORD dwNum;
//發送
CAN_FRAME Sendframe;
memzero(Sendframe,sizeof(CAN_FRAME));
Sendframe.can_id.id = 6;
m_Sendframe.data[0] = 0x01;
m_Sendframe.can_dlc = 1;
dwNum = WriteCAN(hCan, &Sendframe);
//接收
CAN_FRAME Revframe[MAX_ARRAY];
dwNum = ReadCAN(hCan, Revframe, MAX_ARRAY);
WaitCANEvent函數使用
如果輪詢方式接收CAN包,系統負荷會過高,采用事件方式事半功
WaitCANEvent為等待CAN接收事件的阻塞函數,通過返回值可以判斷是否有CAN數據接收。
BOOLWaitCANEvent( HANDLE hDevice, LPDWORD lpEvtMask, DWORD dwTimeout )
參數hDevice:CreateFile打開CAN返回的設備句柄
參數lpEvtMask:返回事件類型,新驅動目前恒為0
參數dwTimeout:超時時間
返回值:FALSE 等待超時,TRUE 有數據幀收到
接收線程調用示例
//主線程中開啟接收線程
m_hRecvThread = CreateThread(0, 0, RecvTread,this, 0, NULL);
//接收線程函數定義
DWORD Ctest_can_v2Dlg::RecvTread(LPVOID lparam)
{
Ctest_can_v2Dlg* pDlg = (Ctest_can_v2Dlg*)lparam;
DWORD dwEvtMask;
int num;
CAN_FRAME rbuf[MAX_ARRAY];
while(!pDlg->m_bThreadStop)
{
if(WaitCANEvent(pDlg->m_hCan, &dwEvtMask, 200))
{
if( dwEvtMask == 0 ) // 接收到數據包
{
num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY);
while( num )
{
OnRecv(pDlg, rbuf, num); //調用回調函數處理數據
num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY);
}
}
else //258
{
}
}
}
return0;
}
錯誤幀定義
當設置注冊表選項,允許接收錯誤幀后,CAN總線上的出錯信息將以幀的形式上報上來。
錯誤幀的幀結構體中,值為1,可通過該值判斷是接收到的數據幀還是驅動上報的錯誤幀。
if(Frame.can_id.error){
//錯誤幀
}
else{
//數據幀;
}
錯誤幀詳細定義,請參數手冊《CAN錯誤幀定義》。
精簡掉的接口
新CAN驅動能夠自動復位CAN總線,不需要再手動復位,所以之前ResetCAN,StartCAN,StopCAN精簡掉了。
SetCANLoop功能實用性不大,故精簡掉。
但是為了兼容老驅動,這些函數依然可以正常調用。
相關測試例程可以聯系英創工程師獲得。
-
嵌入式主板
+關注
關注
7文章
6085瀏覽量
35420
發布評論請先 登錄
相關推薦
評論