使用c语言完成modbus协议,从云端服务器读取温湿度信息

任务目标

在消化学习 server.c和client.c 套接字代码、python-modbus-over-tcp.py 代码基础上,试着用C编程完成modbus协议,从云端服务器读取温湿度数据。

实验材料

  • PyCharm2022
  • mysql
  • wireshark
  • 小熊猫C++软件

Modbus协议简述

(1)协议概述:

Modbus协议是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表的。Modbus协议是应用层协议,已经成为工业领域通信协议的业界标准,是工业电子设备之间常用的连接方式。

Modbus是一个master/slave架构的协议,有一个节点是master节点,其他使用Modbus协 议参与通信的节点是slave节点,每一个slave设备都有一个唯一的地址。只有被指定为master节点的节点可以启动一个命令。所有的Modbus数据帧包含了校验码,保证传输的正确性。基本的ModBus命令能指令一个slave设备改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。

(2)modbus主从协议原理

Modbus串行链路协议是一个主-从协议。在同一时间,只能将一个主站连接到总线,将一个或多个从站(最大数量为247)连接到相同的串行总线。Modbus 通讯总是由主站发起,当从站没有收到来自主站的请求时,将不会发送数据。主站同时只能启动一个Modbus事务处理,从站之间不能相互通信。

(3)modbus串行传输模式

RTU模式:每个8Bit字节包含两个4Bit的十六进制字符, 其优点是在同样的波特率下,可比ASCII方式传送更多的数据,但是每个信息必须以连续的数据流传输。
ASCII模式:信息中的每个8 Bit字节需2个ASCII字符,其优点是准许字符的传输间隔达到1s 而不产生错误。

使用python示例代码,完成Modbus协议从云端获取信息

这是使用Python示例代码来获取云端信息的方法,请求数据的方式为UDP,注意要修改成自己的数据库名称和密码。

import socket
import sys
import struct
import time
import pymysql
import datetime

#实现采集温度传感器和静力水准仪

def crc16(string):
    #data = bytes.fromhex(string)
    data=string
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return hex(((crc & 0xff) << 8) + (crc >> 8))

#连接数据库
def MySQLConnect():
    connection = pymysql.connect(
        host='localhost',  # IP,MySQL数据库服务器IP地址
        port=3306,  # 端口,默认3306,可以不输入
        user='root',  # 数据库用户名
        password='123456',  # 数据库登录密码
        database='sensor',  # 要连接的数据库
        charset='utf8'  # 字符集,注意不是'utf-8'
    )
    return connection

#插入温湿度采集到数据库
def AddData1(wd,sd,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO temp_hum_sensor(temp, hum, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [wd, sd, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

#插入静力水准仪采集到数据库
def AddData2(id,water_level,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO static_level(id, water_level, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [id, water_level, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

#采集温度传感器的数据
def getDataTemp(cmd):
    #flag标志采集的次数
    flag=0
    last = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(last)
    last1 = time.time()
    cmd = bytes.fromhex(cmd)
    #print(cmd)
    crc = crc16(cmd)
    crc = bytes.fromhex(crc[2:])
    #得到发送的指令(modbus协议定义内容+校验)
    cmd = cmd + crc
    udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
    try:
        data, addr = udp.recvfrom(8192)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    crc = data[-2:]
    crc1 = crc16(data[:-2])
    crc1 = crc1[2:]
    if (len(crc1) == 3):
        crc1 = '0' + crc1
    crc1 = bytes.fromhex(crc1)

    # print(crc1)
    if crc != crc1:
        print("CRC16校验失败!")
        sys.exit(2)
    # 解析数据
    wd, sd = struct.unpack('>ii', data[4:12])
    wd = wd / 100.
    print("温度:", wd, "湿度:", sd)
    AddData1(wd, sd, last)
    flag=flag+1
    while True:
        now= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        #print(s)
        now1=time.time()
        #每隔5s获取一次数据
  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值