串网直通车——串口篇(Python+serial+threading)

        完整代码链接:https://download.csdn.net/download/qq_34162147/54904655

        本章节是续上一篇(界面篇)。如未搭建界面,请查阅以下链接。


串网直通车——界面篇_不尽之野火-CSDN博客


        本章节主要是实现串口功能,实现串口收发。类似串口调试助手。如未安装串口模块,可在Python根目录通过命令pip install pyserial进行安装。

1、打开串口

        Python使用串口功能以及线程功能,需要在开头引入。结合前篇(界面篇),需要在开头引入全局变量。

import serial       #串口
import threading    #线程

# 全局变量
global ser
global com_text
global trans_cu

        将以下代码替换到界面篇的com_ctrl函数。整体替换。

        这个函数中cn_var,cp_var,cr_var,cl_var,p0,p1都是通过按钮操作传递过来,读取下拉菜单的值。

        cn_var是按钮控件名 

        cp_var是端口号

        cr_var是波特率

        cl_var是指示灯控件

        p0是红灯图片

        p1是绿灯图片

       函数中,recv_com_data是用来定义接收线程。接收函数是thread_com_recv,后续有讲解。创建线程是为了实现接收一直起作用,程序并与界面显示并行运行。

        代码经过优化,经测试达到0错误。代码中多次使用if和else pass组合。是因为参考其他程序时,发现有错误,无法正常停止串口。而且在else之后绑定串口的ser无法继续使用。如有大神能够知道原因,请在评论区告知,在此感谢!

# 串口打开关闭函数
def  com_ctrl(cn_var,cp_var,cr_var,cl_var,p0,p1):

    global ser
    global com_state
    global com_text
    
    if cn_var.get() == "打开串口":
        ser = serial.Serial(
            port = cp_var,
            baudrate=int(cr_var),
            bytesize=serial.EIGHTBITS, 
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE, 
            timeout=0.2,
            xonxoff=False, 
            rtscts=False,           
            interCharTimeout=None
            )

        if ser.is_open:
            com_state=1
        else:
            ser.open()
            com_state=1

        com_text.delete(1.0,END)


        recv_com_data = threading.Thread(target=thread_com_recv)#创建接收线程
        recv_com_data.start()

    else :
        pass

    if ser.is_open and cn_var.get() == "关闭串口":
        com_state=0
        ser.close()  # 关闭传口
        cn_var.set("打开串口")
        cl_var.configure(image=p0) 
    else:
        pass

    if ser.is_open :
        cn_var.set("关闭串口")
        cl_var.configure(image=p1) 
    else:
        pass   

2、接收

        接收函数整体添加即可。这部分对应打开串口的thread_com_recv函数。

        特别注意:read_com = ser.read_all()后面是read_all,而不是readall。其他地方很多代码都存在这个问题。如果写成readall,可以使用。但是快速传输时,每包数据小于500ms,问题就暴露了,接收出错。实际官方是read_all。

        代码中com_text.see(END),see是用于ScrolledText滚动条文本框控件的光标移动,使得滚动条随着接收数据的增多而移动至最后。此部分结合界面篇带滚动条文本框部分。

        代码中使用了try和except Exception:break的组合,作用在于接收时,防止接收函数read_all()导致出错。出错时会有退出机制。其他网上代码存在此部分不完善的地方。这部分导致停止运行时无法正常停止。必须强制关闭运行进程。

        代码中“停止接收线程”备注那部分,作用是点击按钮关闭时,能够跳出线程,并终止。因为接收代码运行时,一直在while循环。其他网上代码存在此部分不完善的地方。必须强制关闭运行进程,否则串口一直出错而占用。

        代码中的decode是解码,用于串口接收到十六进制ACSII码的解码。

        此部分代码提到的com_send函数,后续会讲解到。只测试接收时,可以先屏蔽。

        特别注意:此部分代码测试时,不能直接点击窗口右上角关闭,必须优先点击关闭串口按钮,关闭窗口。

# 串口数据接收线程
def thread_com_recv():
    global ser
    global com_text
    global com_state
    global trans_cu
    while True:
        try:
            read_com = ser.read_all()
            if len(read_com) > 0:
                trans_cu=bytes(read_com).decode('ascii')           
                com_text.insert(END,trans_cu)
                com_text.insert(END,'\n')
                com_text.see(END)#滚动条移动到最新输入位置           
                # net_send(trans_cu) 
                com_send('I have received your data')       
                print("COM 接收到的数据:%s" % read_com)
                print("COM 接收到的数据:%s" % trans_cu)
            else:
                pass 
        except Exception:
            break  

        if(com_state==0):
            break   #停止wihile循环,停止接收线程
        else:
            pass

插节

        如果程序一直运行,不知道什么错误,如图所示,可以强制停止。我用的是VScode+python3.8

3、发送

         这部分的代码直接添加即可。此部分结合接收函数使用测试。

        代码中encode是编码。

def com_send(cs_var):
    s = ser.isOpen()
    if s == True:
        ser.write(cs_var.encode("utf-8"))

4、测试

        可用串口助手与虚拟串口两个小软件配合从测试。测试效果如图所示。

 5、拓展

        在学习过程,参考了不少资料,也填了不少坑。在此感谢各位前辈们的付出。经过整理筛选后,同样将有用的分享给大家!

Python实现串口通信(pyserial) - -零 - 博客园

Python 实现串口调试助手_u011625775的博客-CSDN博客_python串口调试助手(此代码需要完善)

python3 字符串、十六进制字符串、数字、字节之间的转换_羊驼的博客笔记-CSDN博客

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值