使用Python(SPI)读取ADC(MCP3001)数据

0 投票
2 回答
2307 浏览
提问于 2025-04-18 10:51

我试着用Python从一个模数转换器(ADC)读取一些数据,但不幸的是,它没有成功。我希望有人能给我一点提示,因为我的脚本只生成了一堆混乱的数据。不过我看不出在位数上有什么错误……

我更新了下面的脚本,因为我现在读取的是16位的数据,并且去掉了前面和后面各3位。我需要中间的10位数据——如果我理解数据手册没错的话……

数据手册 MCP3001:(第15页) http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

HIGH = True
LOW  = False

def readAnalogData(SCLKPin, MOSIPin, MISOPin, CSPin):
    GPIO.output(CSPin,   HIGH)    
    GPIO.output(CSPin,   LOW)
    GPIO.output(SCLKPin, LOW)

    adcvalue = 0
    for i in range(16):
        GPIO.output(SCLKPin, HIGH)
        GPIO.output(SCLKPin, LOW)
        adcvalue <<= 1
        if(GPIO.input(MISOPin)):
            adcvalue |= 0x01
    adcvalue >>= 3
    adcvalue &= 0x3ff
    time.sleep(0.5)

    return adcvalue

SCLK        = 11 # Serial-Clock
MOSI        = 10 # Master-Out-Slave-In
MISO        = 9 # Master-In-Slave-Out
CS          = 17 # Chip-Select

GPIO.setup(SCLK, GPIO.OUT)
GPIO.setup(MOSI, GPIO.OUT)
GPIO.setup(MISO, GPIO.IN)
GPIO.setup(CS,   GPIO.OUT)

while True:
    print readAnalogData(SCLK, MOSI, MISO, CS) 

2 个回答

0

这个方法有效。基本上是之前的答案,但做了一些调整并进行了测试。

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

def ReadMCP3001():
    GPIO.setup(11, GPIO.OUT)
    GPIO.setup(7, GPIO.OUT)
    GPIO.setup(9, GPIO.IN)
    GPIO.output(11, False)  # CLK low
    GPIO.output(7, False)   # /CS low
    adcvalue = 0
    for i in range(13):
        GPIO.output(11, True)
        GPIO.output(11, False)
        adcvalue <<= 1
        if(GPIO.input(9)):
            adcvalue |= 0x001
    GPIO.output(7, True)    # /CS high
    adcvalue &= 0x3ff
    return adcvalue
0

从你提供的数据表和代码来看,似乎你想通过把数据转换成str类型,然后用str切片来丢掉最初的3个时钟周期的数据。

adcvalue = str(adcvalue)
adcvalue = adcvalue[3:12]
adcvalue = int(adcvalue)

如果是这样的话,这样做是行不通的。adcvalue是一个整数,转换成str后会变成十进制字符串。你可以选择在前面三个周期不采样数据,或者使用位掩码来从这个整数中去掉这些数据(比如用adcvalue &= 0x1ff)。

另外,你似乎是在负时钟边缘采样数据,但这个时候数据处于不稳定状态。我猜你可能需要在这里加个延迟,或者在正时钟边缘采样,这样数据会更稳定。

编辑

如上所述,试着在正时钟边缘采样。数据表第16页的图6-1显示了这一点。而且看起来它输出的是9位的MSB格式数据,然后再以LSB格式重复这些数据(见图6-2),所以我觉得你不需要保留10位数据。你可能只需要总共输出12位,然后丢掉前面3位。

像这样(未经测试):

def readAnalogData(SCLKPin, MOSIPin, MISOPin, CSPin):
    GPIO.output(CSPin,   HIGH)    
    GPIO.output(CSPin,   LOW)

    adcvalue = 0
    for i in range(12):
        GPIO.output(SCLKPin, LOW) # reverse order of hi/lo here
        GPIO.output(SCLKPin, HIGH)
        adcvalue <<= 1
        if(GPIO.input(MISOPin)):
            adcvalue |= 0x01
    adcvalue >>= 3
    # adcvalue &= 0x3ff <- commented out this line as should be no longer necessary

    return adcvalue

撰写回答