如何转换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
相关产品推荐
相关产品推荐

