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.

[参考译文] ADS8691:输入1.6V或更高的正弦波电压时,转换值输出异常。

Guru**** 2563970 points
Other Parts Discussed in Thread: OPA141, ADS8691

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

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/616845/ads8691-abnormal-output-of-converted-value-when-inputting-sine-wave-voltage-of-about-1-6v-or-more

部件号:ADS8691
主题中讨论的其他部件:OPA141

尊敬的各位:  

我的最后一个问题在您的帮助下得到了解决。 再次感谢。

根据完成的代码执行ADC输入测试时,发现当输入具有特定电压(约1.6 V)或更高电压的正弦电压信号时,转换值异常。

但是,它可以对1.0V以下的输入信号进行稳定和准确的转换。


我的ADC的工作条件如下所示。

ADC的输入范围:±5.12V
信号源:功能发生器(输出阻抗:5欧姆)
信号源和ADC侧元件:5Hz二级HPF,带OPA141
采样:以每秒1.6384万 的速率采集4096次,采集时间为250毫秒。

转换后的值与设定的输入范围不匹配,并定期输出值0。

对示波器波形的分析显示,ADC输出的miso信号为零。

在这些症状中,是否有任何案例可归类为可能的问题或潜在故障?

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

    我会研究这个问题。 您是否能够分享您的原理图?

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

    尊敬的 Cynthia:  

    下面是ADC部件的示意图。  

    请注意,R13当前未插入。

    请提供您的电子邮件地址吗? 如果您告诉我,我可以提供更多信息。

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

    谢谢Young-Kyo,

    您的原理图看起来不错,我可以使用TINA模拟它,以确认电路工作正常。 但我需要您的信号接收频率来完成此操作。

    最有可能的是数字隔离器,它们会引入传播延迟,可能会中断您的ADC数字读数。
    下面 是两 个很好的TIDesign,说明如何使用隔离器并减轻其影响。

    http://www.ti.com/lit/ug/tiducm8a/tiducm8a.pdf

    http://www.ti.com/lit/ug/tidubj1/tidubj1.pdf

    此致

    Cynthia

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

    谢谢Cynthia,

    根据您的建议,我们将此问题的原因视为隔离器,并将其移除。

    拆除后,我直接连接到电线,如下图所示。



    然而,上述问题仍然被重复。

    仔细观察后,在大约2.0 V (几乎1.93 V)或更高的信号转换中再次出现该问题,并且在低于该值的信号下正常工作。

    有时,输入2.0V或更高的信号时,转换结果的峰值与输入电压相同,但仍出现一个没有SPI Miso信号的时间间隔。

    在其他观察中,即使输入高于2.0 V的任何级别的信号,转换结果的峰值也不会超过2.0 V。 此外,ADC的miso信号仍定期为零。

    此问题是否还有其他可能的原因?

    我认为ADC的重置过程或CONVST信号长度的问题是造成问题的另一个原因,但这并不清楚。

    此致

    永教

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


    我现在已经解决了这个问题,但我不知道我的解决办法是否合理。


    发生在我身上的ADS8691异常数据输出现象(当数据转换超过2V时,定期Miso信号变为0)未通过硬件修改解决。
    但是,我通过在固件级别修改ADC的操作顺序来解决了这个问题。

    以前,在MCU通电后,ADC的输入范围(0x14h,0x0003,±5.12V范围)设置的寄存器值在进入环路之前写入一次。

    然后,转换值通过SPI通信在信号采样的计时器中断内定期读取。 (采样率为每秒1.6384万 采样)

    上述代码流返回输入信号低于2.0V时正常转换的ADC值,但Miso信号会定期为上述电压信号返回0,或者无法执行正常的ADC转换。



    作为一种变通办法,我将ADC输入范围(0x14h,0x0003,±5.12V范围)的寄存器写入代码移至计时器中断内部。

    随后,将立即放置读取ADC转换值的代码。

    换言之,ADC输入范围的寄存器写入代码(仅执行一次)现在在计时器中断中的每个采样周期运行。

    修改后的代码配置现在为我提供了正常的ADC转换值。



    我不知道此修改后的代码流是否是合理的代码结构。

    可以理解的是,典型的ADC操作是在ADC初始化例程中的单寄存器设置之后的重复读取操作。

    但是,在这种导致正常操作的修改代码中,寄存器写入操作和ADC值读取操作在一个集中重复。

    我认为,通过中断例程内不必要的SPI通信进行寄存器写入操作,在MCU资源管理方面是不合理的。

    为了获得ADS8691操作的定期转换值,写入操作是否必须先于SPI读取操作?

    我需要你们专家的意见。


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

    这很有趣,因为您能够在工作中获得正确的读数,从而排除了硬件问题,并将软件编程作为问题的罪魁祸首。
    看到读取问题后,您是否能够在仅一次的循环中读取注册内容。 我要确认,寄存器已正确编程,并且仍保持编程状态。 如果不是,这可能解释为什么每次设备正常工作时都要通过循环重新编程。

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

    亲爱的Cynthia

    下面的代码是我测试的代码,它是在寄存器进入循环之前写入和读取寄存器的代码。

    我还在代码下面添加了示波器的屏幕截图。

    //===================================================================================================================== //

    定义Clear_HWORD 0x6000
    #define read_hWORD 0xC800
    #定义读取         0x4800
    #定义写入        0xD000
    #define write_ms   0xD200
    #define write_ls    0xD400
    #define set_hWORD 0xD800

    #define device_id_REG      0x02 //设备ID寄存器
    #define RST_PWRCTL_REG  0x04 //重置和电源控制寄存器
    #define SDI_CTL_REG        0x08 // SDI数据输入控制寄存器
    #define SDO_CTL_REG       0x0C // SDO-x数据输入控制寄存器
    #define DATAOUT_CTL_REG 0x10 //输出数据控制寄存器
    #define range_sel_REG   0x14 //输入范围选择控制寄存器
    #define alarm_REG         0x20 //警报输出寄存器
    #define alarm_H_TH_REG  0x24 //报警高阈值和滞后寄存器
    #define alarm_L_th_REG  0x28 //报警低阈值寄存器

    UINT16_t ADC_Command = 0;
    UINT32_t ADC_Result = 0;
    外部uint8_t TIM7_Flag;
    UINT8_t SPI1_ADC_RxBuffer[8]={0};
    UINT8_t SPI1_ADC_TxBuffer[8]={0};

    /*私有函数原型---------------------------------- */
    void SystemClock_Config(void);
    静态无效MX_NVIC_Init(void);

    内部主(无效)

    /* MCU配置---------------------------------- */

    /*重置所有外围设备,初始化闪存接口和Systick。 */
    HAL_Init();

    /*用户代码开始初始化*/

    /*用户代码End Init */

    /*配置系统时钟*/
    SystemClock_Config();

    /*用户代码begin sysinit */

    /*用户代码结束sysinit */

    /*初始化所有已配置的外围设备*/
    mx_gPIO_Init();

    HAL_GPIO_WritePin (GPIOA,GPIO PIN_4,GPIO PIN_RESET);// SPI1_NSS引脚转至低
    HAL_GPIO_WritePin (GPIOA,GPIO PIN_5,GPIO PIN_RESET);// SPI1_SCK引脚转至低
    HAL_GPIO_WritePin (ADC_RST_GPIO端口,ADC_RST_Pin,GPIO PIN重置);// ADC重置
    HAL_DELAY (100);
    HAL_GPIO_WritePin (ADC_RST_GPIO端口,ADC_RST_Pin,GPIO_PIN_SET);

    mx_DMA_Init();
    mx_SPI1_Init();// SPI_CS硬件控制
    mx_SPI4_Init();
    mx_TIM6_Init();
    mx_TIM7_Init();
    mx_USART1_UART_Init();

    /*初始化中断*/
    mx_NVIC_Init();

    HAL_TIM_Base_Start_IT (&htim7);//用于ADC采样

    /*用户代码开始2 */

    ////// 使用启用内部参考来设置ADC输入范围

    ADC_CONVST_CS();

    ADC_Command = WRITE + RANGE_SEL_REG;
    SPI1_ADC_TxBuffer[0]=(uint8_t)(ADC_Command >> 8);
    SPI1_ADC_TxBuffer[1]=(uint8_t)ADC_Command;
    SPI1_ADC_TxBuffer[2]= 0x00;
    SPI1_ADC_TxBuffer[3]= 0x03;//±1.25V * Vref和内部参考启用

    HAL_SPI_Transmit_DMA(&hspi1, SPI1_ADC_TxBuffer, 4);
    while (hspi1.State == HAL_SPI_STE_BUSY_TX);

    ADC_CONVST_CS();

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

    ////// 发送RANGE_SEL_REG的读取命令

    ADC_CONVST_CS();

    ADC_Command = READ_HEWORD + RANGE_SEL_REG
    SPI1_ADC_TxBuffer[0]=(uint8_t)(ADC_Command >> 8);
    SPI1_ADC_TxBuffer[1]=(uint8_t)ADC_Command;
    SPI1_ADC_TxBuffer[2]= 0x00
    SPI1_ADC_TxBuffer[3]= 0x00

    HAL_SPI_Transmit_DMA(&hspi1, SPI1_ADC_TxBuffer, 4);//发送半字读取命令
    while (hspi1.State == HAL_SPI_STE_BUSY_TX);//等待传输完成。

    ADC_CONVST_CS();

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

    ////// 从SPI帧读取(F+1)
    ADC_CONVST_CS();

    HAL_SPI_RECEIVE_DMA(&hspi1, SPI1_ADC_RxBuffer, 4);// SPI接收
    while (hspi1.State == HAL_SPI_STE_BUSY_RX);//等待接收完成。

    ADC_CONVST_CS();


    //============================================================================================================= //

    //用户代码....... //


    while (1){}

    }

    //=================================================================================================================================== //

    ①: 使用启用内部参考来设置ADC输入范围

    ②:  发送RANGE_SEL_REG的读取命令

    ③: 从SPI帧(F+1)读取

    我怀疑SCLK是在SCLK的第一部分从高变为低之后对ADC的输入。

    请检查此代码的流和信号输出是否正常,请告知我们您的意见。

    此致

    永教。

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

    您好Young-Kyo

    您是否会消除CS的双重脉冲?
    设备仍在转换时,您可能正在读取。 要查看是否发生了这种情况,还需探测RVS,并确保您在RVS仍显示其转换时没有阅读。 每次发送CS脉冲时,设备都会开始新的对话,因此,如果使用双脉冲,您无法在读取前为设备提供足够的时间来完成转换。


    此致,Cynthia

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

    您好Cynthia:  

    根据您的建议,我从之前的代码中删除了Double CS。


    此外,还通过示波器检查了RVS信号。


    在tconv_max之后,它似乎是正常的激活


    但是,ADC转换结果的异常输出仍在继续。


    在我仔细观察示波器波形时,我发现了一件奇怪的事情。

     
    在ADC的输入范围寄存器的写入操作中,当寄存器值被传输到ADC的14h地址时,将传输0x0003的值。 (请参阅上一篇文章中的代码)

    但是,在ADC输入范围寄存器的读取操作中,来自14h地址的值输出为0x3万。 (请参阅屏幕截图上方的图像)

    从ADC接收数据时是否发生字节交换?
    我不知道这些结果是否正常。

    此致。  

    永教。

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

    永教

    此设备没有字节交换。 最后一个屏幕截图显示了正确的信息。 SDO (miso)数据读取为3万。

    该代码显示您在编写x00h后接着编写x03h。  这将 有12个前导零和3h。 然后,设备添加16个滞后0以填充32位。 屏幕显示寄存器正在正确写入,并且也会读取正确的信息。 在数据表的第42页中,将对其进行进一步说明。

    我正在研究复制您的问题。到目前为止,您正在正确设置设备。  我相信 当设备看到范围突然变化时,它会被意外地重置,可能是代码中的某个位置。 由于您之前已进行了修改,因此需要处理ADC的重置过程或CS的长度(如果转换结束时CS保持在高位,则设备将进入NAP模式,这需要启用,因为默认情况下此模式不活动)。

    此致,

    Cynthia