没有这一位)、1位停止位(有校验位时)或者2个停止位(无校验位时)。
1.1Modbus多机通信例程
给从机下发不同的指令,从机去执行不同的操作,这个就是判断一下功能码即可,和我们前边学的实用串口例程是类似的。多机通信,无非就是添加了一个设备地址判断而已,难度也不大。我们找了一个Modbus调试精灵,通过设置设备地址,读写寄存器的地址以及数值数量等参数,可以直接替代串口调试助手,比较方便的下发多个字节的数据,如图18-7所示。我们先来就图中的设置和数据来对Modbus做进一步的分析,图中的数据来自于调试精灵与我们接下来要讲的例程之间的交互。
图18-7Modbus调试精灵
如图,我们的USB转RS485模块虚拟出的是COM5,波特率9600,无校验位,数据位是8位,1位停止位,设备地址假设为1。
写寄存器的时候,如果我们要把01写到一个地址是0000的寄存器地址里,点一下“写入”,就会出现发送指令:010600000001480A。我们来分析一下这帧数据,其中01是设备地址,06是功能码,代表写寄存器这个功能,后边跟0000表示的是要写入的寄存器的地址,0001就是要写入的数据,480A就是CRC校验码,这是软件自动算出来的。而根据Modbus协议,当写寄存器的时候,从机成功完成该指令的操作后,会把主机发送的指令直接返回,我们的调试精灵会接收到这样一帧数据:010600000001480A。
假如我们现在要从寄存器地址0002开始读取寄存器,并且读取的数量是2个。点一下“读出”,就会出现发送指令:01030002000265CB。其中01是设备地址,03是功能码,代表读寄存器这个功能,0002就是读寄存器的起始地址,后一个0002就是要读取2个寄存器的数值,65CB就是CRC校验。而接收到的数据是:01030400000000FA33。其中01是设备地址,03是功能码,04代表的是后边读到的数据字节数是4个,00000000分别是地址为0002和0003的寄存器内部的数据,而FA33就是CRC校验了。
似乎越来越明朗了,所谓的Modbus通信协议,无非就是主机下发了不同的指令,从机根据指令的判断来执行不同的操作而已。由于我们的开发板没有Modbus功能码那么多相应的功能,我们在程序中定义了一个数组regGroup[5],相当于5个寄存器,此外又定义了第6个寄存器,控制蜂鸣器,通过下发不同的指令我们改变寄存器组的数据或者改变蜂鸣器的开关状态。在Modbus协议里寄存器的地址和数值都是16位的,即2个字节,我们默认高字节是0x00,低字节就是数组regGroup对应的值。其中地址0x0000到0x0004对应的就是regGroup数组中的元素,我们写入的同时把数字又显示到1602液晶上,而0x0005这个地址,写入0x00,蜂鸣器就不响,写入任何其它数值,蜂鸣器就报警。我们单片机的主要工作也就是解析串口接收的数据执行不同操作。
/*Lcd1602.c文件程序源代码*/
(此处省略,可参考之前章节的代码)
/RS485.c文件程序源代码*/
(此处省略,可参考之前章节的代码)
/CRC16.c文件程序源代码/
/*CRC16计算函数,ptr-数据指针,len-数据长度,返回值-计算出的CRC16数值*/
unsignedintGetCRC16(unsignedchar*ptr,unsignedcharlen)
{
unsignedintindex;
unsignedcharcrch=0xFF;//高CRC字节
unsignedcharcrcl=0xFF;//低CRC字节
unsignedcharcodeTabH[]={//CRC高位字节值表
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0
|