📄 canmodbus.c
字号:
MODBUSsendbuf[1]=0x80 | function ;
MODBUSsendbuf[2]=0x02;
MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验
MODBUSsendlen=4; //计算CAN发送的数据长度
modbusDataToCan();
}
}
/*------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
函数名称: command_03_04()
函数功能: 作为MODBUS从设备 应答03 04 功能码
入口参数: function 功能码 *MODBUS_3_4area MODBUS区域指针
出口参数: 无
--------------------------------------------------------------------------------------
------------------------------------------------------------------------------------*/
void command_03_04(UINT8 function ,UINT16 *MODBUS_3_4area)
{
UINT16 regaddr;
UINT16 regcount;
UINT16 crc_1; //2008.7.6
regaddr=MODBUSrecvbuf[2]; //寄存器地址
regaddr=(regaddr<<8)|((UINT8)(MODBUSrecvbuf[3]));
regcount=MODBUSrecvbuf[4]; //寄存器数
regcount=(regcount<<8)|((UINT8)(MODBUSrecvbuf[5]));
MODBUSsendlen=5;
if( (regaddr<40) && (regcount==1) )
{
MODBUSsendbuf[0]=MODBUSaddr; //发送本机地址
MODBUSsendbuf[1]=function; //发送MODBUS功能码
MODBUSsendbuf[2]=0x02; //数据字节数
MODBUSsendbuf[3]=*(MODBUS_3_4area+regaddr) >> 8 ; //数据高位
MODBUSsendbuf[4]=*(MODBUS_3_4area+regaddr) & 0xff; //数据低位
crc_1=CRC16(MODBUSsendbuf,MODBUSsendlen);
MODBUSsendbuf[MODBUSsendlen]=(UINT8)(crc_1>>8); //+CRC_Hi
MODBUSsendlen++;
MODBUSsendbuf[MODBUSsendlen]=(UINT8)crc_1; //+CRC_Low
MODBUSsendlen++; //计算CAN发送的数据长度
modbusDataToCan();
}
else
{
MODBUSsendbuf[0]=MODBUSaddr;
MODBUSsendbuf[1]=0x80 | function ;
MODBUSsendbuf[2]=0x02;
MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验
MODBUSsendlen=4; //计算CAN发送的数据长度
modbusDataToCan();
}
}
/*-----------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
函数名称: command_05()
函数功能: 作为MODBUS从设备 应答05 功能码
入口参数: 无
出口参数: 无
-------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------*/
void command_05(void)
{
UINT16 coiladdr;
UINT8 kk,mm,nn;
coiladdr=MODBUSrecvbuf[2]; //线圈地址
coiladdr=(coiladdr<<8)|((UINT8)(MODBUSrecvbuf[3]));
if( coiladdr<80 )
{
mm = coiladdr/8;
nn = coiladdr%8;
if(MODBUSrecvbuf[4]==0xFF)
MODBUS0area[mm]= MODBUS0area[mm] | ONEbit1[nn];
if(MODBUSrecvbuf[4]==0x00)
MODBUS0area[mm]= MODBUS0area[mm] & ONEbit0[nn];
for(kk=0;kk<8;kk++) //原文返回 MODBUSsendbuf[pp]=MODBUSrecvbuf[pp]; 要对自身CAN ID过滤
MODBUSsendbuf[kk] = 0xbf;
MODBUSsendlen=8;
modbusDataToCan();
}
else
{
MODBUSsendbuf[0]=MODBUSaddr;
MODBUSsendbuf[1]=0x85;
MODBUSsendbuf[2]=0x02;
MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验
MODBUSsendlen=4; //计算CAN发送的数据长度
modbusDataToCan();
}
}
/*------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
函数名称: command_06()
函数功能: 作为MODBUS从设备 应答06 功能码
入口参数:
出口参数: 无
--------------------------------------------------------------------------------------
------------------------------------------------------------------------------------*/
void command_06(void) //存在问题
{
UINT16 regaddr;
UINT8 pp;
regaddr=MODBUSrecvbuf[2]; //寄存器地址
regaddr=(regaddr<<8)|((UINT8)(MODBUSrecvbuf[3]));
if(regaddr<40)
{
MODBUS4area[regaddr]= ((UINT16)MODBUSrecvbuf[4]<<8) | (UINT16)MODBUSrecvbuf[5] ;
for(pp=0;pp<8;pp++) //原文返回 MODBUSsendbuf[pp]=MODBUSrecvbuf[pp];
MODBUSsendbuf[pp] = 0xaf;
MODBUSsendlen = 0x08;
modbusDataToCan();
}
else
{
MODBUSsendbuf[0]=MODBUSaddr;
MODBUSsendbuf[1]=0x86;
MODBUSsendbuf[2]=0x02;
MODBUSsendbuf[3]= LRC8(MODBUSsendbuf, 3); //LCR校验
MODBUSsendlen=4; //计算CAN发送的数据长度
modbusDataToCan();
}
}
/*------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------
函数名称: modbus_master()
函数功能: 作为MODBUS主设备 发送 各 功能码
入口参数:
出口参数: 无
--------------------------------------------------------------------------------------
------------------------------------------------------------------------------------*/
void modbus_master(UINT8 stationaddr,UINT8 function,UINT16 Maddr,UINT16 Mcount)
{
UINT16 crc_1;
MODBUSsendbuf[0]=stationaddr;
MODBUSsendbuf[1]=function;
MODBUSsendbuf[2]=Maddr>>8;
MODBUSsendbuf[3]=Maddr&0xff;
MODBUSsendbuf[4]=Mcount>>8;
MODBUSsendbuf[5]=Mcount&0xff;
crc_1=CRC16(MODBUSsendbuf,6);
MODBUSsendbuf[6]=(UINT8)(crc_1>>8); //+CRC_Hi
MODBUSsendbuf[7]=(UINT8)crc_1; //+CRC_Low
MODBUSsendlen=8; //计算CAN发送的数据长度
modbusDataToCan();
}
/*------------------------------------------------------------------------
--------------------------------------------------------------------------
函数名称: CRC16()
函数功能:
入口参数: 要进行CRC校验的数组的头指针 *pushMsg
要进行CRC校验的数组的字节数
出口参数: 校验生成的16位校验码
-------------------------------------------------------------------------
------------------------------------------------------------------------*/
UINT16 CRC16(UINT8 *pushMsg ,UINT8 usDataLen)
{
UINT8 uchCRCHi=0xFF; //高CRC字节初始化
UINT8 uchCRCLo=0xFF; //低CRC 字节初始化
UINT16 uIndex; //CRC循环中的索引
while (usDataLen--) //传输消息缓冲区
{
uIndex = uchCRCHi ^ *pushMsg++; // 计算CRC
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi<< 8 | uchCRCLo);
}
/*------------------------------------------------------------------------
--------------------------------------------------------------------------
函数名称: LRC8()
函数功能:
入口参数: 要进行LRC校验的数组的头指针 *aushMsg
要进行CRC校验的数组的字节数 LCRDataLen
出口参数: 校验生成的8位校验码
-------------------------------------------------------------------------
------------------------------------------------------------------------*/
UINT8 LRC8(UINT8 *auchMsg, UINT8 LCRDataLen)
{
INT8 uchLRC = 0 ; /*初始化LRC字符 */
while (LCRDataLen--) /*通过数据缓冲器*/
uchLRC += *auchMsg++;
return (UINT8)(-((INT8)uchLRC)) ; /*返回二进制补码*/
}
/*------------------------------------------------------------------------
--------------------------------------------------------------------------
函数名称: modbusDataToCan(void)
函数功能: 把MODBUS应答报文发送到CAN总线上
入口参数: 无
出口参数: status 0:发送成功 1:发送不成功
-------------------------------------------------------------------------
------------------------------------------------------------------------*/
UINT32 modbusDataToCan(void)
{
UINT32 status=0,i;
CTbuf.TxFrameInfo.Bits.PRIO_BIT = 0; //CAN通道号
CTbuf.TxFrameInfo.Bits.FF_BIT = 1; //帧格式
CTbuf.TxFrameInfo.Bits.RTR_BIT = 0; //帧类型
CTbuf.TxFrameInfo.Bits.DLC_BIT = MODBUSsendlen ;//数据长度
for(i=0;i<4;i++)
{
*((UINT8 *)&CTbuf.TxCANID.Word +i)=MODBUScanID[i];
}
memcpy((UINT8 *)&CTbuf.CANTDA,&MODBUSsendbuf[0],4);
memcpy((UINT8 *)&CTbuf.CANTDB,&MODBUSsendbuf[4],4);
status = CANSendData(00,02,&CTbuf);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -