Python 字节缓冲区仅给出零,即使在 Raspberry Pi 上通过 SPI 正确接收数据也是如此

Python bytes buffer only giving out zeros even though data is being correctly received through SPI on Raspberry Pi

这是来自 的跟进问题,但这是一个不同的问题,所以我 post 在这里提出一个新问题。

我正在使用 ctypes 从 python 脚本调用 c 函数。正在调用的 c 函数是:

uint32_t crc32Word(uint32_t crc, const void *buffer, uint32_t size)

我有这个 python 代码:

import datetime
import os
import struct
import time
import pigpio
import spidev
import ctypes

lib = ctypes.CDLL('/home/pi/serial_communication/crc.so')
lib.crc32Word.argtypes = ctypes.c_uint32, ctypes.c_void_p, ctypes.c_uint32
lib.crc32Word.restype = ctypes.c_uint32

bus = 0
device = 0
spi = spidev.SpiDev()
spi.open(bus, device)
spi.max_speed_hz = 4000000
spi.mode = 0

pi.set_mode(12, pigpio.INPUT)

C=0
 
def output_file_path():
    return os.path.join(os.path.dirname(__file__),
               datetime.datetime.now().strftime("%dT%H.%M.%S") + ".csv")
 
def spi_process(gpio,level,tick):
    print("Detected")
    data = bytes([0]*1024)
    spi.xfer([0x02])
    with open(output_file_path(), 'w') as f:
        t1=datetime.datetime.now()
        for x in range(1):
            spi.xfer2(data)
            values = struct.unpack("<" +"I"*256, bytes(data))
            C = lib.crc32Word(0xffffffff,data,len(data))
            f.write("\n")
            f.write("\n".join([str(x) for x in values]))
        t2=datetime.datetime.now()
        print(t2-t1)
        print(C)

input("Press Enter to start the process ")
spi.xfer2([0x01])

cb1=pi.callback(INTERRUPT_GPIO, pigpio.RISING_EDGE, spi_process)

while True:
    time.sleep(1)

之前,我将数据初始化为 data = [0]*1024,所以我收到了前面 post 中提到的一些错误。但是通过将数据初始化为字节来解决错误。现在我遇到的问题是,即使在 Raspberry Pi 上收到了正确的数据(使用逻辑分析仪检查),文件中也只存储了 0。

我还尝试使用 numpy 库将数据初始化为数组而不是列表,如下所示,但我收到一条错误消息: 尝试过的代码:

import numpy as np
 
#changed initialization of data to:
data= np.arange(1024) #also tried: np.zeros(1024,ctypes.c_uint8), also get same error

错误:

File "2crc_spi.py", line 48, in spi_process
   spi.xfer2(data)
TypeError: Non-Int/Long value in arguments: b5410b00

但数据一次只接收一个字节,所以不确定使用数组时问题出在哪里。

有人可以帮忙吗?谢谢~

编辑: 下面是在我开始集成 CRC 功能之前可以很好地处理数据收集和解包功能的原始代码:

import datetime
import os
import struct
import time
import pigpio
import spidev

bus = 0
device = 0
spi = spidev.SpiDev()
spi.open(bus, device)
spi.max_speed_hz = 4000000
spi.mode = 0

pi.set_mode(12, pigpio.INPUT)

a=0
 
def output_file_path():
    return os.path.join(os.path.dirname(__file__),
               datetime.datetime.now().strftime("%dT%H.%M.%S") + ".csv")
 
def spi_process(gpio,level,tick):
    print("Detected")
    data = [0]*2048
    spi.xfer([0x02])
    with open(output_file_path(), 'w') as f:
        t1=datetime.datetime.now()
        for x in range(1):
            spi.xfer2(data)
            values = struct.unpack("<" +"I"*256, bytes(data))
            f.write("\n")
            f.write("\n".join([str(x) for x in values]))
        t2=datetime.datetime.now()
        print(t2-t1)

input("Press Enter to start the process ")
spi.xfer2([0x01])

cb1=pi.callback(INTERRUPT_GPIO, pigpio.RISING_EDGE, spi_process)

while True:
   time.sleep(1)

正如@Mark 在评论中所建议的那样,您必须将 数据 存储到另一个 variable/list 中,例如:recv = spi.xfer2(data)。那么你需要在你的 unpack 函数中使用这个 recv 。 此外,您还可以使用名为 zlib 的 python 库,而不是使用 c 库(还有其他 python 库)。

还有一点,由于zlib只接受字节作为输入,你需要将recv转换成字节(这里recv 是一个列表;检查我的代码)。 我修改了你的一些代码。

import datetime
import os
import struct
import time
import pigpio
import spidev
import zlib

bus = 0
device = 0
spi = spidev.SpiDev()
spi.open(bus, device)
spi.max_speed_hz = 4000000
spi.mode = 0

pi.set_mode(12, pigpio.INPUT)

C=0
 
def output_file_path():
    return os.path.join(os.path.dirname(__file__),
               datetime.datetime.now().strftime("%dT%H.%M.%S") + ".csv")
 
def spi_process(gpio,level,tick):
    print("Detected")
    data = bytes([0]*1024)
    spi.xfer2([0x02])
    with open(output_file_path(), 'w') as f:
        t1=datetime.datetime.now()
        for x in range(1):
            recv = spi.xfer2(data)
            values = struct.unpack("<" +"I"*256, bytes(recv))
            C = zlib.crc32(bytes(recv))
            f.write("\n")
            f.write("\n".join([str(x) for x in values]))
        t2=datetime.datetime.now()
        print(t2-t1)
        print(C)

input("Press Enter to start the process ")
spi.xfer2([0x01])

cb1=pi.callback(INTERRUPT_GPIO, pigpio.RISING_EDGE, spi_process)

while True:
    time.sleep(1)