问题简述:
最近在做树莓派项目,想写一个能够实时更新数据的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
```