qq_46051246 2021-10-19 19:45 采纳率: 0%
浏览 167

用python的GUI写一个实时更新数据的界面应该怎么写?

问题简述:
最近在做树莓派项目,想写一个能够实时更新数据的GIUI界面,但是遇到问题,就是在不断接收数据时我用了一个循环来做,但是在做GUI的时候也发现有了mainloop()函数,把数据接收后进行显示,结果就出现了,卡在第一个数据界面上,只有当点击退出GUI界面时,才会退出GUI界面,重新更新第二次接收到的数据,我知道它是卡在了mainloop()里,想问这种问题应该怎么解决?

# -*- coding: UTF-8 -*-
import time
import RPi.GPIO as GPIO
import jianpan
import os
import tkinter as tk

# 一下试一下nrf24l01的C语言宏定义
TX_ADR_WIDTH = 5  # 5 uints TX address width
RX_ADR_WIDTH = 5  # 5 uints RX address width
TX_PLOAD_WIDTH = 32  # 20 uints TX payload
RX_PLOAD_WIDTH = 32  # 20 uints TX payload

TX_ADDRESS = [0x34, 0x43, 0x10, 0x10, 0x01]  # 本地地址
RX_ADDRESS = [0x34, 0x43, 0x10, 0x10, 0x01]  # 接收地址
sta = 0
RX_DR = sta ^ 6
TX_DS = sta ^ 5
MAX_RT = sta ^ 4
READ_REG = 0x00  # 读寄存器指令
WRITE_REG = 0x20  # 写寄存器指令
RD_RX_PLOAD = 0x61  # 读取接收数据指令
WR_TX_PLOAD = 0xA0  # 写待发数据指令
FLUSH_TX = 0xE1  # 冲洗发送 FIFO指令
FLUSH_RX = 0xE2  # 冲洗接收 FIFO指令
REUSE_TX_PL = 0xE3  # 定义重复装载数据指令
NOP = 0xFF  # 保留
# *************************************SPI(nRF24L01)寄存器地址****************************************************
CONFIG = 0x00  # 配置收发状态,CRC校验模式以及收发状态响应方式
EN_AA = 0x01  # 自动应答功能设置
EN_RXADDR = 0x02  # 可用信道设置
SETUP_AW = 0x03  # 收发地址宽度设置
SETUP_RETR = 0x04  # 自动重发功能设置
RF_CH = 0x05  # 工作频率设置
RF_SETUP = 0x06  # 发射速率、功耗功能设置
STATUS = 0x07  # 状态寄存器
OBSERVE_TX = 0x08  # 发送监测功能
CD = 0x09  # 地址检测
RX_ADDR_P0 = 0x0A  # 频道0接收数据地址
RX_ADDR_P1 = 0x0B  # 频道1接收数据地址
RX_ADDR_P2 = 0x0C  # 频道2接收数据地址
RX_ADDR_P3 = 0x0D  # 频道3接收数据地址
RX_ADDR_P4 = 0x0E  # 频道4接收数据地址
RX_ADDR_P5 = 0x0F  # 频道5接收数据地址
TX_ADDR = 0x10  # 发送地址寄存器
RX_PW_P0 = 0x11  # 接收频道0接收数据长度
RX_PW_P1 = 0x12  # 接收频道0接收数据长度
RX_PW_P2 = 0x13  # 接收频道0接收数据长度
RX_PW_P3 = 0x14  # 接收频道0接收数据长度
RX_PW_P4 = 0x15  # 接收频道0接收数据长度
RX_PW_P5 = 0x16  # 接收频道0接收数据长度
FIFO_STATUS = 0x17  # FIFO栈入栈出状态寄存器设置

keyword = 0
# RX_DR = 0
# 树莓派各个引脚的定义
MOSI = 15
CSN = 12
MISO = 16
SCK = 13
CE = 11
IRQ = 18


def GPIO_Init():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setwarnings(False)
    Pinlist = [15, 12, 13, 11, 22]
    GPIO.setup(Pinlist, GPIO.OUT)
    Pinlist_Input = [16, 18]
    GPIO.setup(Pinlist_Input, GPIO.IN)
    return 0


def LEDH():
    GPIO.output(22, GPIO.HIGH)


def LEDL():
    GPIO.output(22, GPIO.LOW)


# ****************************************************************************************************
# *函数:uint SPI_RW(uint dat)
# *功能:NRF24L01的SPI写时序
# ****************************************************************************************************
def SPI_RW(dat):
    bit_ctr = 8
    _MOSI = 0
    while (bit_ctr):

        bit_ctr = bit_ctr - 1
        _MOSI = dat & 0x80  # output 'dat', MSB to MOSI
        if (_MOSI):
            GPIO.output(MOSI, GPIO.HIGH)
        else:
            GPIO.output(MOSI, GPIO.LOW)
        dat = (dat << 1)  # shift next bit into MSB..
        GPIO.output(SCK, GPIO.HIGH)  # Set SCK GPIO.high..
        dat |= GPIO.input(MISO)  # capture current MISO bit
        GPIO.output(SCK, GPIO.LOW)  # ..then set SCK GPIO.low again
    return dat


# ****************************************************************************************************
# *函数:uchar SPI_Read(uchar reg)
# *功能:NRF24L01的SPI读时序
# *****************************************************************************************************
def SPI_Read(reg):
    reg_val = 0
    GPIO.output(CSN, GPIO.LOW)  # CSN GPIO.low, initialize SPI communication...
    SPI_RW(reg)  # Select register to read from..
    reg_val = SPI_RW(0)  # ..then read registervalue
    GPIO.output(CSN, GPIO.HIGH)  # CSN GPIO.high, terminate SPI communication
    return reg_val  # return register value


# ****************************************************************************************************#
# *功能:NRF24L01读写寄存器函数
# ****************************************************************************************************#
def SPI_RW_Reg(reg, value):
    status = 0
    GPIO.output(CSN, GPIO.LOW)  # CSN GPIO.low, init SPI transaction
    status = SPI_RW(reg)  # select register
    SPI_RW(value)  # ..and write value to it..
    GPIO.output(CSN, GPIO.HIGH)  # CSN GPIO.high again
    return status  # return nRF24L01 status uchar


# ****************************************************************************************************#
# *函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
# *功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数
# ****************************************************************************************************#
def SPI_Read_Buf(reg, pBuf, uchars):
    status = 0
    uchar_ctr = 0
    GPIO.output(CSN, GPIO.LOW)  # Set CSN GPIO.low, init SPI tranaction
    status = SPI_RW(reg)  # Select register to write to and read status uchar
    while (uchar_ctr < uchars):
        pBuf[uchar_ctr] = SPI_RW(0)  #
        uchar_ctr = uchar_ctr + 1
    GPIO.output(CSN, GPIO.HIGH)
    return (status)  # return nRF24L01 status uchar


# *********************************************************************************************************
# *函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
# *功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数
# *********************************************************************************************************#
def SPI_Write_Buf(reg, pBuf, uchars):
    status = 0
    uchar_ctr = 0
    GPIO.output(CSN, GPIO.LOW)  # SPI使能
    status = SPI_RW(reg)
    while (uchar_ctr < uchars):  #
        SPI_RW(pBuf[uchar_ctr])
        uchar_ctr = uchar_ctr + 1
    GPIO.output(CSN, GPIO.HIGH)  # 关闭SPI
    return (status)


def RX_Mode():
    GPIO.output(CE, GPIO.LOW)  # chip enable
    GPIO.output(CSN, GPIO.HIGH)  # Spi disable
    GPIO.output(SCK, GPIO.LOW)  # Spi clock line init GPIO.high
    SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH)  # 写本地地址
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH)
    SPI_RW_Reg(WRITE_REG + EN_AA, 0x01)
    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01)
    SPI_RW_Reg(WRITE_REG + RF_CH, 40)
    SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH)
    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x09)
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f)
    GPIO.output(CE, GPIO.HIGH)
    return 0


def SetRX_Mode():
    GPIO.output(CE, GPIO.LOW)
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f)  # IRQ收发完成中断响应,16位CRC    ,主接收
    GPIO.output(CE, GPIO.HIGH)


def TX_Mode(BUF):
    GPIO.output(CE, GPIO.LOW)
    SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH)
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH)
    SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH)
    SPI_RW_Reg(WRITE_REG + EN_AA, 0x01)
    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01)
    SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a)
    SPI_RW_Reg(WRITE_REG + RF_CH, 40)
    SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH)
    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x09)
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e)
    GPIO.output(CE, GPIO.HIGH)


def Check_ACK(clear):
    global IRQ
    if GPIO.input(IRQ):
        sta = SPI_RW(NOP)
        if sta & 0x20:
            LEDH()
            time.sleep(0.5)
            LEDL()
            time.sleep(0.5)
        if sta & 0x10:
            if clear:
                SPI_RW(FLUSH_TX)
            SPI_RW_Reg(WRITE_REG + STATUS, sta)
            GPIO.output(IRQ, GPIO.HIGH)
        if (TX_DS):
            return (0x00)
        else:
            return (0xff)


def NRF2401RxcPacket(rx_buf):
    flag = 0
    for a in range(0, 3):
        sta = SPI_Read(STATUS)
        if sta & 0x40:
            GPIO.output(CE, GPIO.LOW)
            SPI_Read_Buf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH)
            flag = 1
        SPI_RW_Reg(WRITE_REG + STATUS, sta)
        SPI_RW_Reg(FLUSH_RX, 0xff)
    return flag


class UpdateLabel():
    def __init__(self):
        self.win = tk.Tk()
        self.win.title('智慧安防系统')  # 窗口名 智慧安防系统
        self.win.minsize(40, 40)  # 设置窗口的最小大小
        self.ctr1 = 0  # 气体
        self.ctr2 = 0  # 光敏
        self.ctr3 = 0  # 火焰
        self.ctr4 = 0  # 电流
        self.ctr5 = 0  # 温度
        self.tk_var1 = tk.StringVar()
        self.tk_var1.set("0")
        self.tk_var2 = tk.StringVar()
        self.tk_var2.set("0")
        self.tk_var3 = tk.StringVar()
        self.tk_var3.set("0")
        self.tk_var4 = tk.StringVar()
        self.tk_var4.set("0")
        self.tk_var5 = tk.StringVar()
        self.tk_var5.set("0")
        l1 = tk.Label(self.win, textvariable=self.tk_var1, bg='green', font=('Arial', 12), width=30, height=2,
                      anchor="w")  # 设置气体标签
        l1.pack()
        l2 = tk.Label(self.win, textvariable=self.tk_var2, bg='yellow', font=('Arial', 12), width=30, height=2,
                      anchor="w")  # 设置光敏标签
        l2.pack()
        l3 = tk.Label(self.win, textvariable=self.tk_var3, bg='purple', font=('Arial', 12), width=30, height=2,
                      anchor="w")  # 设置火焰标签
        l3.pack()
        l4 = tk.Label(self.win, textvariable=self.tk_var4, bg='pink', font=('Arial', 12), width=30, height=2,
                      anchor="w")  # 设置电流标签
        l4.pack()
        l5 = tk.Label(self.win, textvariable=self.tk_var5, bg='white', font=('Arial', 12), width=30, height=2,
                      anchor="w")  # 设置温度标签
        l5.pack()
        self.updater()
        self.win.mainloop()

    def updater(self):
        self.ctr1 = 0
        self.ctr2 = 1
        self.ctr3 = 2
        self.ctr4 = 3
        self.ctr5 = 100
        self.tk_var1.set(str(self.ctr1))
        self.tk_var2.set(str(self.ctr2))
        self.tk_var3.set(str(self.ctr3))
        self.tk_var4.set(str(self.ctr4))
        self.tk_var5.set(str(self.ctr5))


if __name__ == "__main__":
    TxBuf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    RxBuf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    GPIO_Init()
    RX_Mode()
    while True:
        # print('first:')
        # print('NAME:xiaoming')
        # print('XUEHAO:4190211120')
        # print('CURRENT:{}uA'.format(100))
        while not NRF2401RxcPacket(RxBuf):
            jianpan.key()
            if jianpan.keyword:
                if jianpan.keyword == '1':
                    TxBuf[0] = 0xdf
                elif jianpan.keyword == '2':
                    TxBuf[0] = 0x00
                elif jianpan.keyword == 'A':
                    TxBuf[0] = 0x20
                elif jianpan.keyword == '3':
                    TxBuf[1] = 0x00
                    TxBuf[2] = 0x45
                elif jianpan.keyword == '4':
                    TxBuf[1] = 0x00
                    TxBuf[2] = 0x46
                TX_Mode(TxBuf)
                Check_ACK(1)
                jianpan.keyword = 0
                TxBuf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
                RX_Mode()
        else:
            if RxBuf[12] == 0x55:
                os.system('raspistill -v')
            dat0 = (RxBuf[0] << 2) | (RxBuf[1] & 0x03)
            dat1 = (RxBuf[2] << 2) | (RxBuf[3] & 0x03)
            dat2 = (RxBuf[4] << 2) | (RxBuf[5] & 0x03)
            dat3 = (RxBuf[6] << 2) | (RxBuf[7] & 0x03)
            dat4 = RxBuf[8] * 256 + RxBuf[9]
            UL = UpdateLabel()
            print('gas:{}   illumination:{}   flam:{}   current:{}   temperature:{}'.format(dat0, dat1, dat2, dat3,
                                                                                            dat4 / 100))
            #   print(RxBuf[12])

            if dat4 > 5000 or dat2 < 800:
                if RxBuf[11] & 0x10 == 0:
                    TxBuf[0] |= 0x10
                    TX_Mode(TxBuf)
                    RX_Mode()
            SetRX_Mode()
```python


```

  • 写回答

1条回答 默认 最新

  • CSDN专家-黄老师 2021-10-19 21:47
    关注

    应该是你数据更新频率太快而导致软件卡死,你将数据实时更新改用多线程,将软件对象传入多线程,用多线程更新试试

    评论

报告相同问题?

问题事件

  • 创建了问题 10月19日

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料