基于QT编写的解析周立功CAN
1.介绍
应用场景:需要将CAN数据传输到上位机。
可以进行界面显示,做一些基于can的演示系统等
2.封装的模块
1.CanComm.c 中间层 封装通信函数
封装了
可以读取uds报文
可以写入uds报文
可以读取应用报文
可以写入应用报文
2.cantxthread.cpp 中间层 重底层读取
3.canrxthread.cpp 中间层 重底层读取
4.zlgCANFunctions.cpp 底层 周立功库函数封装
5.xlCANFunctions.cpp 底层 周立功库函数封装
6.widget.cpp 应用层
3.基本的一些介绍
底层周立功zlgCANFunctions.cpp 介绍
bool zlgCANFunctions::zlgCANInit(int devtype,unsigned long baud, int canNum)
{
VCI_INIT_CONFIG init_config;
int baudTemp;
m_devtype = devtype;
m_canind = canNum;
m_devind = 0;
/* 0x700 ~ 0x7ff */
// if (0 == canExternFlag)
// {
// init_config.AccCode = 0xE0000000;
// init_config.AccMask = 0x1FFFFFFF;
// }
// else
// {
// init_config.AccCode = 0x00003800;
// init_config.AccMask = 0xFFFFC7FF;
// }
/* 不滤波 */
init_config.AccCode = 0x00;//0xE0000000;
init_config.AccMask = 0xFFFFFFFF;//0x1FFFFFFF;
/* 0->双滤波 , 1->单滤波 */
init_config.Filter = 1;
/* 0->正常模式,1->监听模式 */
init_config.Mode = 0;
switch(baud)
{
case 500000://500k
default:
if (m_devtype == VCI_USBCAN2)
{
init_config.Timing0 = 0x00;
init_config.Timing1 = 0x1c;
}
else if (((m_devtype == VCI_USBCAN_E_U))||((m_devtype == VCI_USBCAN_2E_U)))
{
baudTemp = 0x60007;
}
break;
case 250000://250k
if (m_devtype == VCI_USBCAN2)
{
init_config.Timing0 = 0x01;
init_config.Timing1 = 0x1c;
}
else if (((m_devtype == VCI_USBCAN_E_U))||((m_devtype == VCI_USBCAN_2E_U)))
{
baudTemp = 0x1c0008;
}
break;
case 125000://125k
if (m_devtype == VCI_USBCAN2)
{
init_config.Timing0 = 0x03;
init_config.Timing1 = 0x1c;
}
else if (((m_devtype == VCI_USBCAN_E_U))||((m_devtype == VCI_USBCAN_2E_U)))
{
baudTemp = 0x1c0011;
}
break;
}
if(VCI_OpenDevice(m_devtype,m_devind,0) != STATUS_OK )
{
return false;
}
if(VCI_SetReference(m_devtype,m_devind,m_canind,0,&baudTemp)!= STATUS_OK)
{
VCI_CloseDevice(m_devtype,m_devind);
return false;
}
if(VCI_InitCAN(m_devtype,m_devind,m_canind,&init_config)!= STATUS_OK)
{
VCI_CloseDevice(m_devtype,m_devind);
return false;
}
if(VCI_StartCAN(m_devtype,m_devind,m_canind) != STATUS_OK )
{
VCI_CloseDevice(m_devtype,m_devind);
return false;
}
VCI_ClearBuffer(m_devtype,m_devind,0);
return true;
}
这个底层配置周立功CAN设置,可以自行查看周立功CAN的封装库
需要支持你的CAN卡只需要添加更改这个代码块即可
查看ControlCAN.h 导入相应名称即可
switch(baud)
{
case 500000://500k
default:
if (m_devtype == VCI_USBCAN2)
{
init_config.Timing0 = 0x00;
init_config.Timing1 = 0x1c;
}
else if (((m_devtype == VCI_USBCAN_E_U))||((m_devtype == VCI_USBCAN_2E_U)))
{
baudTemp = 0x60007;
}
break;
case 250000://250k
if (m_devtype == VCI_USBCAN2)
{
init_config.Timing0 = 0x01;
init_config.Timing1 = 0x1c;
}
else if (((m_devtype == VCI_USBCAN_E_U))||((m_devtype == VCI_USBCAN_2E_U)))
{
baudTemp = 0x1c0008;
}
break;
case 125000://125k
if (m_devtype == VCI_USBCAN2)
{
init_config.Timing0 = 0x03;
init_config.Timing1 = 0x1c;
}
else if (((m_devtype == VCI_USBCAN_E_U))||((m_devtype == VCI_USBCAN_2E_U)))
{
baudTemp = 0x1c0011;
}
break;
}
拿取数据的周期及数据数。这里使用的函数VCI_GetReceiveNum及VCI_Receive
周立功的库开发里面有使用方法
bool zlgCANFunctions::zlgCANRecv()
{
VCI_CAN_OBJ rec[20];//这里10ms拿取20为拿取的数据数
int reclen ,i;
int length = VCI_GetReceiveNum(m_devtype,m_devind,m_canind);
if(length <= 0)
{
return false;
}
if(length > 20)
{
length = 20;
}
mutex.lock();
if((reclen = VCI_Receive(m_devtype,m_devind,m_canind,rec,length,10))>0)//周期10MS
{
for(i = 0; i < reclen; i++)
{
COMM_WriteRxMessage(rec[i].ID,rec[i].Data,rec[i].DataLen);
}
}
mutex.unlock();
return true;
}
可以在这里更改周期等。使用方法如下
相应的一些底层配置都在zlgCANFunctions.cpp 这个里面。一些配置都在这里修改。使用方法查看周立功的接口函数的调用方法
CanComm.c中间层 介绍
你需要重can读取数据,就需要把数据放到一个池子里面,然后在周期性的去取数据出来。这里的中间层就起到了一个缓存池的作用
已经封装了多个函数。读应用数据,写应用数据,读uds数据,写uds数据
。这里就可以开发uds、can应用型上位。
/***************************************************************
** Function Name : App_SendAppMsgToCOMM
** Description : 插入应用报文到队列中去
** Input parameters: NONE
** Return Value : NONE
** Version : V0.1
** Author : WZH
***************************************************************/
void App_SendAppMsgToCOMM(unsigned int can_id,unsigned char *buffer,unsigned char length)
{
unsigned char i = 0;
if(!g_tCanAppMsgTx.full)
{
g_tCanAppMsgTx.msg[g_tCanAppMsgTx.wr_index].canId = can_id;
g_tCanAppMsgTx.msg[g_tCanAppMsgTx.wr_index].len = length;
for( i = 0 ; i < length ; i++)
{
g_tCanAppMsgTx.msg[g_tCanAppMsgTx.wr_index].buffer[i] = buffer[i];
}
if (++g_tCanAppMsgTx.wr_index >= CAN_MSG_QUEUE_LEN)
{
g_tCanAppMsgTx.wr_index = 0;
}
if (g_tCanAppMsgTx.wr_index == g_tCanAppMsgTx.rd_index)
{
g_tCanAppMsgTx.full = 1;
}
}
if(!g_tCanAllMsg.full)
{
g_tCanAllMsg.msg[g_tCanAllMsg.wr_index].canId = can_id;
g_tCanAllMsg.msg[g_tCanAllMsg.wr_index].len = length;
MemeryCopy(g_tCanAllMsg.msg[g_tCanAllMsg.wr_index].buffer,buffer,8);
if(++g_tCanAllMsg.wr_index >= CAN_MSG_QUEUE_LEN)
{
g_tCanAllMsg.wr_index = 0;
}
if(g_tCanAllMsg.wr_index == g_tCanAllMsg.rd_index)
{
g_tCanAllMsg.full = 1;
}
}
}
4.demo分享
这里提供一个demo 。只需要更改serial.cpp就可以了。
1、https://download.csdn.net/download/a_954710805/13053480
2、https://wwdj.lanzout.com/iDEu20x0dk1i
5.Tsmaster调用库来完成底层库
关注我另外一个文章
https://blog.csdn.net/a_954710805/article/details/130821093?spm=1001.2014.3001.5501