4.4、crc校验 包含两个字节,发送端发送时,一帧的所有数据统一计算出一个crc校验
码,然后加在一帧的最后两位中,然后等到发送到接收端时接收端重新计算一次除最后两位
的一帧所有数据,然后根据两个数据的对比,来判断接收到的数据是否正确。
5、程序,以下位机为程序对象,主要使用c语言编写,首先,先从变量入手,既然
modbus接受以帧为单位,所以就要设置两个缓冲区,用来接收数据,我们这里使用数组来
存储接收来的数据Modbus_send_buf[Modbus_max_send_buf];//数据发送缓冲 和
Modbus_recevie_buf[Modbus_max_recevie_buf];//数据接收缓冲 ,其中
Modbus_max_send_buf,和Modbus_max_recevie_buf ,为宏定义,这样可以方便的修
改一帧最大的存储数据。有了发送接收缓冲,就可以写中断函数了,进入中断后,首先做一
些必要的工作,清ES ,判断IR,清IR,做完后,就可以开始接收数据了,但有个问题?如果
设备处于空闲状态,那么接收数据后按命令执行,但如果当设备正在执行指令的时候,则不
应该再继续的接收指令,那样的话,会让程序进入混乱状态。所以要在基础工作做完后,增
加一个判断,来确定设备的忙闲。if((Modbus_cmd_flag == 0) && (Modbus_exe_flag
== 0)),判断完以后就可以继续下面的工作了。如果通讯中包含奇偶校验的话,那么则判断
奇偶校验。下面就是接收数据。Modbus_recevie_buf[Modbus_recevie_count] = SBUF;
,将接收来的数据存入数组并记录存入的数据个数Modbus_recevie_count,由于modbus
是通过时间来判断一帧的结束的,所以在程序中,必须要有一个定时器函数,这个定时器用
来判断程序是正在接受,还是已经接受完成了。所以中断的最后所做的是计数器自加
Modbus_recevie_count++;,定时器清0 Modbus_timeout_cnt = 0; ,将设备状态转入
接收状态Modbus_recevie_flag = 1;。此时,串口中断的工作就完成了。
下面开始分析定时器,定时器的目的其实就1个,判断一帧是否接收完毕,如果完
毕,则进入下一步。在定时器中断函数中,首先要对定时器值进行初始化,这个就不多说
了,然后是判断程序是否处于接受状态if(Modbus_recevie_flag == 1),这个状态只有在串
口中断函数中才会被置位,其他的情况不会被置位。若程序不是接收状态,则直接跳出定时
器中断,若程序处于接收状态,则定时计数自加Modbus_timeout_cnt++;,自加后进入判
断if(Modbus_timeout_cnt >= Modbus_max_timeout_cnt),判断的值即为modbus接收
一帧传输完成所需要的时间间隔。至于是多少时间,可以通过修改
Modbus_max_timeout_cnt来确定。可以将定时器终端设置为1ms1次,在9600的情况下
将超时时间设为4,#define Modbus_max_timeout_cnt 4,这样如果串口中断不在接收
数据时,定时计数将不会清0,当到达设定的超时时间后即判断接收结束,转向命令解析状
态。
接收来的数据可以经过一个函数来执行,同时也可以经过两个函数,解析与执行两步
来分别执行。我喜欢后者,因为这样可以把解析的过程和执行的过程分开来写。程序显得更
加清晰与明朗。
在主函数中就执行1个函数,
while(1)