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:正确数据采集出现问题

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

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/1409608/ads1292r-problem-with-correct-data-acquisition

器件型号:ADS1292R
主题中讨论的其他器件: ADS1292

工具与软件:

您好、 Fellows、
我认为有一个新问题、我认为这是 SPI 中的时钟通信问题。

或许、可以帮我解决这个问题、下面我分享了使用数字分析仪观察过程中拍摄的一些图片。

通信似乎不同步、因此这些值未正确显示。 为了实现通信、我使用 SMCLK 和12MHz、该 SMCLK 源自时钟系统、频率为24MHz 的 MCLK。 通过这种方式 、SPI 时钟为500kHz。

有人可以帮我吗?

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

    您好 Armando:

    感谢您发帖。

    请查看  E2E 上的生物电势常见问题解答页面、了解有关 ADS1292R 的一些有用调试技巧。 500kHz SCLK 不是问题。 很难理解根据提供的图像在每帧中传达的内容。 我建议仅捕获一个或两个帧(即在寄存器读取或写入期间)并检查分析仪输出。

    此致、

    Ryan

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

    您好、Ryan、  

    感谢您的快速响应、我与您分享 一帧的捕获。  

    我阅读了所有常见问题解答、对我来说、代码中似乎存在 加电或  通信计时问题。 此外 、我共享用于与 AFE 进行通信的代码、该器件应在 AVDD = 3V 且 DVDD = 1.8V 的条件下工作

    main.c

    #include <msp432.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include "cs.h"
    #include "uart.h"
    #include "spi.h"
    #include "delay.h"
    #include "ads1292r.h"
    
    #define LOW         0x00
    #define HIGH        0x01
    
    uint32_t DCO_FREQ;
    
    uint8_t read_ADS1292R = 0;
    extern uint8_t SPI_TX_BUFF[SPI_TX_BUFF_SIZE];
    extern uint8_t SPI_RXBUFF[SPI_RXBUFF_SIZE], SPI_RX_COUNT, SPI_RX_EXP_COUNT;
    volatile bool ADS1292R_RECEIVED_DATA = false;
    unsigned long uecgTemp = 0;
    signed long secgTemp = 0;
    volatile signed long s32DaqVals[8];
    uint8_t DataPacket[16];
    uint8_t dataLength = 8;
    
    void sendString(char *str);
    void set_uart(void);
    void set_gpio(void);
    void processData(void);
    
    
    void main(void){
        WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
        uint16_t i;
    
        set_gpio();                                     /*INITIALIZE GPIO*/
        clockSystem(FREQ_24_MHz);                       /*INITIALIZE CLOCK SYSTEM*/
    
        set_uart();                                     /*INITIALIZE UART*/
        set_spi();                                      /*INITIALIZE SPI*/
        set_ads1292r();                                 /*INITIALIZE ADS1292R*/
    
    
        /*ENABLE GLOBAL INTERRUPT*/
    
        NVIC->ISER[1] = 1 << ((PORT2_IRQn) & 31);       /*ENABLE PORT2 INTERRUPT IN NVIC MODULE*/
        NVIC->ISER[0] = 1 << ((EUSCIB0_IRQn) & 31);     /*ENABLE EUSCI_B0 INTERRUPT IN NVIC MODULE*/
        __enable_irq();
    
    
        while(1){
    
            /*VERIFY IF PIN IS LOW*/
            while ((P2->IN & BIT3) == 0x00) {
                read_ADS1292R = true;
                //setDeviceOutBytes();
            }
            if(ADS1292R_RECEIVED_DATA == true){
    
            }
        }
    }
    
    

    ads1292.c

    uint8_t SPI_TX_BUFF[SPI_TX_BUFF_SIZE];
    uint8_t SPI_RXBUFF[SPI_RXBUFF_SIZE], SPI_RX_COUNT = 0, SPI_RX_EXP_COUNT = 0;
    long ADS1292_ECG_DATA_BUFFER[6];
    extern uint8_t read_ADS1292R;
    extern volatile bool ADS1292R_RECEIVED_DATA;
    static volatile uint8_t RX_Data = 0;
    
    void set_ads1292r(void) {
        drdy_interruptsADS();
        _delay(1, 's');
        resetADS();
        _delay(100, 'm');
    
        start_disableADS();                             // Set START pin to LOW
        start_enableADS();                              // Set START pin to HIGH
        start_disableADS();                             // Set START pin to LOW
    
        hard_stopADS();
        _delay(10, 'm');
        start_data_convertionCMD();
        soft_stopADS();
        _delay(50, 'm');
    
        /*READ DATA IN CONTINUOUS MODE IS THE DEVICE DEFAULT MODE*/
        /*THE DEVICE GOES TO THIS MODE ON POWER-UP, BY DEFAULT*/
        stop_read_dataContinuous();
        _delay(300, 'm');
        /*INITIATE REGISTERS*/
    
        read_regsADS(0x00);
        register_writeADS(ADS1292_REG_CONFIG1, 0x02);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_CONFIG2, 0xE8);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_LOFF, 0xF0);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_CH1SET, 0x00);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_CH2SET, 0x00);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_RLDSENS, 0xAC);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_LOFFSENS, 0x0F);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_RESP1, 0xEA);
        _delay(10, 'm');
        register_writeADS(ADS1292_REG_RESP2, 0x07);
        _delay(10, 'm');
        start_read_dataContinuous();
        _delay(10, 'm');
      //  start_enableADS();
    
    }
    
    void resetADS(void) {
        P2->OUT |= BIT6;      // Drive reset pin HIGH
        _delay(100, 'm');
        P2->OUT &= ~(BIT6);     // Drive reset pin LOW
        _delay(100, 'm');
        P2->OUT |= BIT6;      // Drive reset pin HIGH
        _delay(100, 'm');      // Hold reset for 17 milliseconds
    }
    
    void drdy_interruptsADS(void) {
        P2->DIR &= ~(BIT3);                             /*SET P2.3 DRDY TO INPUT*/
        P2->OUT &= ~(BIT3);
        P2->REN |=   BIT3;
        P2->SEL0&= ~(BIT3);
        P2->SEL1&= ~(BIT3);
    
        P2->IE  |= BIT3;
        P2->IES &= ~(BIT3);
        P2->IFG &= ~(BIT3);
    
    }
    
    void clock_selectADS(uint8_t clock_in) {
        if (clock_in == 1) {
            P2->OUT |= BIT4;  // Choose internal clock
        } else {
            P2->OUT &= ~(BIT4); // Choose external clock
        }
    }
    
    void start_enableADS(void) {
        P2->OUT |= BIT5;  // Set START pin HIGH
        _delay(20, 'm');  // Wait for 25 microseconds
    }
    
    void start_disableADS(void) {
        P2->OUT &= ~BIT5; // Set START pin LOW
        _delay(20, 'm');  // Wait for 17 microseconds
    }
    
    void chip_enableADS(void) {
        P3->OUT |= BIT0;  // Set CS pin HIGH
    }
    
    void chip_disableADS(void) {
        P3->OUT &= ~BIT0; // Set CS pin LOW
    }
    
    void hard_stopADS(void) {
        P2->OUT &= ~BIT5; // Set START pin LOW
        _delay(35, 'm');  // Wait for 35 milliseconds
    }
    
    void start_data_convertionCMD(void) {
        spi_transmit(START_);
    }
    
    void stop_read_dataContinuous(void) {
        spi_transmit(SDATAC);
    }
    
    void start_read_dataContinuous(void) {
        spi_transmit(RDATAC);
    }
    
    void soft_stopADS(void) {
        spi_transmit(STOP_);
    }
    
    static void spi_transmit(uint8_t data) {
        chip_disableADS();
        _delay(1, 'm');
        chip_enableADS();
        _delay(1, 'm');
        chip_disableADS();
    
        EUSCI_B0->TXBUF = data;
        while (EUSCI_B0->STATW & EUSCI_B_STATW_BBUSY);
    
        _delay(2, 'm');
        chip_enableADS();
    }
    
    static uint8_t spi_receive(void) {
        EUSCI_B0->TXBUF = 0x00; // Send dummy byte to receive data
        while (EUSCI_B0->STATW & EUSCI_B_STATW_BBUSY);
    
        return EUSCI_B0->RXBUF;
    }
    
    void register_writeADS(uint8_t WRITE_ADDRESS, uint8_t DATA) {
        // Apply bit masks based on register address
        switch (WRITE_ADDRESS) {
            case 1:
                DATA &= 0x87;
                break;
            case 2:
                DATA &= 0xFB;
                DATA |= 0x80;
                break;
            case 3:
                DATA &= 0xFD;
                DATA |= 0x10;
                break;
            case 7:
                DATA &= 0x3F;
                break;
            case 8:
                DATA &= 0x5F;
                break;
            case 9:
                DATA |= 0x02;
                break;
            case 10:
                DATA &= 0x87;
                DATA |= 0x01;
                break;
            case 11:
                DATA &= 0x0F;
                break;
            default:
                break;
        }
    
        SPI_TX_BUFF[0] = WRITE_ADDRESS | WREG;
        SPI_TX_BUFF[1] = 0;
        SPI_TX_BUFF[2] = DATA;
    
        chip_disableADS();
        _delay(1, 'm');
        chip_enableADS();
        _delay(1, 'm');
        chip_disableADS();
        _delay(1, 'm');
    
        // Transmit command
        spi_transmit(SPI_TX_BUFF[0]);
        spi_transmit(SPI_TX_BUFF[1]);
        spi_transmit(SPI_TX_BUFF[2]);
    }
    
    uint8_t read_regsADS(uint8_t READ_ADDRESS) {
        SPI_TX_BUFF[0] = READ_ADDRESS | RREG;
        SPI_TX_BUFF[1] = 0;
    
        chip_disableADS();
        _delay(1, 'm');
        chip_enableADS();
        _delay(1, 'm');
        chip_disableADS();
    
        spi_transmit(SPI_TX_BUFF[0]);
        spi_transmit(SPI_TX_BUFF[1]);
        /*RECEIVE THE RESPONSE*/
        uint8_t response = spi_receive();
        /*ENSURE THE CHIP IS ENABLED AFTER  TRANSACTION*/
        chip_enableADS();
    
        return response;
    }
    
    void EUSCIB0_IRQHandler(void) {
        if (EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG) {
            RX_Data = EUSCI_B0->RXBUF;
            if (read_ADS1292R == true) {
                printf("Waiting for 2...\n");
                SPI_RXBUFF[SPI_RX_COUNT++] = RX_Data; // Store data
    
                if (SPI_RX_COUNT > SPI_RX_EXP_COUNT) {
                    SPI_RX_COUNT = 0;
                    ADS1292R_RECEIVED_DATA = true; // Set flag to indicate data received
                    read_ADS1292R = false;
                }
            }
            /* Delay between transmissions for slave to process information */
            _delay(50,'u');
        }
    }
    
    void PORT2_IRQHandler(void) {
        if (P2->IFG & BIT3) {
            P2->IFG &= ~(BIT3); // Clear the interrupt flag
            SPI_RX_COUNT = 0;
    
            EUSCI_B0->TXBUF = 0; // Send dummy byte
            EUSCI_B0->IE |= EUSCI_B_IE_RXIE; // Re-enable RX interrupt
        }
    }
    
    void setDeviceOutBytes(void) {
        SPI_RX_EXP_COUNT = 9; // Set the expected byte count
    }
    

    SPI.c

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

    您好  Armando:

    ADS1292期望 CPOL = 0且 CPHA = 1、因此后沿用于采集数据。 逻辑分析仪捕获结果将前沿显示为捕获边沿。 请在您的逻辑分析仪和控制器设置中检查此配置。

    话虽如此、上图中的第一个字节似乎是向地址0x01发送 WREG 命令、但我看不到帧的其余部分(即 NCS 返回高电平时)。 您是否已成功写入寄存器配置并读回已配置的设置?

    另一个令人担忧的问题是 MISO 线路、它在高频率切换、比 SCLK 快得多。  请检查此连接。

    AVDD = 3V 和 DVDD = 1.8V 没有问题。

    此致、

    Ryan

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

    Ryan、您好!
    在微控制器论坛上的各位同事的帮助下、我取得了一些进展。
    现在我的 MISO 线似乎更好... 但读数的结果始终相同(0xFF)...

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

    尊敬的 Armando:

    是否有人将 PCB 上或通过 MCU 的 MISO 线路拉高?

    另外、请注意、WREG 命令0x41 0x02意味着您要写入3个连续的寄存器、从地址01h 开始。 在这两个字节之后、您需要跟随要写入每个地址的寄存器数据、所有这些都在同一个 SPI 帧中。 MISO 上的数据不会包含转换结果、直到:

    1. 完成器件寄存器写入并恢复 RDATAC 模式
    2. 将 START 拉为高电平或发送 START 命令

    此致、

    Ryan