实验8 485组网实验_主机

1. 实验目的

本实验为非mobus方式,实现485组网。modbus组网参考实验三和实验四。

带485接口的串口屏,也可以进行485组网。要进行485组网,需要定义一套比较完整的协议。主机是谁,从机是哪些,主机和从机的地址需要定义好,不要冲突。

比较常见的,是485总线上一主机多从机的模式,主机可以主动发起查询和设置,从机只能被动响应主机的命令。

本实验的协议仅仅简单的体现485怎么实现组网,仅供参考。

本实验模拟实验八中的主机。

2. 页面设计

(1)浮点数控件,显示温度值

(2)整数控件,显示湿度

(3)按钮,翻页

(4)定时器,定时器间隔100ms,定时时间到会执行定时器脚本。在定时器里面发送查询和设置命令

(5)变量控件,存放命令发送状态

(6)变量控件,存放系统运行时间

(7)变量控件,存放系统故障状态

(8)协议解析器控件,处理接收到的串口命令

选中控件,可以在右侧属性栏查看控件的各个属性和事件代码。详细属性说明可参考 第四章 控件的介绍和用法。

Page1

1、浮点数控件,显示温度告警值

2、整数控件,显示湿度告警值

3、按钮,点击按钮时会发送设置命令

4、文本控件,显示设置成功或失败

5、按钮,返回page0

选中控件,可以在右侧属性栏查看控件的各个属性和事件代码。详细属性说明可参考 第四章 控件的介绍和用法。

3. 串口屏协议处理

本实验通信协议定义如下:

报文帧格式

帧头

原地址

目的地址

命令码

参数

校验

0xA5

1Byte

1Byte

1Byte

N

2Byte

主机:STM32F103实验板 主机地址0x01

从机地址

命令码

参数长度

参数

校验

0xF1 温湿度模块

0x01主机发送 查询温度值

0字节

0xF1从机响应

6字节

[0~3]温度值 [4~5]湿度值

0x02主机发送 查询告警温度值

0字节

0xF2从机响应

6字节

[0~3]温度告警值 [4~5]湿度告警值

0x03主机发送 设置告警温度值

6字节

[0~3]温度告警值 [4~5]湿度告警值

0xF3从机响应

1字节

[0]是否成功

0成功,1失败

0xF3 从机显示屏

0x01主机发送 系统运行时间

2字节

[0~1]运行时间

单位,分钟

0xF1从机响应

1字节

0x02 系统运行状态

1字节

[0]运行状态

0系统正常 1系统故障

0xF2从机响应

0字节

本实验是串口屏模拟STM32F103实验板,地址为0x01.

定时器用于间隔发送查询和设置命令,脚本代码如下


byte buf[10];
int crc_val;

if(state.val == 0) //查询温度值
{
    buf[0] = 0xA5;
    buf[1] = 0x01;
    buf[2] = 0xF1;
    buf[3] = 0x01;    
    crc_val = crc16(buf,0,4);
    buf[4] = (byte)crc_val;
    buf[5] = (byte)(crc_val>>8);
    uartSendBytes(buf, 0, 6);//发送数组的数据        
}
else if(state.val == 1) //查询温度告警
{
    buf[0] = 0xA5;
    buf[1] = 0x01;
    buf[2] = 0xF1;
    buf[3] = 0x02;    
    crc_val = crc16(buf,0,4);
    buf[4] = (byte)crc_val;
    buf[5] = (byte)(crc_val>>8);
    uartSendBytes(buf, 0, 6);//发送数组的数据        
}

else if(state.val == 2) //发送系统运行时间
{
    run_time.val++;

    buf[0] = 0xA5;
    buf[1] = 0x01;
    buf[2] = 0xF3;
    buf[3] = 0x01;    
    buf[4] = (byte)run_time.val;
    buf[5] = (byte)(run_time.val>>8);    
    crc_val = crc16(buf,0,6);
    buf[6] = (byte)crc_val;
    buf[7] = (byte)(crc_val>>8);
    uartSendBytes(buf, 0, 8);//发送数组的数据        
}

else if(state.val == 3) //发送系统状态
{
    buf[0] = 0xA5;
    buf[1] = 0x01;
    buf[2] = 0xF3;
    buf[3] = 0x02;    
    buf[4] = (byte)sys_state.val;
    crc_val = crc16(buf,0,5);
    buf[5] = (byte)crc_val;
    buf[6] = (byte)(crc_val>>8);
    uartSendBytes(buf, 0, 7);//发送数组的数据        
}

state.val++;
if(state.val > 3)
    state.val = 0;

delay(20); //延时20ms,等待从机响应

协议解析器处理串口接收的命令,脚本代码如下

int src_addr;
int dst_addr;
int len;
int crc_data;
int crc_val;

if(proto.rxBuf[0] == 0xA5)
{
    src_addr = proto.rxBuf[1];
    dst_addr = proto.rxBuf[2];

    if(dst_addr == 0x01)   //检测该命令,是否是本机的命令
    {
        len = proto.rxLen;    
        crc_data = (proto.rxBuf[len-1]<<8) | proto.rxBuf[len-2];
        crc_val  = crc16(proto.rxBuf,0,len-2);
        if(crc_data == crc_val) //CRC判断
        {    
            if(src_addr == 0xF1) //温度模块的数据
            {
                if(proto.rxBuf[3] == 0xF1)
                {
                    //获取温度值
                    temp.valf = bytesToFloat(proto.rxBuf,4,0);     
                    
                    //获取湿度值
                    hum.val = (proto.rxBuf[9]<<8) | proto.rxBuf[8];                        
                }
                else if(proto.rxBuf[3] == 0xF2)
                {
                    //获取温度告警值
                    page1.temp_alarm.valf = bytesToFloat(proto.rxBuf,4,0);     
                                    
                    //获取湿度告警值
                    page1.hum_alarm.val = (proto.rxBuf[9]<<8) | proto.rxBuf[8];            
                }
                else if(proto.rxBuf[3] == 0xF3)
                {
                    if(proto.rxBuf[4] == 0)
                        page1.text5.txt = "设置成功";
                    else
                        page1.text5.txt = "设置失败";
                }
            }
            else if(src_addr == 0xF3) //从机显示屏的数据
            {
                //不用处理
            }
        
        }
    }
}   

Page1的设置按钮用于发送设置命令,脚本代码如下

byte buf[16];
int crc_val;


buf[0] = 0xA5;
buf[1] = 0x01;
buf[2] = 0xF1;
buf[3] = 0x03;    

floatToBytes(temp_alarm.valf,buf,4,0);  //温度告警值
buf[8] = (byte)(hum_alarm.val>>0);      //湿度告警值L
buf[9] = (byte)(hum_alarm.val>>8);        //湿度告警值H
crc_val = crc16(buf,0,10);
buf[10] = (byte)crc_val;
buf[11] = (byte)(crc_val>>8);
uartSendBytes(buf, 0, 12);//发送数组的数据        

page0.timer2.en = 1;

4. 下载验证

编译成功后,点击下载按钮,选择正确的端口号和波特率,下载到串口屏。

调试时,用电脑的串口助手监控串口屏的数据。

可以看到串口屏不停的发出命令

(1)查询温度湿度值

(2)查询温度湿度告警值

(3)发送系统运行时间

(4)发送系统状态

发送测试命令

//模拟从机0xF1的响应

A5 F1 01 F1 33 33 BB 41 3A 00 29 47 //温度23.4,湿度 58

A5 F1 01 F2 00 00 20 42 46 00 22 10 //温度告警40,湿度告警70

A5 F1 01 F3 00 AB 4C //设置成功