This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] ADS1292R 不稳定转换 ECG (10s 后在通道2中归零

Guru**** 2387830 points
Other Parts Discussed in Thread: ADS1292R, ADS1292
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/1006607/ads1292r-unstable-convert-ecg-get-zero-in-channel-2-after-10s

主题中讨论的其他器件:ADS1292RADS1292

大家好,

"大约10s 后在通道2中读取零"

我已经过测试步骤:

a.使用单模式?

b.使用测试模式

硬件(ADS1292R)状态错误或时序问题? 如何设置。

您能给我一些建议吗?

1.硬件  

I 参考数据表电路。  

2.SW,SPS 1k Hz,读取数据间隔为5ms  

初始化和读取函数  

3.波形(正常;失败)和概述

typedef enum
{
    // Device Settings (READ ONLY REGs)
    ECG_REG_ID          = 0x00,
    // Reg ID Control Register: Factory programmed, Read only register
    // Global settings accross channels
    ECG_REG_CONFIG1     = 0x01,     // Configuration 1 Reg
    ECG_REG_CONFIG2     = 0x02,     // Configuration 1 Reg
    ECG_REG_LOFF        = 0x03,     // Lead-Off Control Reg
    // Channel-specific settings
    ECG_REG_CH1SET      = 0x04,     // Channel 1 Settings
    ECG_REG_CH2SET      = 0x05,     // Channel 2 Settings
    ECG_REG_RLD_SENS    = 0x06,     // Right Leg Drive Sense Selection
    ECG_REG_LOFF_SENS   = 0x07,     // Lead-Off Sense Selection
    ECG_REG_LOFF_STAT   = 0x08,     // Lead-Off Sense Status
    // GPIO and other Registers
    ECG_REG_RESP1       = 0x09,     // Respiration Control Register 1
    ECG_REG_RESP2       = 0x0A,     // Respiration Control Register 1
    ECG_REG_GPIO        = 0x0B,     // General Purpose I/O Register

    ECG_REG_COUNT       = 0x0C      // Reg Count
} ECG_REG_MAP;

// Config2 register: Configures ADC sample rate & mode (continuous / one shot)
typedef enum
{
    // Bits 0 - 2 are used for oversampling ratio for both channels 1 & 2
    // fMod (128 KHz) / one of these #s.
    // (Ex /64 = 128K / 64 = 2KHz ECG sampling)
    ECG_CONFIG1_DIVBY_1024  = 0x00,
    ECG_CONFIG1_DIVBY_512   = 0x01,
    ECG_CONFIG1_DIVBY_256   = 0x02,
    ECG_CONFIG1_DIVBY_128   = 0x03,
    ECG_CONFIG1_DIVBY_64    = 0x04,
    ECG_CONFIG1_DIVBY_32    = 0x05,
    ECG_CONFIG1_DIVBY_16    = 0x06,
    // Bits 6-3 are constants, and must be set to 0
    ECG_CONFIG1_CONSTANT    = 0x00,
    // Bit 7
    ECG_CONFIG1_SINGLE_SHOT = 0x80,
    ECG_CONFIG1_CONTINUOUS  = 0x00
} ECG_CONFIG1_REG;

#define ECG_CONFIG1_NORMAL  (ECG_CONFIG1_CONTINUOUS |ECG_CONFIG1_DIVBY_128)


// Config2 register: Configures the TEST signal, CLK, reference and LOFF buffer
typedef enum
{
    // Bit 7 must always be set high & BIT2: Must always be set to 0
    ECG_CONFIG2_CONSTANT                = 0x80,
    // Bit 6: PDB_LOFF_COMP
    ECG_CONFIG2_PDB_LOFF_COMP_ENABLED   = 0x40,
    // BIT5: PDB_REFBUF
    ECG_CONFIG2_PDB_REFBUF_ON           = 0x20,
    // BIT4: VREF)2.42V or 4.033V. We can only have a 2.42
    // reference since the 4 V ref requires a 5VDC supply
    // ECG_CONFIG2_VREF_4033             = 0x10,
    // BIT 3: CLK_EN internal Osc is test used in our design.
    // select external/internal Osc
    ECG_CONFIG2_INTEROSC_ON = 0x08,
    // BIT1: TEST signal
    ECG_CONFIG2_TEST_ON                 = 0x02,
    // BIT 0: TEST_FREQ: DC / 1Hz
    ECG_CONFIG2_TEST_FREQ_1HZ           = 0x01
} ECG_CONFIG2_REG;

#define ECG_CONFIG2_TEST    (ECG_CONFIG2_CONSTANT \
                            | ECG_CONFIG2_PDB_REFBUF_ON | \
                            ECG_CONFIG2_TEST_ON | ECG_CONFIG2_TEST_FREQ_1HZ)
#define ECG_CONFIG2_NORMAL  (ECG_CONFIG2_CONSTANT | \
                             ECG_CONFIG2_PDB_LOFF_COMP_ENABLED |\
                            ECG_CONFIG2_PDB_REFBUF_ON  \
                             )

typedef enum
{
    // Bit 7: Channel power up / down
    ECG_CHAN_SET_PWR_DOWN               = 0x80,
    ECG_CHAN_SET_PWR_UP                 = 0x00,
    // BITS 6-4:  GAIN
    ECG_CHAN_SET_GAIN_6                 = 0x00,  // Default
    ECG_CHAN_SET_GAIN_1                 = 0x10,
    ECG_CHAN_SET_GAIN_2                 = 0x20,
    ECG_CHAN_SET_GAIN_3                 = 0x30,
    ECG_CHAN_SET_GAIN_4                 = 0x40,
    ECG_CHAN_SET_GAIN_8                 = 0x50,
    ECG_CHAN_SET_GAIN_12                = 0x60,
    // BITS 3:0 Channel input selection
    ECG_CHAN_SET_INPUT_NORMAL           = 0x00,
    ECG_CHAN_SET_INPUT_SHORTED          = 0x01,
    ECG_CHAN_SET_INPUT_RLD              = 0x02,
    ECG_CHAN_SET_INPUT_MVDD             = 0x03,
    ECG_CHAN_SET_INPUT_TEMP             = 0x04,
    ECG_CHAN_SET_INPUT_TEST             = 0x05,
    ECG_CHAN_SET_INPUT_RLD_DRP          = 0x06,
    ECG_CHAN_SET_INPUT_RLD_DRM          = 0x07,
    ECG_CHAN_SET_INPUT_RLD_DRPM         = 0x08,
    ECG_CHAN_SET_INPUT_ROUTE_IN3        = 0x09
} ECG_CHAN_SETTINGS_REG;

#define ECG_CH_OFF              (ECG_CHAN_SET_PWR_DOWN +  \
                                ECG_CHAN_SET_INPUT_SHORTED)
#define ECG_CH_DRP              (ECG_CHAN_SET_INPUT_RLD_DRP)
#define ECG_CH_RLD              (ECG_CHAN_SET_PWR_UP |ECG_CHAN_SET_INPUT_RLD)
#define ECG_CH_DRM              (ECG_CHAN_SET_INPUT_RLD_DRM)
#define ECG_CH_DRPM             (ECG_CHAN_SET_PWR_UP + \
                                ECG_CHAN_SET_INPUT_RLD_DRPM)
// If the gain is ever changed then the
// ECG_CONVERSION_FACTOR which assumes a gain of 6 should also be changed.
#define ECG_CH_NORMAL           (ECG_CHAN_SET_PWR_UP | \
                                ECG_CHAN_SET_INPUT_NORMAL)

typedef enum
{
    // Bits 7 & 6: Chop Freq
    ECG_RLD_SENS_CF_DIV_16              = 0x00,
    ECG_RLD_SENS_CF_RES                 = 0x40,
    ECG_RLD_SENS_CF_DIV_2               = 0x80,
    ECG_RLD_SENS_CF_DIV_4               = 0xC0,
    // Bit 5:  Buffer Power
    ECG_RLD_SENS_PDB_RLD_EN             = 0x20,
    // Bit 4: RLD_LOFF_SENSE
    ECG_RLD_SENS_RLD_LOFF_SENSE_EN      = 0x10,
    // Bit 3: RLD2N Ch2 RLD neg inputs
    ECG_RLD_SENS_RLD2N_CONNECTED        = 0x08,
    // Bit 2: RLD2P Ch2 RLD pos inputs
    ECG_RLD_SENS_RLD2P_CONNECTED        = 0x04,
    // Bit 1: RLD1N Ch1 RLD neg inputs
    ECG_RLD_SENS_RLD1N_CONNECTED        = 0x02,
    // Bit 0: RLD1P Ch1 RLD pos inputs
    ECG_RLD_SENS_RLD1P_CONNECTED        = 0x01
} ECG_RLD_SENS_REG;

#define RLD_SENS_USE_CH2        (ECG_RLD_SENS_PDB_RLD_EN \
                                | ECG_RLD_SENS_RLD2N_CONNECTED \
                                | ECG_RLD_SENS_RLD2P_CONNECTED)
#define RLD_SENS_USE_CH1        (ECG_RLD_SENS_PDB_RLD_EN \
                                | ECG_RLD_SENS_RLD1N_CONNECTED \
                                | ECG_RLD_SENS_RLD1P_CONNECTED)

#define RLD_SENS_USE_CH1_2        (ECG_RLD_SENS_PDB_RLD_EN \
                                | ECG_RLD_SENS_RLD1N_CONNECTED \
                                | ECG_RLD_SENS_RLD1P_CONNECTED \
                                | ECG_RLD_SENS_RLD2N_CONNECTED \
                                | ECG_RLD_SENS_RLD2P_CONNECTED )

typedef enum
{
    // Bits 7 & 5: Constant must be 0
    ECG_LOFF_STAT_CONSTANT              = 0x00,
    // Bit 6:  CLK_DIV
    ECG_LOFF_STAT_CLK_DIV_2048KHZ       = 0x40,  // Our HW provided external Osc
    // Bit 4: RLD_STAT
    ECG_LOFF_STAT_RLD_DISCONNECTED      = 0x20,
    // Bit 3 IN2N_OFF (Input 2 Negative electrode connection status)
    ECG_LOFF_STAT_IN2N_DISCONNECTED     = 0x08,
    // Bit 3 IN2P_OFF (Input 2 Positive electrode connection status)
    ECG_LOFF_STAT_IN2P_DISCONNECTED     = 0x04,
    // Bit 3 IN2N_OFF (Input 1 Negative electrode connection status)
    ECG_LOFF_STAT_IN1N_DISCONNECTED     = 0x02,
    // Bit 3 IN2N_OFF (Input 1 Positive electrode connection status)
    ECG_LOFF_STAT_IN1P_DISCONNECTED     = 0x01
} ECG_LOFF_STATUS_REG;

#define LOFF_CONFIG (ECG_LOFF_STAT_CLK_DIV_2048KHZ + \
                    ECG_LOFF_STAT_IN2N_DISCONNECTED + \
                    ECG_LOFF_STAT_IN2P_DISCONNECTED)

typedef enum
{
    // Bits 7 Calibration on
    ECG_RESP2_CALIB_ON                  = 0x80,
    // Bit 6 -3 Must be 0s.
    // Bit 2:
    ECG_RESP2_RESP_FREQ_64KHZ           = 0x04,
    ECG_RESP2_RESP_FREQ_32KHZ           = 0X00,
    // Bits 1:RLD_REF_INT Internal or externally generated RLD ref
    ECG_RESP2_RLD_REF_INTERNAL          = 0x02,
    ECG_RESP2_RLD_REF_EXTERNAL          = 0X00,
    // bit 0: must be 1
    ECG_RESP2_CONSTANT                  = 0x01,
} ECG_REG_RESP2_REG;

#define RESP2_EXTERNAL_REF          (ECG_RESP2_RLD_REF_EXTERNAL | \
                                    ECG_RESP2_CONSTANT)
#define RESP2_INTERNAL_REF          (ECG_RESP2_RLD_REF_INTERNAL | \
                                    ECG_RESP2_CONSTANT|ECG_RESP2_CALIB_ON)
typedef enum
{
    // System Commands
    ECG_WAKEUP = 0x02,      // Wake up from standby mode
    ECG_STANDBY = 0x04,     // Enter standby mode
    ECG_RESET = 0x06,
    // Reset the registers of the device to default values
    ECG_START = 0x08,       // Start / Restart (synchronized) conversions
    ECG_STOP = 0x0A,        // Stop Conversions
    ECG_OFFSETCAL = 0x1A,   // Channel offset calibration
    // Data Read Commands
    ECG_RDATAC = 0x10,      // Enable Read Data continuous mode
    ECG_SDATAC = 0x11,      // Stop Read Data Continuous mode
    ECG_RDATA = 0x12,       // Read data by command
    // Register Read / Write Commands. Note that these are 2 byte commands.
    // The second byte's lowest 5 bits contains the # of registers to R/W -1.
    // So to read 3 registers, the second byte should contain a 0x02.
    ECG_RREG = 0x20,
    // Read Register: The least 5 significant bits are \
    the starting register's address to read from
    ECG_WREG = 0x40
               // Write Register: The least 5 significant bits \
               are the starting register's address to write to
} ECG_CMD;

#define EXPECTED_ECG_ID             0x73

#define ECG_LOFF1P 0x1
#define ECG_LOFF1N 0x2
#define ECG_LOFF2P 0x4
#define ECG_LOFF2N 0x8

//-----------------------------------

static ECG_CommStatusType _initChip()
{
    uint8_t tempByte;

    _write_ecg_cmd(ECG_SDATAC);  // 4 tclk
    SysCtlDelay(100);
    // -----------------------------------------
    // RESET Command
    //  Our PWDN/RESET signal is provided \
    by HW(U15: TPS3836K33) 200 ms after power up
    //  However, since this can be called at anytime, \
    reset the chip via a cmd as well.
    //  Reset all registers to default values before changing anything.
    // -----------------------------------------
    _write_ecg_cmd(ECG_RESET);  // 9 x Fmod(module cycle,~128k,)
    // It takes 9xFmod cycles (70.3 uS) for the RESET cmd \
    to complete. >> FA Measure wait
                 // Wait added here for testing only.
                 SysCtlDelay(10000);



    // -----------------------------------------
    // Send STOP CONTINOUS Mode Command
    //    ADS1292R device wakes up in the continuous mode.
    //    We must stop the continuous mode so the registers can be written
    // -----------------------------------------
    _write_ecg_cmd(ECG_SDATAC);

    // Must wait 4xTclk cycles (31.25 uS) for the cmd to complete.
    // Wait 18 TClks (~8.8 uS given our 2.048 MHz clk)
    SysCtlDelay(100);

    // -----------------------------------------
    // Read the REG_ID
    // -----------------------------------------
    _read_ecg_reg(ECG_REG_ID, 1, &tempByte);
    if (tempByte != EXPECTED_ECG_ID)
    {
        return INVALID_DEVICE_ID;
    }
    SysCtlDelay(100);

    // -----------------------------------------
    // Write the CONFIG 1 register
    // -----------------------------------------
    _write_ecg_reg(ECG_REG_CONFIG1, ECG_CONFIG1_NORMAL);
    SysCtlDelay(100);

    _read_ecg_reg(ECG_REG_CONFIG1, 1, &tempByte);
    if (tempByte != ECG_CONFIG1_NORMAL)
    {
        return ECG_COMM_FAILED;
    }
    // -----------------------------------------
    // Write the CONFIG 2 register,ECG_CONFIG2_NORMAL,ECG_CONFIG2_TEST
    // -----------------------------------------
    _write_ecg_reg(ECG_REG_CONFIG2, ECG_CONFIG2_NORMAL);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_CONFIG2, 1, &tempByte);
    if (tempByte != ECG_CONFIG2_NORMAL)
    {
        return ECG_COMM_FAILED;
    }

    _write_ecg_reg(ECG_REG_LOFF, 0xF0);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_LOFF, 1, &tempByte);
    if (tempByte != 0xF0)
    {
        return ECG_COMM_FAILED;
    }

    // -----------------------------------------
    // Write the ECG_REG_LOFF_STAT register
    // Set the clock divider for 512k clock per sequence specification
    // -----------------------------------------


    _write_ecg_reg(ECG_REG_CH1SET, ECG_CHAN_SET_GAIN_4 | \
                   ECG_CHAN_SET_INPUT_NORMAL);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_CH1SET, 1, &tempByte);
    if (tempByte != (ECG_CHAN_SET_GAIN_4 | ECG_CHAN_SET_INPUT_NORMAL))
    {
        return ECG_COMM_FAILED;
    }

    _write_ecg_reg(ECG_REG_CH2SET, ECG_CHAN_SET_GAIN_4 | \
                   ECG_CHAN_SET_INPUT_NORMAL);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_CH2SET, 1, &tempByte);
    if (tempByte != (ECG_CHAN_SET_GAIN_4 | ECG_CHAN_SET_INPUT_NORMAL))
    {
        return ECG_COMM_FAILED;
    }

    _write_ecg_reg(ECG_REG_LOFF_SENS,
                   ECG_LOFF2N | ECG_LOFF2P | ECG_LOFF1N | ECG_LOFF1P);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_LOFF_SENS, 1, &tempByte);
    if (tempByte != (ECG_LOFF2N | ECG_LOFF2P | ECG_LOFF1N | ECG_LOFF1P))
    {
        return ECG_COMM_FAILED;
    }

    // -----------------------------------------
    // Configure RLD output related registers:
    // -----------------------------------------
    _write_ecg_reg(ECG_REG_RLD_SENS, RLD_SENS_USE_CH1_2);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_RLD_SENS, 1, &tempByte);
    if (tempByte != RLD_SENS_USE_CH1_2)
    {
        return ECG_COMM_FAILED;
    }

    // Configure Respiration Control ,no use Respiration,set default
    _write_ecg_reg(ECG_REG_RESP1, 0x02);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_RESP1, 1, &tempByte);
    if (tempByte != 0x02)
    {
        return ECG_COMM_FAILED;
    }

    _write_ecg_reg(ECG_REG_RESP2, RESP2_INTERNAL_REF);
    SysCtlDelay(100);
    _read_ecg_reg(ECG_REG_RESP2, 1, &tempByte);
    if (tempByte != RESP2_INTERNAL_REF)
    {
        return ECG_COMM_FAILED;
    }

    // -----------------------------------------

    SysCtlDelay(100);
    ECG_START(1);
    return ECG_COMM_SUCCESS;
}

//-------------------------
ECG_CommStatusType ECGReadData(int32_t *val)
{
#define ECG_READ_LEN 10
    bool result;
    uint8_t txBuff[ECG_READ_LEN];
    uint8_t rxBuff[ECG_READ_LEN];
    unsigned char byte0, byte1, byte2;
    SPI_Transaction ECG_SPI_Transaction;
    int32_t ECGCh1Data;
    int32_t ECGCh2Data;

    // static uint8_t ecgindex=0;

    txBuff[0] = ECG_RDATA;  // 1 byte cmd
    ECG_SPI_Transaction.count = ECG_READ_LEN;
    // Must read both channels even if discarding ch2.
    ECG_SPI_Transaction.txBuf = (Ptr) txBuff;
    ECG_SPI_Transaction.rxBuf = (Ptr) rxBuff;

    if (ECG_RDY())
    {
        ECG_CS(0);
        // SysCtlDelay(10);
        result = SPI_transfer(_h_spi, &ECG_SPI_Transaction);
        ECG_CS(1);
        if (!result)
        {
            return (SPI_XFER_FAILED);
        }

        // Byte 0 is not a valid response \
        since the cmd opcode hasn't yet been processed
        // First 3 response bytes are the ECG status as follows:\
        1100 + LOFF_STAT[4:0] + GPIO[1:0] + 13 0s.
        // Should always be: 0b1100,LLLL,LGG0,0000,0000,0000
        byte2 = rxBuff[1];  // MSB
        byte1 = rxBuff[2];
        byte0 = rxBuff[3];  // LSB
        ECGStatus = ((byte2 << 16) | (byte1 << 8) | byte0);

        byte2 = rxBuff[7];  // MSB
        byte1 = rxBuff[8];
        byte0 = rxBuff[9];  // LSB

        ECGCh2Data = 0;  // Init the data
        if (byte2 > 0x7F)
        {
            // Negative #
            ECGCh2Data = ((0xFF << 24) | (byte2 << 16) | (byte1 << 8) | byte0);
            ECGCh2Data = (~ECGCh2Data);
            ECGCh2Data += 1;
            ECGCh2Data = -ECGCh2Data;
        }
        else  // Positive #
            ECGCh2Data = ((byte2 << 16) | (byte1 << 8) | byte0);

        *val = ECGCh2Data;

        return (ECG_COMM_SUCCESS);
    }
    else
    {
        return (ECG_COMM_FAILED);
    }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Steven、

    感谢您发帖。  

    您用于读取数据的 SCLK 频率是多少? 根据您展示的图表、SPI 数据采集似乎存在一些问题。 数据输出的第一个4位应始终为0b1100以用于数据检索。 逻辑分析仪图中的第二个图显示了第2个字节上出现的0b1100、这与数据的外观不一致。

    我建议先查看有关 调试 ADS1292 SPI 的 E2E ADS129x 生物电势常见问题解答。 请参阅以下直接链接以供您参考。 请使用内部测试信号(CONFIG2[1:0]=11)进行 SPI 捕捉调试、并查看输出波形以查看是否得到方波。

    常见问题解答:ADS1292 SPI 调试

    谢谢

    -TC

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、TCT、

    感谢你的答复。

     我不理解第二个0b1100、  

    我使用连续模式进行测量。 然后发送'ECG_RDATA'、然后每5ms 读取72位(雕像、通道1/2)

    所以第一  个0b1100 xxxx (LOFF_STAT)应该是未使用的字节(它不是 LOFF_STAT)。

    或者、不发送 RDATA 命令的应直接读取72位数据(通过命令读取/读取数据)  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、TCT、

    在读取过程中、它似乎会发送垃圾数据、

    ECG_CommStatusType ECGReadData (Int32_t *值)

    #define ECG_READ_LEN 10.
    bool 结果;
    uint8_t txBuff[ECG_READ_LEN];
    uint8_t rxBuff[ECG_READ_LEN];
    unsigned char 字节0、字节1、字节2;
    SPI_Transaction ECG_SPI_Transaction;
    int32_t ECGCh1Data;
    int32_t ECGCh2Data;

    memset (txBuff、0、ECG_READ_LEN);//******* 清除 TX 缓冲区,仅发送 ECG_RDATA

    txBuff[0]= ECG_RDATA;// 1字节 cmd
    ECG_SPI_Transaction.count = ECG_READ_LEN;
    即使丢弃 CH2、//也必须读取两个通道。
    ECG_SPI_Transaction.txBuf =(ptr) txBuff;
    ECG_SPI_Transaction.rxBuf =(ptr) rxBuff;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Steven、

    对于连续读取数据模式(RDATAC)、无需发送 RDATA 命令即可检索数据。 有关“连续读取数据”和“读取数据”操作之间的差异,请参阅数据表中的第8.5.2.7和8.5.2.9节。

    谢谢

    -TC