使用Python(SPI)读取ADC(MCP3001)数据
我试着用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