Can通信模块详细设计说明书.docx
- 文档编号:26726381
- 上传时间:2023-06-22
- 格式:DOCX
- 页数:25
- 大小:143.43KB
Can通信模块详细设计说明书.docx
《Can通信模块详细设计说明书.docx》由会员分享,可在线阅读,更多相关《Can通信模块详细设计说明书.docx(25页珍藏版)》请在冰豆网上搜索。
Can通信模块详细设计说明书
Can.cpp模块设计说明
1.总则:
传送故障记录数据或运行记录数据时,不传送参数数据和实时数据。
传送参数数据和实时数据可同时传送。
在界面层:
1.读故障记录数据BUTTON和运行记录数据BUTTON和记录实时数据BUTTON没有按下,参数没有操作时,才能按下读故障记录数据BUTTON或运行记录数据BUTTON。
否则弹出信息框。
2.按下故障记录数据BUTTON后,把运行记录数据BUTTON和记录实时数据BUTTON变灰,参数MENU和参数界面上的读和修改BUTTON变灰,故障记录数据读完后,上述按钮复原。
对按下运行记录数据BUTTON作同样处理。
3.按下记录实时数据BUTTON时,把故障记录数据BUTTON和运行记录数据BUTTON变灰。
按下停止记录实时数据BUTTON时,把故障记录数据BUTTON和运行记录数据BUTTON复原。
4.对参数上载和修改时,把故障记录数据BUTTON和运行记录数据BUTTON变灰,完成操作后把故障记录数据BUTTON和运行记录数据BUTTON复原。
CAN和以太网类似,相应7种事件:
关闭CAN、实时数据请求、读参数、写参数、发送心跳报文,读故障记录,读运行记录。
2功能
模块类名为:
ClassCan
类对象定义在Can.cpp中,是一个全局对象。
ClassLang_Can;
该模块的功能为:
1.
通过USB转CAN与下位机进仃头时数据请求和参数的上传下载读运行记录;
,读故障记录,
2.
通过PCI插卡与下位机进仃头时数据请求和参数的上传下载运行记录;
,读故障记录,读
3.
出错处理。
3流程逻辑
CAN部分由线程CanThread(宽成5个事件。
OpenCan(DWORDDevType,DWORDDevIndex,DWORDReserved)函数通过调用API函数VCI_OpenDevice(DWORDDevType,DWORDDevIndex,DWORDReserved)打开CAN;
CloseCan(DWORDDevType,DWORDDevIndex)函数通过调用API函数VCI_CloseDevice(DWORDDevType,DWORDDevIndex)关闭CAN;
StartCanThread()函数用于开启Can线程;
SuspendedCanThread()函数用于关闭线程;
CanThread()为Can线程函数,用于执行五种事件:
关闭Can、发送实时数据请求、读参数、写参数和发送心跳报文。
SendCanPacket(intiEvent,intIndex=0,intSubIndex=0,*Data=NULL)为CAN发送报文函数,iEvent为事件值,Index、SubIndex、Data用于参数的读写事件。
根据不同的事件,发送相应的报文。
RecvCanPacket()
JudgeOvertime();
以上函数形参封装在以下的数据结构中:
typedefstruct_CAN_DEVICE_PARM_
{
DWORDdwDevType;〃设备类型号
DWORDdwDevIndex;〃设备索引号
DWORDdwReserved;〃保留
DWORDdwCANIndex;//Can第几路
DWORDdwChecCode;//验收码
DWORDdwMask;//屏蔽码
DWORDm_dwMode;//模式
intiTimer0;//定时器
intiTimer1;//定时器
intiFilterType;//滤波方式
}CAN_DEVICE_PARM;
typedefstruct_VCI_CAN_OBJ{
UINTuiID;
UINTuiTimeStamp;
BYTEbyTimeFlag;
BYTEbySendType;
BYTEbyRemoteFlag;//是否是远程帧
BYTEbyExternFlag;//是否是扩展帧
BYTEbyDataNbytes;
BYTEbyDataBuf[8];
BYTEbyReserved[3];
}VCI_CAN_OBJ,*PVCI_CAN_OBJ;
成员
uiID:
报文ID;
uiTimeStamp:
接收到信息帧的时间标识,从CAN控制器初始化开始计时;
byTimeFlag:
是否使用时间标识,为1时uiTimeStamp有效,byTimeFlag和
uiTimeStamp只在此帧为接收帧时有意义;
bySendType:
发送帧类型,0为正常发送,1为单次发送,2为自发自收,3为单次自发自收只在此帧为发送帧时有意义;
byRemoteFlag:
是否为远程帧;
byExternFlag:
是否为扩展帧;
byDataNbytes:
数据长度(<=8),即Data的长度;
byDataBuf:
报文的数据;
byReserved:
系统保留。
typedefstruct_VCI_INIT_CONFIG{
DWORDdwAccCode;
DWORDdwAccMask;
DWORDdwReserved;
UCHARucFilter;
UCHARucTiming0;
UCHARucTiming1;
UCHARucMode;
}VCI_INIT_CONFIG,*PVCI_INIT_CONFIG;
成员:
dwAccCode:
验收码;
dwAccMask:
屏蔽码;
dwReserved:
系统保留;
ucFilter:
滤波方式,1为单波方式,0为双波方式;
ucTiming0:
定时器0;
ucTimingl:
定时器1;
ucMode:
模式。
0为正常模式,1为只听模式
在Datalayer.cpp中添加成员变量:
BYTEm_byCANRealTimeBuffer[];
BYTEm_byCANParmBuffer[];
添加成员函数:
intGetDataFromCANPacket();
对CAN接收到的数据进行解析分类,将数据存于他对应的地方。
CAN从界面层到通讯层的整体流程图:
OpenCAN()函数流程图:
SendCanPacket()流程图:
SendCanPacket。
判断iEvent
CANThread()流程图:
关闭CANN
发送实时数
据请求报文
接收实时数
据报文
While判断是否瓷生其他事件并且是否为一*..-组数据的最后一帧'
发送故障记
录请求报文
接收实时数
据报文
通过返回值
判断是否超
时重发请求
通过返回值
判断是否超
时重发请求
1)如收到的是
心跳报文;则丢掉
ID
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
0x702
0x01
State
0
0
0
0
0
0
0
2)如收到的是’中止SDO请求报文’(最后4个字节是16进制中止代码之一■
——06010000,其功能描述是对象不支持访问勺
CAN
ID
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
DL
0x582
0x08
0x80
Index
Sub-index
00
00
01
06
则上位机通知参数设定界面,参数设定界面弹出对话框告知参数INDEX或
SUBINDEX出错。
上位机停止上传/下载系统参数。
4实时数据和参数通信过程(供参考)
4.1数据结构:
在InternalDef.h中增加
#defineLIMIT_CAN_RECV_ONE_PACKET_TIMEOUT_MS200
#definePACKET_TIMEOUT2
在PdasConfig中增加
Intm_iCanRecvOnePacketTimeoutMs;
在PdasCong.cpp中
m_iCanRecvOnePacketTimeoutMs=LIMIT_CAN_RECV_ONE_PACKET_TIM
EOUT_MS
在DataLayer.h中增加
intm_iCanRealTimeDataNbytes;//UDP收到的数据长度
BYTEm_byCanRealTimeData[500];
在Can.h中增加
BYTEm_byRealTimeData[12][8]
Intm_iIndexOfRealTimeData;
BOOLm_bFirstRealTimeBlock
4.2程序伪代码:
1.初始化m_byRealTimeData[][]为全0,且
m_byRealTimeData[0][0]=0xff;
m_bFirstRealTimeBlock=TRUE
2.在应该发送的时刻调用SendNmi(0x01)函数
然后调用VCI_Trasmit()
3.
BOOLbShouldSave=FALSE;
While(TRUE)
{
If(ShouldSendParmPacket(...)){〃有上载参数报文或修改参数报文要发送
OrganizeParmPacket(...)〃组织发送
VCI_Transmit(...)
}
iNbytes=VCI_Receive(...),超时时间用变量g_PdasConfig.CanRecvOnePacketTimeoutMs;
iState=ProcessPossibleTimeOut(...)〃返回PACKET_TIMEOUT或DEVICE_FAULT
If(iState==PACKET_TIMEOUT)
Continue;
Elseif(iState==DEVICE_FAULT)
{
g_DataLayer.iDeviceState[DEVICE_CAN]=DEVICE_FAULT
Break;
}
iPacketType=JudgeReceivedPacketType(...)
If(iPacketType==REAL_TIME_DATA||
==LAST_REAL_TIME_DATA)〃收到实时数据报文
根据ID,DL,Byte放入相应m_byRealTimeData[?
][]
Elseif(iPacketType==UPLOAD_PARM)
ProcessUpLoadParm(....)〃参数报文处理
Elseif(iPacketType==MODITY_PARM)
ProcessModityParm(...)//参数报文处理
If(iPacketType==LAST_REAL_TIME_DATA)//(0x484,0x08,0x0B)收到
{
If(m_iReadRecordStage==BEGNbreak
〃退出循环,去读故障记录数据
If(m_bFirstRealTimeBlock==TRUE)
{
If(12个报文全收到)
{
m_bFirstRealTimeBlock=FALSE
bShouldSave=TRUE
}
}
Else
{
bShouldSave=TRUE
}
}
If(bShouldSave)
{
bShouldSave=FALSE;
g_DataLayer.PutRealTimeData(m_byRealTimeData,iErrorCode,DEVICE_CAN);
}}//endofWhile()
5传送故障记录数据或运行记录数据过程(供参考)5.1数据结构:
InternalDef.h中增加#defineNON_RECORD0
#defineFAULT_RECORD1
#defineNORMAL_RECORD2
#defineBEGIN_RECORD1
0x2000
0x3000
(0x3000-1)
(0x4000-1)
...#defineCOMPLETE_RECORDxx
#defineFIRST_INDEX_OF_FAULT_RECORD
#defineFIRST_INDEX_OF_NORMAL_RECORD
#defineLAST_INDEX_OF_FAULT_RECORD
#defineLAST_INDEX_OF_NORMAL_RECORD
〃现由周提供
PdasConfig.h中增加Intm_iFirstIndexOfFaultRecordIntm_iFirstIndexOfNormalRecordIntm_iLastIndexOfFaultRecord
Intm_iLastIndexOfNormalRecord
PdasConfig.cpp中增加
对它们赋初值
Can类中增加
Intm_iRecvRecordType
Intm_iRecvRecordStage
BYTEm_byRecordData[12][8]
Intm_iIndexOfRecordData;
Intm_iSubIndexOfRecordData
Intm_iBlockSizeOfRecordData
DalaLayer中增加
RecvFaultRecord(..)
RecvNormalRecord(...)
5.2伪代码
1.对故障记录数据,界面调用g_DataLayer.RecvFaultRecord().
g_DataLayer.RecvFaultRecord()勺工作:
-设置变量Can.m_iRecvRecordStage=BEGIN
还是设置事件m_EventRecvRecord?
?
?
M论
-设置Can.m_iRecvRecordType=FAULT_RECORD
对故障记录数据,界面调用g_DataLayer.RecvNormalRecord().
g_DataLayer.RecvNormalRecord()勺工作:
-设置变量Can.m_iRecvRecordStage=BEGIN_RECORD
还是设置事件m_EventRecvRecord?
?
?
M论
-设置Can.m_iRecvRecordType=NORMAL_RECOED
初始化m_byRecordData[12][8]为0和m_byReacordData[0][0]为0xFF。
2.CanThread的代码
在适当时刻检查一系歹0变量(事件?
?
?
),当检查到m_iRecvRecord
Stage==BEGIN_RECORD时,做:
OpenRecordFile()〃伪代码后面提供
-设置m_iRecvRecordType=NORMAL_RECOED
初始化m_byRecordData[12][8]为0和m_byReacordData[0][0]为0xFF。
-设置m_iReadRecordStage=SEND_SDO1
-设置If(m_iReadRecordType==FAULT_RECORD)
m_iIndexOfRecordData
=g_PdasConfig.m_iFirstIndexOfFaultRecord
Else(m_iReadRecordType==NORMAL_RECORD)
m_iIndexOfRecordData=
g_PdasConfig.m_iFirstIndexOfNormalRecord
-设置m_iSubIndexOfRecordData=0;
m_iBlockSizeOfRecordData=128
-调用SendNmi(0x80)函数
该函数组织报文(00,02,80,02,00,00,00,00,00,00
然后调用VCI_Trasmit()
3.调用SendSdo1()函数
SDO1
ID
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
DL0x602
0x08
0xA4
m_iIndex
m_iSubIndex
m_iBlockSize
0
0
0
然后调用VCI_Transmit()
-设置m_iReadRecordStage=RECV_SDO2
4.CanThread等待接收报文Sdo2
调用VCI_Receive(),超时时间用变量g_PdasConfig.CanRecvOnePacketTimeoutMs
iState=ProcessPossibleTimeOut(...)〃返回PACKET_TIMEOUT或DEVICE_FAULT
If(iState==PACKET_TIMEOUT)
超时处理?
?
?
Elseif(iState==DEVICE_FAULT)
{
g_DataLayer.iDeviceState[DEVICE_CAN]=DEVICE_FAULT
故障处理?
?
?
}
-如果准确,即收到的是
SDO2
ID
ni
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
0x582
0x08
0xC6
Index
Sub-index
size
00
00
0
0
调用SendSdo3()函数
SDO3
ID
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
DL0x602
0x08
0xA3
0
0
0
0
0
0
然后调用VCI_Transmit()发送
设置m_iReadRecordStage=RECV_DATA
5.接收报文
调用VCI_Receive(),超时时间用变量g_PdasConfig.CanRecvOnePacketTimeoutMs
iState=ProcessPossibleTimeOut(...)〃返回PACKET_TIMEOUT或
DEVICE_FAULT
If(iState==PACKET_TIMEOUT)
超时处理?
?
?
Elseif(iState==DEVICE_FAULT)
{
g_DataLayer.iDeviceState[DEVICE_CAN]=DEVICE_FAULT
故障处理?
?
?
}
-如果准确,即收到的是
SDO
ID
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
Bit7
Bit6-0
1
0x582
0x08
0
0
xx
xx
xx
xx
xx
xx
xx
2
0x582
0x08
0
1
xx
xx
xx
xx
xx
xx
xx
3
0x582
0x08
0
2
xx
xx
xx
xx
xx
xx
xx
……
……
……
……
……
……
……
……
……
……
……
……
N-1
0x582
0x08
0
N-1
xx
xx
xx
xx
xx
xx
xx
N
0x582
0x08
1
N
xx
xx
xx
xx
xx
xx
xx
根据ID,DL,Byte0的Bit6-0位把Byte0到Byte7放入m_byRecordData[][].
If(Byte。
的Bit7为1)
{
m_iReadRecordStage=SEND_SDO4iLastBlockNo=Byte0的Bit6-0的值}
否则继续5
6.调用SendSdo4()函数
该函数组织报文
SDO4
ID
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
0x602
0x08
0xA2
1
blksize
0
0
0
0
0
然后调用VCI_Transmit()
-设置m_iReadRecordStage=RECV_SDO5
7CanThread等待接收报文Sdo5
调用VCI_Receive(),超时时间用变量g_PdasConfig.CanRecvOnePacketTimeoutMs
iState=ProcessPossibleTimeOut(...)〃返回PACKET_TIMEOUT或
DEVICE_FAULT
If(iState==PACKET_TIMEOUT)
超时处理?
?
?
Elseif(iState==DEVICE_FAULT)
{
g_DataLayer.iDeviceState[DEVICE_CAN]=DEVICE_FAULT
故障处理?
?
?
}
-如果准确,即收到的是
SDO5
ID
_DJ
DL
Byte0
Byte1
Byte2
Byte3
Byte4
Byte5
Byte6
Byte7
0x582
0x08
byPacketCmd
byPacketCrc
0
0
0
0
0
注:
byPacketcmd=((0x06<<5)|((7-size%7)<<2)|0x01),其中size
表示所要上传的数据数量(字节数)。
byPacketCrc为整个数据的CRC校验。
//PC计算cmd和CRC(使用变量byMyCmd,byMyCrc)
byMyCmd=CalCmd(&m_byRecordData[][],iLastBlockNo);
byMyCrc=CalCrc(&m_byRecordData[][],iLastBlockNo);
If(byMyCmd==byPacketCmd&&byMyCrc==byPacketCrc)
{
则file.write(m_byRecordBuf,limit_block_nbytes)
++m_iSubIndexOfRecordData;
If(m_iSubIndexOfRecord==0)m_iIndexOfRecordData++;
}
设置m_iRecvRecordStage=RECV_SDO6
8.调用SendSdo6()函数
该函
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Can 通信 模块 详细 设计 说明书