2021-11-10 micropython 485slave crc_esp32

这里记录 micropython 485从机的驱动类,由于是自己写的所以可读性不强,大概率还是我自己用用

  1. slave.py文件如下,放在主文件同级目录下
"""
#from slave import slave485
#from esp32 import NVS
#slaveCtr= slave485(U1)
#关于主机请求从机的数据
#slaveCtr.recData(*data)#这里就循环调用就可以持续监听了,因为是轮询串口所以可靠性差一点,
# 其他程序不要太耗时就行,作为从机无非就是两件事,主机来要数据和主机送来数据,对于主机要数据的情况,我们可以传入任意个数的数据来给主机读取,例如:
# slaveCtr.recData(数据1,数据2,....,数据n)
# 比如: slaveCtr.recData(5,6,7,8) 这个都可以我写了自适应逻辑,程序自己会识别主机要几个数据然后给主机发过去,如果你给的数据不够则空余位置会补上-1这个值,给主机发回去


#关于主机送来数据给从机的情况,我们作为从机要保持串口轮询这个状态是对的就是不停的调用上面的slaveCtr.recData(*data)
#此状态下如果主机送来数据直接调用:
#rec_data=slaveCtr.recData_4Data  
#主机给的数据这里就会有,如果主机没给数据,这里的数据就是[-1,-1,-1,-1]
#这里也写了自适应逻辑,可以自动判断传进来任意个偶个数的数据返回列表,列表自适应。
#NVS这个是非易失存储用来存设备地址,没有地址自动定为1号
#因为结合西门子200PLC写的所以是根据modbusRTU来写的从机设备
"""
import time 
import struct,time
from machine import UART,I2C,Pin
from crc_esp32 import CRC_esp32
from esp32 import NVS

#u1=UART(1,9600,tx=27,rx=26)

class slave485(object):
  def __init__(self,u1):
    self.local=NVS('local')
    self.u1=u1
    self.crc=CRC_esp32()
    self.recData_4Data=[-1,-1,-1,-1]#主机没给数据则显示这个值
    try:
      self.addr=self.local.get_i32('addr')#读设备地址
    except:
      self.local.set_i32('addr',1)#没地址则指定为1号
      self.local.commit()#别忘了刷进去,否则不会存
      self.addr=1
    
  def recData(self,*data_a):#
    if self.u1.any()>0:
      recData=self.u1.read()
      recDataCrc=self.crc.into(recData[:-2])#接收的内容去掉尾部俩个校验码后重新计算校验码添加上
      
      if recDataCrc == recData:#新算的和接收的一致则没错
        if len(recData)==8:
          recDataList=struct.unpack('>6b',recData)#读命令长度固定,这里不用管
          if recDataList[0]==self.addr and recDataList[1]==3 :#主机请求站号确认
            if len(data_a)== recDataList[5]:#主机请求和从机提供正好相等,传值就行了,这里是个元组
              data_ture=data_a
            elif len(data_a) > recDataList[5]:#从机数据多,那就切片给人家,从前边切,后边不要了
              data_ture=data_a[:recDataList[5]]
            elif len(data_a) < recDataList[5]:#从机数据少,那就-1补足了再给送去
              data_ture=list(data_a)
              while len(data_ture) < recDataList[5]:
                data_ture.append(-1)
            
            
            sendDataList=[self.addr,3,recDataList[5]*2]#数据头,注意第三位的整数是看主机请求几个数据乘以2,确定字节数
            sendDataList.extend(data_ture)#拼数据接头和数据
            sendData=struct.pack('>3b%dh'%recDataList[5],*sendDataList)#根据个数来打包
            print(self.crc.into(sendData))
            time.sleep_ms(10)
            self.u1.write(self.crc.into(sendData))#填个校验,就发送吧
            print(sendData)
            
            
          if recDataList[0]==0 and recDataList[1]==6: #这个是本机设定站号
            self.local.set_i32('addr',recDataList[5])
            self.local.commit()
            self.addr=recDataList[5]
        if len(recData)== (7+recData[6]+2):#表示可能是写请求
          recDataList=struct.unpack('>7b%dhbb'%recData[5],recData)#动态捕捉数据
          if recDataList[0]==self.addr and recDataList[1]==16 :#确定是写数据命令
            self.recData_4Data= recDataList[7:-2]#####把发来的多个数据存到变量里########这里这里表示取这个self.recData_4Data就能拿到主机发来的数据 

crc_esp32.py


import struct
import binascii
class CRC_esp32():
  def __init__(self):
    pass    
  def calculateCRC(self,dataarray):#输入是列表,输出是带CRC校验的列表
    datalist = dataarray
    date03=dataarray[:]
    try:
      print (u'对应的序列:{0}'.format(datalist))
      # 处理第1个字节数据
      temp = self.calculateonebyte(datalist.pop(0), 0xFFFF)
      # 循环处理其它字节数据
      for data in datalist:
        temp = self.calculateonebyte(data,temp)
      date03.append(temp&0xff)
      date03.append(temp>>8)
      return date03
    except:
      pass
  def calculateonebyte(self,databyte, tempcrc):
  
    """
    计算1字节数据的CRC值
    :param databyte: 需计算的字节数据
    :param tempcrc: 当前的CRC值
    :return: 当道新的CRC值
    """
    # databyte必须为字节数据
    # assert 0x00 <= databyte <= 0xFF
    # 同上字节数据检查
    if not 0x00 <= databyte <= 0xFF:
      raise Exception((u'数据:0x{0:<02X}不是字节数据[0x00-0xFF]'.format(databyte)).encode('utf-8'))

    # 把字节数据根CRC当前值的低8位相异或
    low_byte = (databyte ^ tempcrc) & 0x00FF
    # 当前CRC的高8位值不变
    resultCRC = (tempcrc & 0xFF00) | low_byte
    # 循环计算8位数据
    for index in range(8):
      # 若最低为1:CRC当前值跟生成多项式异或;为0继续
      if resultCRC & 0x0001 == 1:
        #print("[%d]: 0x%4X ^^^^ 0x%4X" % (index,resultCRC>>1,resultCRC^GENERATOR_POLYNOMIAL))
        resultCRC >>= 1
        resultCRC ^= 0xA001 # 0xA001是0x8005循环右移16位的值
      else:
        # print ("[{0}]: 0x{1:X} >>>> 0x{2:X}".format(index,resultCRC,resultCRC>>1))
        resultCRC >>= 1
    return resultCRC
  def into(self,strr):#输入串口数据,b'\x01\x02'
    into0=self.calculateCRC(list(struct.unpack('%dB'%len(strr),strr)))#先变元祖再转列表
    into0=struct.pack('%dB'%len(into0),*into0)
    return into0
"""
# 用into  输入流输出流
# import crc_esp32
# x1=CRC_esp32()
# xx=x1.into(b'\x01\x05\x00\x02\xff\x00')
# print(xx)
# -------------or or  or --------------------
# 用calculateCRC 输入列表输出列表
# import crc_esp32
# x1=CRC_esp32()
# xx=x1.calculateCRC([1,5,0,2,255,0])
# print(xx)==>[1, 5, 0, 2, 255, 0, 45, 250]
"""
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值