2021-09-23

基于RS485的MODBUS通讯(三)

程序若采用RTU协议通讯,则需使用CRC校验方式,在程序中加入CRC算法(固定格式)。
modbus.c文件首先要实现MODBUS初始化,以及数据的接收工作,为了程序使用方便,在h文件中定义相关结构体,把MODBUS所需的东西集中在结构体中。

typedef struct
{
   unsigned char myaddr;   //设备地址
   unsigned char rcbuf[100];   //接收数据缓冲区
   unsigned short timeout;   //MODBUS数据断续时间
   unsigned char recount;   //MODBUS端口已经收到的数据个数
   unsigned char timerun;   //MODBUS定时器计时标志位
   unsigned char reflag;   //收到帧数据标志位
}MODBUS;

在modbus.c文件中首先定义结构体变量,其次初始化MODBUS,初始化的第一件事就是确定设备地址,之后初始化通讯底层(USART)。初始化完成之后开始对接收/发送数据做出编写。
如接收一个数据包,若计算机发送数据至从机,需在结构体中定义RS485的接收缓冲区 ,在没有收到停止信号之前,所有接受的数据都放在缓冲区中。
那如何知道一帧数据发送完成?
MODBUS协议规定,当接收到第一个字节时开始计时,若达到3.5个字节间隔未收到数据,则认为数据发送结束。所以需定义一个变量timeout来存储“间隔时长”,此变量会在定时器中断函数中累加,若此变量达到3.5个字符间隔,则认为一帧数据到齐。
3.5个字符间隔时长是多少?
当波特率为9600,一位数据发送时间为1000000us / 9600bit/s = 104us。1个字节为10位(8位数据为+1位起始位+1位停止位)。所以主机发送一个字节的时间为10104 = 1040us,所以说MODBUS确定一个数据帧完成的时间为3.51040 = 3.64ms。当接收字节间隔为3.64ms时,则认为主机数据发送完成。
但timeout累加是有条件的限制的,只有没有收到数据后才可以累加。一旦收到数据则将timeout清空。
同时定义结构体变量recount用来统计端口已经接收到的数据个数,在USART接收中断中,每一次进入次函数就意味着接收到一次数据,recount累加一次,并将数据存入rcbuf中。
一旦接收到数据,则需通知定时器开始计时了,所以需在结构体中增加定时器启动标志位timerun。
在MODBUS初始化函数中,首先将timerun置0,因为还未开始接收数据。主机开始发送数据当从机接收到第一个字节时(recount==1),通知定时器开始工作(timerun = 1)。
当timeout累加到设定的间隔时间,则关闭定时器(timerun = 0),并将帧数据接收标志位(reflag)置1。
之后对刚才接收到的数据进行处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值