用戶可從英創(chuàng)開發(fā)光盤中或聯(lián)系英創(chuàng)工程師獲得CAN例程源碼。參考例程使用英創(chuàng)已經(jīng)封裝好的.h及.cpp庫(kù)文件可以使開發(fā)更方便。
注冊(cè)表設(shè)置項(xiàng)說(shuō)明
CAN驅(qū)動(dòng)設(shè)置參數(shù)位于注冊(cè)表[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\CAN1]及[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\CAN2]下
主要配置參數(shù)項(xiàng):
TxTimeout:發(fā)送超時(shí)時(shí)間,單位ms。
BusErrorReport:錯(cuò)誤幀上報(bào)標(biāo)記,0:不上報(bào),1:上報(bào)錯(cuò)誤幀
設(shè)置程序可以連接英創(chuàng)工程師獲得。
CAN打開及關(guān)閉
打開關(guān)閉采用標(biāo)準(zhǔn)的流式設(shè)備驅(qū)動(dòng)接口CreateFile及CloseHandle,設(shè)備名為”CAN1:”及”CAN2:”
調(diào)用示例如下:
//打開CAN1
HANDLE hCan;
hCan = CreateFile( L”CAN1:”, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
//關(guān)閉CAN
CloseHandle(hCan);
CAN波特率設(shè)置
參考CAN例程,對(duì)驅(qū)動(dòng)的DeviceIoCon trol操作已封裝在SetBaud函數(shù)中。
BOOLSetBaud(HANDLE hCan, DWORD dwBaud)
參數(shù)hCan:CreateFile打開CAN返回的設(shè)備句柄
參數(shù)dwBaud:波特率,單位bps
返回值:TRUE 設(shè)置成功,F(xiàn)ALSE 設(shè)置失敗
調(diào)用示例如下:
//設(shè)置波特率250bps CAN
SetBaud(m_hCan, 250000);
CAN過(guò)濾設(shè)置
調(diào)用方法
參考CAN例程,對(duì)驅(qū)動(dòng)的DeviceIoCon trol操作已封裝在SetFilter函數(shù)中。
BOOLSetFilter(HANDLE hCan, PCAN_FILTER pFilter, DWORD num)
參數(shù)hCan:CreateFile打開CAN返回的設(shè)備句柄
參數(shù)pFilter:過(guò)濾器結(jié)構(gòu)體數(shù)組指針
參數(shù)num:過(guò)濾器結(jié)構(gòu)體數(shù)組長(zhǎng)度,最大為4
返回值:TRUE 設(shè)置成功,F(xiàn)ALSE 設(shè)置失敗
注:此函數(shù)如果重復(fù)調(diào)用,生效的為最后一次調(diào)用設(shè)置值。
CAN_FILTER過(guò)濾器結(jié)構(gòu)體定義
typedefstruct_can_filter
{
CAN_ID can_id;
CAN_ID can_mask;
} CAN_FILTER, *PCAN_FILTER
過(guò)濾器由id和mask組成,設(shè)置的過(guò)濾器組數(shù)最大4個(gè)。CAN包能滿足其中一組過(guò)濾器以下條件才能接收
CAN包id & 過(guò)濾器mask = 過(guò)濾器id
即,2進(jìn)制中,過(guò)濾MASK為1的對(duì)應(yīng)位需和過(guò)濾ID值一致,示例表
調(diào)用示例如下
//設(shè)置一組寄存器
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發(fā)送/接收
發(fā)送接收同樣采用標(biāo)準(zhǔn)的流式設(shè)備驅(qū)動(dòng)接口ReadFile及WriteFile
調(diào)用方法
參考CAN例程,封裝好的函數(shù)定義。
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);
}
參數(shù)hCan:CreateFile打開CAN返回的設(shè)備句柄
參數(shù)pFrame:幀結(jié)構(gòu)體數(shù)組指針
參數(shù)num:幀結(jié)構(gòu)體數(shù)組長(zhǎng)度,默認(rèn)值1,可空
返回值:發(fā)送/接收的數(shù)據(jù)包個(gè)數(shù)
注:發(fā)送函數(shù)為阻塞函數(shù),超時(shí)時(shí)間可以在注冊(cè)表中設(shè)置,默認(rèn)1000ms。
發(fā)送失敗后,應(yīng)用程序應(yīng)當(dāng)自行判斷是否需要重新發(fā)送。
接收函數(shù)應(yīng)當(dāng)單獨(dú)開一個(gè)接收線程,并配合WaitCANEvent函數(shù)使用,參考下一節(jié)。
CAN_FRAME數(shù)據(jù)幀結(jié)構(gòu)體定義
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;
調(diào)用示例如下:
DWORD dwNum;
//發(fā)送
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函數(shù)使用
如果輪詢方式接收CAN包,系統(tǒng)負(fù)荷會(huì)過(guò)高,采用事件方式事半功
WaitCANEvent為等待CAN接收事件的阻塞函數(shù),通過(guò)返回值可以判斷是否有CAN數(shù)據(jù)接收。
BOOLWaitCANEvent( HANDLE hDevice, LPDWORD lpEvtMask, DWORD dwTimeout )
參數(shù)hDevice:CreateFile打開CAN返回的設(shè)備句柄
參數(shù)lpEvtMask:返回事件類型,新驅(qū)動(dòng)目前恒為0
參數(shù)dwTimeout:超時(shí)時(shí)間
返回值:FALSE 等待超時(shí),TRUE 有數(shù)據(jù)幀收到
接收線程調(diào)用示例
//主線程中開啟接收線程
m_hRecvThread = CreateThread(0, 0, RecvTread,this, 0, NULL);
//接收線程函數(shù)定義
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 ) // 接收到數(shù)據(jù)包
{
num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY);
while( num )
{
OnRecv(pDlg, rbuf, num); //調(diào)用回調(diào)函數(shù)處理數(shù)據(jù)
num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY);
}
}
else //258
{
}
}
}
return0;
}
錯(cuò)誤幀定義
當(dāng)設(shè)置注冊(cè)表選項(xiàng),允許接收錯(cuò)誤幀后,CAN總線上的出錯(cuò)信息將以幀的形式上報(bào)上來(lái)。
錯(cuò)誤幀的幀結(jié)構(gòu)體中,值為1,可通過(guò)該值判斷是接收到的數(shù)據(jù)幀還是驅(qū)動(dòng)上報(bào)的錯(cuò)誤幀。
if(Frame.can_id.error){
//錯(cuò)誤幀
}
else{
//數(shù)據(jù)幀;
}
錯(cuò)誤幀詳細(xì)定義,請(qǐng)參數(shù)手冊(cè)《CAN錯(cuò)誤幀定義》。
精簡(jiǎn)掉的接口
新CAN驅(qū)動(dòng)能夠自動(dòng)復(fù)位CAN總線,不需要再手動(dòng)復(fù)位,所以之前ResetCAN,StartCAN,StopCAN精簡(jiǎn)掉了。
SetCANLoop功能實(shí)用性不大,故精簡(jiǎn)掉。
但是為了兼容老驅(qū)動(dòng),這些函數(shù)依然可以正常調(diào)用。
相關(guān)測(cè)試?yán)炭梢月?lián)系英創(chuàng)工程師獲得。
-
嵌入式主板
+關(guān)注
關(guān)注
7文章
6086瀏覽量
35616
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論