全网最适合入门的面向目标编程教程:11 类和目标的Python完成-子类调用父类办法-模仿串口传感器和主机
全网最适合入门的面向方针编程教程:11 类和方针的 Python 完结-子类调用父类办法-模仿串口传感器和主机
摘要:
本节课,咱们首要解说了在 Python 类的承继中子类怎么进行初始化、调用父类的特点和办法,一起解说了模仿串口传感器和主机类的详细完结,并运用 xcom 串口帮手与两个类进行串口通讯运用。
原文链接:
FreakStudio 的博客
往期引荐:
学嵌入式的你,还不会面向方针??!
全网最适合入门的面向方针编程教程:00 面向方针规划办法导论
全网最适合入门的面向方针编程教程:01 面向方针编程的根本概念
全网最适合入门的面向方针编程教程:02 类和方针的 Python 完结-运用 Python 创立类
全网最适合入门的面向方针编程教程:03 类和方针的 Python 完结-为自界说类增加特点
全网最适合入门的面向方针编程教程:04 类和方针的Python完结-为自界说类增加办法
全网最适合入门的面向方针编程教程:05 类和方针的Python完结-PyCharm代码标签
全网最适合入门的面向方针编程教程:06 类和方针的Python完结-自界说类的数据封装
全网最适合入门的面向方针编程教程:07 类和方针的Python完结-类型注解
全网最适合入门的面向方针编程教程:08 类和方针的Python完结-@property装修器
全网最适合入门的面向方针编程教程:09 类和方针的Python完结-类之间的联系
全网最适合入门的面向方针编程教程:10 类和方针的Python完结-类的承继和里氏替换准则
更多精彩内容可看:
给你的 Python 加加快:一文速通 Python 并行计算
一文搞懂 CM3 单片机调试原理
肝了半个月,嵌入式技能栈大汇总出炉
电子计算机类竞赛的“武林秘籍”
一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython东西库
文档和代码获取:
可拜访如下链接进行对文档下载:
https://github.com/leezisheng/Doc
本文档首要介绍怎么运用 Python 进行面向方针编程,需求读者对 Python 语法和单片机开发具有根本了解。比较其他解说 Python 面向方针编程的博客或书本而言,本文档愈加详细、侧重于嵌入式上位机运用,以上位机和下位机的常见串口数据收发、数据处理、动态图制作等为运用实例,一起运用 Sourcetrail 代码软件对代码进行可视化阅览便于读者了解。
相关示例代码获取链接如下:https://github.com/leezisheng/Python-OOP-Demo
正文
模仿串口传感器和主机类的详细完结:
接下来看一下咱们新建的两个类办法的详细完结,能够清晰的是,SensorClass 和 MasterClass 都需求调用 SerialClass 类中有关串口收发的办法,也便是子类调用父类的办法,子类调用父类的办法有三种办法:
- 父类名.办法名(self):此刻需求加上父类的类名前缀,且需求带上 self 参数变量。该办法单承继或多承继均适用。
- super(子类名,self).父类办法名()/super().父类办法名:运用 super()函数,但假如触及多承继,该函数只能调用第一个直接父类的结构办法。
SensorClass 类的完结
(1)首要,咱们将 SensorClass 中作业状况的对应字符表明和指令对应字符表明设置为类特点,什么意思?咱们来看如下代码:
class SensorClass(SerialClass):
_# 类变量:_
_# RESPOND_MODE-呼应形式-0_
_# LOOP_MODE -循环形式-1_
RESPOND_MODE,LOOP_MODE = (0,1)
_# 类变量:_
_# START_CMD - 敞开指令 -0_
_# STOP_CMD - 封闭指令 -1_
_# SENDID_CMD - 发送ID指令 -2_
_# SENDVALUE_CMD - 发送数据指令 -3_
START_CMD,STOP_CMD,SENDID_CMD,SENDVALUE_CMD = (0,1,2,3)
类特点归类一切,与前面讲的实例特点不同,类特点就适当与全局变量,是实例方针共有的特点,类特点影响类的一切方针;而实例方针的特点为实例方针自己私有,实例特点只影响当时方针。类特点常用于存储常量、界说默认值或结构一个一切方针都能拜访的缓存。
这儿,咱们界说了两品种特点:
RESPOND_MODE,LOOP_MODE = (0,1)
用于表明 SensorClass 不同作业形式。
START_CMD,STOP_CMD,SENDID_CMD,SENDVALUE_CMD = (0,1,2,3)
用于表明不同指令。
(2)在初始化中,咱们调用父类初始化办法进行,一起能够在初始化 SensorClass 类时指定 id、state、port 三个参数。
def __init__(self,id:int = 0,state:int = RESPOND_MODE,port:str = "COM11"):
# 调用父类的初始化办法,super() 函数将父类和子类衔接
super().__init__(port)
self.sensorvalue = 0
self.sensorid = id
self.sensorstate = state
这儿,实践上 SensorClass 类初始化的参数应该包含其他有关串口装备相关的参数(波特率、校验位、数据位、中止位),因为串口通讯两边这些参数装备相同,这儿为了便利解说故而简化。
(3)模仿传感器上电初始化,在实践传感器上电进程中会完结校准、自检等操作,这儿咱们简略输出传感器状况和 ID 号:
_# 传感器上电初始化_
def InitSensor(self):
_# 传感器上电初始化作业_
_# 一起输出ID号以及状况_
print("Sensor %d Init complete : %d"%(self.sensorid,self.sensorstate))
(4)在传感器使能和封闭办法中,咱们敞开或封闭串口并打印相关信息:
_# 敞开传感器_
def StartSensor(self):
super().OpenSerial()
print("Sensor %d start serial %s "%(self.sensorid,self.dev.port))
_# 中止传感器_
def StopSensor(self):
super().CloseSerial()
print("Sensor %d close serial %s " % (self.sensorid, self.dev.port))
(5)在传感器发送 ID 号的办法中,咱们调用了父类的 WriteSerial 办法:
_# 发送传感器ID号_
def SendSensorID(self):
super().WriteSerial(str(self.sensorid))
print("Sensor %d send id "%self.sensorid)
(6)在传感器发送数据办法中,咱们运用如下句子生成一个随机数:
_# 生成[1, 10]内的随机整数_
data = random.randint(1, 10)
留意,此办法需求运用 import random 句子导入 random 库。
一起调用父类的 WriteSerial 办法完结传感器数据的发送:
_# 发送传感器数据_
def SendSensorValue(self):
_# 生成[1, 10]内的随机整数_
data = random.randint(1, 10)
super().WriteSerial(str(data))
print("Sensor %d send data %d" % (self.sensorid,data))
(7)在传感器接纳指令办法中,咱们调用了父类的 ReadSerial 接纳指令:
_# 接纳主机指令_
def RecvMasterCMD(self):
cmd = super().ReadSerial()
print("Sensor %d recv cmd %d " % (self.sensorid,cmd))
return cmd
MasterClass 类的完结
(1)首要界说关于作业形式和指令的类特点:
class MasterClass(SerialClass):
_# 类变量:_
_# BUSY_STATE -繁忙状况-0_
_# IDLE_STATE -闲暇状况-1_
BUSY_STATE, IDLE_STATE = (0, 1)
_# 类变量:_
_# START_CMD - 敞开指令 -0_
_# STOP_CMD - 封闭指令 -1_
_# SENDID_CMD - 发送ID指令 -2_
_# SENDVALUE_CMD - 发送数据指令 -3_
START_CMD, STOP_CMD, SENDID_CMD, SENDVALUE_CMD = (0, 1, 2, 3)
(2)在初始化函数中调用父类的初始化办法,并界说 valuequeue 和__masterstatue 特点:
_# 类的初始化_
def __init__(self,state:int = IDLE_STATE,port:str = "COM17"):
_# 调用父类的初始化办法,super() 函数将父类和子类衔接_
super().__init__(port)
self.valuequeue = queue.Queue(10)
self.__masterstatue = state
(3)在 StartMaster 办法中咱们翻开串口并运用 logging.info()办法输出调试信息:
_# 敞开主机_
def StartMaster(self):
super().OpenSerial()
logging.info("START MASTER :"+self.dev.port)
这儿,需求导入 logging 库并设置日志输出等级:
import logging
_# 设置日志输出等级_
logging.basicConfig(level=logging.DEBUG)
(4)封闭主机办法中调用父类的 CloseSerial 办法:
_# 中止主机_
def StopMaster(self):
super().CloseSerial()
logging.info("CLOSE MASTER :" + self.dev.port)
(5)如下调用父类的 ReadSerial 办法接纳 ID 号和数据:
_# 接纳传感器ID号_
def RecvSensorID(self):
sensorid = super().ReadSerial()
logging.info("MASTER RECIEVE ID : " + str(sensorid))
return sensorid
_# 接纳传感器数据_
def RecvSensorValue(self):
data = super().ReadSerial()
logging.info("MASTER RECIEVE DATA : " + str(data))
self.valuequeue.put(data)
return data
(6)调用父类的 WriteSerial 办法发送指令:
_# 主机发送指令_
def SendSensorCMD(self,cmd):
super().WriteSerial(str(cmd))
logging.info("MASTER SEND CMD : " + str(cmd))
(7)如下 RetMasterStatue 办法获取主机状况:
_# 主机回来作业状况-_
def RetMasterStatue(self):
return self.__masterstatue
完好代码
以下为两个类的完好代码:
class SensorClass(SerialClass):
_# 类变量:_
_# RESPOND_MODE -呼应形式-0_
_# LOOP_MODE -循环形式-1_
RESPOND_MODE,LOOP_MODE = (0,1)
_# 类变量:_
_# START_CMD - 敞开指令 -0_
_# STOP_CMD - 封闭指令 -1_
_# SENDID_CMD - 发送ID指令 -2_
_# SENDVALUE_CMD - 发送数据指令 -3_
START_CMD,STOP_CMD,SENDID_CMD,SENDVALUE_CMD = (0,1,2,3)
_# 类的初始化_
def __init__(self,port:str = "COM11",id:int = 0,state:int = RESPOND_MODE):
_# 调用父类的初始化办法,super() 函数将父类和子类衔接_
super().__init__(port)
self.sensorvalue = 0
self.sensorid = id
self.sensorstate = state
_# 传感器上电初始化_
def InitSensor(self):
_# 传感器上电初始化作业_
_# 一起输出ID号以及状况_
print("Sensor %d Init complete : %d"%(self.sensorid,self.sensorstate))
_# 敞开传感器_
def StartSensor(self):
super().OpenSerial()
print("Sensor %d start serial %s "%(self.sensorid,self.dev.port))
_# 中止传感器_
def StopSensor(self):
super().CloseSerial()
print("Sensor %d close serial %s " % (self.sensorid, self.dev.port))
_# 发送传感器ID号_
def SendSensorID(self):
super().WriteSerial(str(self.sensorid))
print("Sensor %d send id "%self.sensorid)
_# 发送传感器数据_
def SendSensorValue(self):
_# 生成[1, 10]内的随机整数_
data = random.randint(1, 10)
super().WriteSerial(str(data))
print("Sensor %d send data %d" % (self.sensorid,data))
_# 接纳主机指令_
def RecvMasterCMD(self):
cmd = super().ReadSerial()
print("Sensor %d recv cmd %d " % (self.sensorid,cmd))
return cmd
class MasterClass(SerialClass):
_# 类变量:_
_# BUSY_STATE -繁忙状况-0_
_# IDLE_STATE -闲暇状况-1_
BUSY_STATE, IDLE_STATE = (0, 1)
START_CMD, STOP_CMD, SENDID_CMD, SENDVALUE_CMD = (0, 1, 2, 3)
_# 类的初始化_
def __init__(self,state:int = IDLE_STATE,port:str = "COM17"):
_# 调用父类的初始化办法,super() 函数将父类和子类衔接_
super().__init__(port)
self.valuequeue = queue.Queue(10)
self.__masterstatue = state
_# 敞开主机_
def StartMaster(self):
super().OpenSerial()
logging.info("START MASTER :"+self.dev.port)
_# 中止主机_
def StopMaster(self):
super().CloseSerial()
logging.info("CLOSE MASTER :" + self.dev.port)
_# 接纳传感器ID号_
def RecvSensorID(self):
sensorid = super().ReadSerial()
logging.info("MASTER RECIEVE ID : " + str(sensorid))
return sensorid
_# 接纳传感器数据_
def RecvSensorValue(self):
data = super().ReadSerial()
logging.info("MASTER RECIEVE DATA : " + str(data))
self.valuequeue.put(data)
return data
_# 主机发送指令_
def SendSensorCMD(self,cmd):
super().WriteSerial(str(cmd))
logging.info("MASTER SEND CMD : " + str(cmd))
_# 主机回来作业状况-_
def RetMasterStatue(self):
return self.__masterstatue
模仿实例
这儿,咱们运用 XCOM 软件和咱们的 Python 程序进行交互。
传感器试验模仿
这儿,咱们首要在主函数中创立传感器方针,完结初始化后使能传感器中串口模块,并设置循环,轮询读取指令并履行操作,示例代码如下:
if __name__ == "__main__":
_# 创立传感器方针_
s = SensorClass(port="COM11", id=1, state=SensorClass.RESPOND_MODE)
_# 初始化传感器_
s.InitSensor()
_# 传感器敞开_
s.StartSensor()
while True:
_# 依据不同指令履行不同操作_
cmd = s.RecvMasterCMD()
_# START_CMD, STOP_CMD, SENDID_CMD, SENDVALUE_CMD = (0, 1, 2, 3)_
if cmd == SensorClass.SENDID_CMD:
s.SendSensorID()
elif cmd == SensorClass.SENDVALUE_CMD:
s.SendSensorValue()
elif cmd == SensorClass.STOP_CMD:
s.StopSensor()
break
print(" Sensor Stop Work!")
咱们来看一下实践验证作用:
主机试验模仿
这儿,咱们首要在主函数中创立并敞开主机方针,咱们的 xcom 模仿传感器,主机在轮询中发送接纳数据指令,并将接纳的数据参加主机类的行列,最终发送停机指令,并封闭主机。
if __name__ == "__main__":
m = MasterClass(state=MasterClass.IDLE_STATE, port="COM17")
m.StartMaster()
_# START_CMD, STOP_CMD, SENDID_CMD, SENDVALUE_CMD = (0, 1, 2, 3)_
_# 发送指令,获取传感器ID_
m.SendSensorCMD(MasterClass.SENDID_CMD)
m.RecvSensorID()
for i in range(3):
_# 发送指令,获取传感器数据_
m.SendSensorCMD(MasterClass.SENDVALUE_CMD)
m.RecvSensorValue()
m.SendSensorCMD(MasterClass.STOP_CMD)
m.StopMaster()
print("Master Stop Work!")
这儿咱们将主机日志打印到文件中:
_# 在装备下日志输出方针文件和日志格局_
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT)
咱们来看一下实践验证作用:
能够看到两个试验都能够完好运转,关于两个类的交互作业,咱们将在后续多线程中讲到。