void Modbud_fun6() //6号功能码处理
{
u16 Regadd;
u16 val;
u16 i,crc,j;
i=0;
Regadd=modbus.rcbuf[2]*256+modbus.rcbuf[3]; //获取要修改的寄存器地址
val=modbus.rcbuf[4]*256+modbus.rcbuf[5]; //获取修改后的值
Reg[Regadd]=val; //修改本设备相应的寄存器
//以下为回应主机
modbus.Sendbuf[i++]=modbus.myadd;//添加本设备地址到发送缓冲区
modbus.Sendbuf[i++]=0x06; //添加功能码到发送缓冲区
modbus.Sendbuf[i++]=Regadd/256; //添加寄存器地址的高字节到发送缓冲区
modbus.Sendbuf[i++]=Regadd%256; //添加寄存器地址的低字节到发送缓冲区
modbus.Sendbuf[i++]=val/256; //添加修改后的值的高字节到发送缓冲区
modbus.Sendbuf[i++]=val%256; //添加修改后的值的低字节到发送缓冲区
crc=crc16(modbus.Sendbuf,i); //计算CRC校验码
modbus.Sendbuf[i++]=crc/256; //添加CRC校验码的高字节到发送缓冲区
modbus.Sendbuf[i++]=crc%256; //添加CRC校验码的低字节到发送缓冲区
RS485_RT_1; //设置RS485为发送模式
for(j=0;j<i;j++) //发送缓冲区中的所有数据
{
RS485_byte(modbus.Sendbuf[j]);
}
RS485_RT_0; //设置RS485为接收模式
}
Modbus协议中,CRC16校验用于检测通信数据的完整性。它通过对传输的数据进行循环冗余校验(CRC),生成一个16位的校验码,附加到数据的末尾,接收方根据相同算法计算CRC码,判断数据是否有误。
CRC校验方式说明:
1. CRC16多项式:采用的是0xA001,即Modbus协议中常用的CRC16-IBM算法,初始值为0xFFFF。
2. 查表法优化:代码使用了查表法来提高效率,通过auchCRCHi[]和auchCRCLo[]两个数组存储CRC的高位和低位预计算值。这样避免了逐位移位运算,减少了处理时间。
3. 计算过程:
初始化高位和低位CRC字节为0xFF。
遍历数据缓冲区的每一个字节,计算出当前CRC字节与当前数据字节异或的索引uIndex。
根据uIndex在auchCRCHi[]和auchCRCLo[]查找对应的高位和低位CRC值,更新uchCRCHi和uchCRCLo。
4. 结果组合:最终返回时,将高位字节uchCRCHi左移8位,与低位字节uchCRCLo合并,形成最终的16位CRC值。
这个方法有效地验证Modbus通信中的数据完整性,一旦接收方计算出的CRC值与附加的CRC码不一致,就说明数据传输过程中出现了错误。
在 Modbus 通信协议中,主机与设备之间通常使用 CRC16 校验 来确保通信数据的完整性。因此,主机与上面代码通信时,默认使用的校验方式也是 CRC16。
具体来说,Modbus 协议有两种主要的传输模式,每种模式的校验方式不同:
1. Modbus RTU 模式:
使用 CRC 校验:Modbus RTU(Remote Terminal Unit)是二进制通信格式,使用 CRC16 校验。如上代码所示,发送数据时,会计算数据的 CRC16 校验值,并将其附加在数据帧的末尾。接收方再通过相同的算法计算出 CRC 值,验证数据是否正确。
2. Modbus ASCII 模式:
使用 LRC 校验:在 Modbus ASCII 模式下,校验方式为 LRC(纵向冗余校验,Longitudinal Redundancy Check)。这是通过对数据帧中的每个字节进行异或运算,生成一个校验字节。
因此,如果通信采用 Modbus RTU 模式,则使用的是 CRC16 校验,这也是上述代码所实现的校验方式。如果是 Modbus ASCII 模式,则会使用 LRC 校验。
总结:
主机与上述代码进行通信时,通常使用的是 Modbus RTU 模式的 CRC16 校验。
触摸屏通讯设置的485通讯参数波特率,奇/偶/N效验,这些都是基本物理传输协议。 与程序中串口设置对应
/*USART初始化*/
USART_InitTypeDef USART_InitStructure; //定义结构体变量
USART_InitStructure.USART_BaudRate = 115200; //波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制,不需要
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //模式,发送模式和接收模式均选择
USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶校验,不需要
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位,选择1位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长,选择8位
USART_Init(USART1, &USART_InitStructure); //将结构体变量交给USART_Init,配置USART1
完成物理协议才是软件协议触摸屏选择的是 Modbus RTU 模式也就决定了数据格式,效验方式为CRC,具体数据协议为标准协议
按标准写就行了,具体通讯报文分析我提供的文档内都有
威纶通自由协议报文 地址 通讯 4x 15 01 03 00 0F 00 01 B4 09 数字元件 站号1、功能码03 读多个寄存器、 地址15 、 数量1、 效验码 5x 10 01 03 00 0A 00 01 A4 08 数字元件 站号1、功能码03 读多个寄存器、 地址10 、 数量1、 效验码
|