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

如何转换MAX11613双极性差分ADC值?树莓派3B+ C++采集异常排查

MAX11613双极性差分ADC采集结果异常问题

我正在尝试使用C++实现ADC双极性差分信号转换,所用设备为12位MAX11613,微控制器为树莓派3B+。目前已经可以正常采集到数值,但结果并非预期的AIN0与AIN1的差分结果。

该器件采用3.3V供电,AIN0输入范围为0-3.3V,AIN1为输入信号的虚拟地,电压为1.65V。

如下所示的器件双极性传输函数是我困惑的来源:为什么略低于1.65V中间值的输入会输出0b111111111111而非0b100000000001?如果该输出逻辑是正确的,我要如何调整才能得到相对于虚拟地输入(AIN1)的实际负电压值?

双极性传输函数


参考代码

max11613.h

#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
extern "C" {
    #include <linux/i2c.h>
   #include <linux/i2c-dev.h>
   #include <i2c/smbus.h>
}
#define MAX_ADDRESS  (0x34)//binary: 0110100
#define MAX_READ        (0x01)
#define MAX_WRITE       (0x00)
#define MAX_SETUP       (0x8E)//0x8E
//REG SEL2 SEL1 SEL0 CLK BIP/UNI RST X
//1000 1110=0x8E SEL2=0, SEL1=0, SEL0=0, VDD REF, EXTERNAL CLOCK, BIPOLAR, RESET 
#define MAX_CONFIG  (0x00)//0x00
//REG SCAN1 SCAN0 CS3 CS2 CS1 CS0 SGL/DIFF
//0000 0000=0x00 DIFFERENTIAL CHANNEL 0, 1 NO SCAN
class MAX11613 {
    protected:
        uint8_t   m_i2cAddress;
        uint32_t  m_conversionDelay;
    public:
        MAX11613(uint8_t i2cAddress = MAX_ADDRESS);
        void setup(void);
        int16_t readMAXADC_Differential_0_1(void);
    private:
};

max11613.cpp

#include "max11613.h"
#include <iostream>
int i2cMAXHandle;
float mv_conversion = float(3300.0/4095);
static void beginMAXTransmission(uint8_t i2cAddress) {
  i2cMAXHandle = i2cOpen(1, i2cAddress, 0);
  if(i2cMAXHandle < 0) {
    std::cout << "HANDLE ERROR: " << stderr << " " << strerror(errno) << std::endl;
    exit(1);
  }
}
static void endMAXTransmission(void) {
    i2cClose(i2cMAXHandle);
}
static void writeMAXRegister(uint8_t i2cAddress, uint8_t reg, uint8_t value) {
    uint8_t payload = value;
    beginMAXTransmission(i2cAddress);
    i2cWriteByteData(i2cMAXHandle, reg, payload);
    endMAXTransmission();
}
static int16_t readMAXRegister(uint8_t i2cAddress, uint8_t reg) {
    const uint8_t datalength = 2;
    char data[datalength];
    beginMAXTransmission(i2cAddress);
    i2cReadI2CBlockData(i2cMAXHandle, reg, data, datalength);
    endMAXTransmission();
    int16_t res = (uint16_t)(data[0] << 8) & ((data[0] & 0x08) ? 0xffff: ~0xf000) | (uint16_t)data[1];//移除前导1111位,合并data[0]和data[1]为16位整数值
    float mv = float(mv_conversion * float(res));//转换ADC结果为毫伏值
    return mv;
}
MAX11613::MAX11613(uint8_t i2cAddress) {
    m_i2cAddress = i2cAddress;
    m_conversionDelay = int(0);
}
void MAX11613::setup() {
    writeMAXRegister(m_i2cAddress, 1, MAX_SETUP);
    writeMAXRegister(m_i2cAddress, 1, MAX_CONFIG);//向ADC写入配置寄存器
}
int16_t MAX11613::readMAXADC_Differential_0_1() {
    int16_t res = readMAXRegister(m_i2cAddress, 0);//读取转换结果,右移得到12位结果
    usleep(100);
    return res;
}

输出数据示例

示例1:示波器读数为-1.16V时

  • readMAXRegister()第一次输出:1111001010110010 << 芯片输出的前四位固定为1111
  • readMAXRegister()第二次输出:0000001010110010 << 移除前四位1111后的调整结果
  • readMAXADC_Differential_0_1()最终输出:0000001010110010 690 << 该值为正数,并非预期的负差分值,似乎对应相对于实际地到VDD的电压值。

示例2:示波器读数为+1.28V时

  • readMAXRegister()第一次输出:1111110011111110 << 芯片输出的前四位固定为1111
  • readMAXRegister()第二次输出:0000110011111110 << 移除前四位1111后的调整结果
  • readMAXADC_Differential_0_1()最终输出:1111110011111011 -773 << 该负值应为正值。

补充信息

原理图

原理图

示波器采样图像

黄色波形为AIN0信号,示波器接地端连接到AIN1(双极性正弦波响应范围为-800mV到920mV),蓝色方波表示信号峰值和谷值处每次ADC读取的采样范围。
示波器采样图


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:57:02