You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派4上MCP3208读数错误且极不稳定问题求助

MCP3208 ADC读数错误且噪声极大的排查问题

我使用MCP3208这款ADC通过放大器读取传感器输出。已验证运算放大器的输出符合预期,且直接测量ADC引脚的电压也正常。该ADC由树莓派提供的3.3V供电,Vref引脚同样接3.3V。

问题出在ADC上(已更换两片芯片测试),其读数错误且噪声极大,以下是ADC引脚输入为3.3V时的输出示例:

Raw Value: 1338 | Voltage: 1.078V
Raw Value: 1079 | Voltage: 0.870V
Raw Value: 88 | Voltage: 0.071V
Raw Value: 816 | Voltage: 0.658V
Raw Value: 1250 | Voltage: 1.007V
Raw Value: 1496 | Voltage: 1.206V
Raw Value: 0 | Voltage: 0.000V
Raw Value: 1095 | Voltage: 0.882V
Raw Value: 711 | Voltage: 0.573V
Raw Value: 1482 | Voltage: 1.194V
Raw Value: 327 | Voltage: 0.264V
Raw Value: 1344 | Voltage: 1.083V
Raw Value: 967 | Voltage: 0.779V
Raw Value: 38 | Voltage: 0.031V
Raw Value: 647 | Voltage: 0.521V
Raw Value: 3673 | Voltage: 2.960V
Raw Value: 967 | Voltage: 0.779V
Raw Value: 704 | Voltage: 0.567V
Raw Value: 1087 | Voltage: 0.876V
Raw Value: 999 | Voltage: 0.805V
Raw Value: 384 | Voltage: 0.309V
Raw Value: 583 | Voltage: 0.470V
Raw Value: 1112 | Voltage: 0.896V
Raw Value: 1343 | Voltage: 1.082V
Raw Value: 1279 | Voltage: 1.031V
Raw Value: 2672 | Voltage: 2.153V
Raw Value: 1248 | Voltage: 1.006V

以下是读取ADC值所用的库代码:

#include "MCP3208.h"

#include <wiringPi.h>

using namespace std;

MCP3208::MCP3208(int CS, int CLK, int MOSI, int MISO) {
    this->CS = CS;
    this->CLK = CLK;
    this->MOSI = MOSI;
    this->MISO = MISO;
}

void MCP3208::setupSPI() {
    wiringPiSetup();
    
    pinMode(CS, OUTPUT);
    pinMode(CLK, OUTPUT);
    pinMode(MOSI, OUTPUT);
    pinMode(MISO, INPUT);

    digitalWrite(CS, HIGH);
    digitalWrite(CLK, LOW);
    digitalWrite(MOSI, LOW);
}

int MCP3208::readADC(int channel) {
    if (channel > 7 || channel < 0) return -1;
    
    digitalWrite(CS, LOW); //启动通信

    // 构造命令
    // 0b -> 二进制
    // 11 -> 命令起始位
    // (channel << 3) -> 将指定通道转为二进制后移至第5、4、3位
    // 最后三位000 -> 无关位
    unsigned char command = 0b11000000 | (channel << 3);
    
    // 从左到右发送命令
    for (int i = 7; i >= 0; i--) {
        digitalWrite(MOSI, (command >> i) & 1); // 通过右移和掩码'& 1'提取第i位的值
        digitalWrite(CLK, HIGH);
        digitalWrite(CLK, LOW);
    }

    // 读取12位ADC数据
    int value = 0;
    for (int i = 11; i >= 0; i--) {
        value <<= 1; // 将现有位左移,为下一位读取腾出空间
        digitalWrite(CLK, HIGH); // 向ADC发送信号,使其在MISO输出下一位
        if (digitalRead(MISO)) {
            value |= 1; // 当位为1时添加该位,左移时默认位为0
        }
        digitalWrite(CLK, LOW);
    }

    digitalWrite(CS, HIGH);

    return value;
}

以下是用于打印值的程序代码:

#include "/home/pi/Desktop/MCP3208/MCP3208.h"

#include <wiringPi.h>
#include <stdio.h>

// MCP3208参数
#define CS 10    // 片选引脚
#define CLK 14   // 时钟引脚
#define MOSI 12  // 主出从入引脚
#define MISO 13  // 主入从出引脚

MCP3208 adc(CS, CLK, MOSI, MISO);

int main() {
    adc.setupSPI();
  
    while (1) {
        int value = adc.readADC(1); // 读取通道1
        float voltage = value * 3.3 / 4095.0;
  
        printf("Raw Value: %d | Voltage: %.3fV\n", value, voltage);
  
        delay(500);
    }
  
    return 0;
}

补充说明:该电路此前使用MCP3008测试正常,为提高读数精度更换为MCP3208。根据两款ADC的数据手册,理论上无需更改电路即可直接替换,但不确定是否因此导致问题,也不清楚需具体检查哪些点。


内容的提问来源于stack exchange,提问作者LoneRetriever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 21:00:09