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.

[参考译文] ADS8665:无需同步 CS 和 CLK 信号即可在固定周期获取样本

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

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/1531389/ads8665-getting-samples-at-fixed-period-without-needing-to-synchronize-cs-and-clk-signals

器件型号:ADS8665

工具/软件:

您好!

我正在使用 STM32 器件以 48kHz 采样速率从 ADS8665 读取音频应用的数据。 遗憾的是、STM32 SPI 硬件不提供 SPI 在固定周期内获取样本的功能。 尽管有、但我必须在没有 CPU 干预的情况下以 48kHz 的方式切换 CS 引脚。 我使用软件计时器中断来生成所需的 CS 信号并启动 SPI DMA 传输、这涉及 CPU、从而导致采样之间的时间周期不一致。 我最近使用 2 个不同的计时器解决了这一问题。

一个计时器以%20 占空比作为 48kHz PWM 生成 CS 信号。 其他计时器在触发模式下工作、当 CS 计时器触发时、该计时器会生成 16 个时钟脉冲。 我使用 STM32 SPI 作为从器件。 连接如下所示:
TIM CLK 信号:连接至 ADC CLK 和 STM32 SPI 从器件 CKL

TIM CS 信号:仅连接到 ADC CS

ADC SDO:已连接 SO STM32 SPI SDI

ADC SDI:始终为低电平

这样、我欺骗 STM32、好像一些主器件向它发送数据、而 ADC 就像主器件从它请求数据一样。 这样可以、但我需要 STM32 的高级计时器来提供正好 16-32 个时钟、如果 ADC 已经处理了这些时钟、则可以将其用于更复杂的任务。

我意识到 ADS8665 能够从 RVS 引脚提供计时器时钟、但我执行该 ADC 操作时遇到困难。 如果我使用它的内部时钟、RVS 引脚的时钟输出将非常高、以满足我的采样率需求、并且该内部时钟不可分频。 我想知道是否可以提供外部元件

48kHz 连续 CS 信号、占空比为 50%

占空比为 50%的 2MHz 连续 CLK 信号

ADC 从 SDO 输出样本、还从 RVS 提供 32 位时钟信号、以便我仍然可以通过将 RVS 连接到 STM SPI CLK 并将 ADC SDO 连接到 STM SDI 在循环 DMA 模式下使用 STM32 SPI?

如果无法实现、是否有办法在没有 CPU 干预的情况下获取 ADC 样本?

提前感谢!

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

    尊敬的 Cagri:

    欢迎来到我们的 e2e 论坛!  您提出的建议听起来像是使用 ADS8665 的可行选项。  我不知道以前有人尝试过、所以请让我知道它是如何工作的。

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

    当然! 我将分享如何使用 STM32 硬件计时器接收固定采样率。 但正如我所说、如果我能以某种方式将这项工作交给 ADS8665、那会很棒。 RVS 引脚上的当前 SPI 输出时钟频率非常高。 如果有任何方法可以减少它并保持数据和时钟同步、那就太棒了。  

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

    尊敬的 Cagri:

    向 SCLK 施加外部 2MHz 时钟时、这将是 RVS 时钟输出 — 请查看数据表中的第 7.5.4.2.3.1 节(第 46 页)。

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

    您好!

    如果您感兴趣、我找到了一种方法、可以使用配置为 SPI 从器件的 STM32 通过 ADS8665 ADC 实现周期性采样率、所有这些都没有 CPU 参与。 在此设置中、尽管 STM32 不是 SPI 主器件、但它基本上控制时序信号、将主器件行为模拟到来自 ADC 的位拆裂数据。 以下是我如何连接所有内容:

    我使用 TIM2 为 ADS8665 生成片选 (CS) 信号。 TIM2 不仅控制 CS 线路、还充当 TIM8 的触发源、TIM8 负责生成 SPI 时钟。 每次切换 CS 线路时、ADS8665 从其模拟输入捕获样本。 在 CS 激活后不久、触发 TIM8 以输出具有 16 个脉冲的 50%占空比 PWM、该脉冲用作 SPI 时钟信号。 下面是在 STM32CubeIDE 中配置它的方式:

    两个计时器都以 108MHz 运行、通过将该频率除以 2250、可以实现所需的 48kHz 采样率。 在 TIM2 中、通道 1 配置为在 225 个计时器计数后生成 CS 信号。 通道 4 未连接到任何物理输出时、在内部用于触发 TIM8。 其比较值设置为 725、以确保 TIM8 生成的时钟信号与有效 CS 状态中心对齐。 输出触发源配置为 OC4REF。

    TIM8 配置为从模式、其触发源设置为 ITR1 并将其链接到 TIM2。 请注意、不同 STM32 型号的触发器映射(如 ITR1)可能会有所不同、因此务必查阅参考手册以验证哪个计时器连接到哪个 ITR 输入。 TIM8 设置为 1 脉冲模式并配置为 16 重复计数器、因此每个触发器正好生成 16 个时钟脉冲。 时钟信号在通道 2 上以 864kHz 的频率输出。 对于 50%占空比、我将 PWM 脉冲宽度设置为 62、这是周期值 (125) 的一半。

    在 SPI 端、我将外设配置为仅接收从模式、数据大小为 16 位。 我启用了 DMA 和 NVIC 中断、并将 DMA 设置为具有半满阈值和半字(16 位)数据宽度的循环模式。

    有几个要点需要在代码中正确处理。

    1 — 您必须在 main.c 中的主计时器 (TIM2) 之前初始化从计时器 (TIM8) 这可确保正确同步并防止过早触发。

    int main(void)
    {
    
      /* MPU Configuration--------------------------------------------------------*/
      MPU_Config();
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
      MX_TIM8_Init();
      MX_TIM2_Init();
      /* USER CODE END SysInit */
      
      //rest of the initialization.....
    }

    2 — 用于 SPI 数据接收的 DMA 缓冲区必须正确地存储器对齐。 如果未对齐、数据可能会错位 1 个字节、这可能会导致不正确的读取、甚至缓冲区溢出。

    // This may not work
    struct {
    	volatile uint8_t a;
    	volatile uint8_t b;
    
    	uint8_t raw_buf[K * 2];
    } data_str;
    
    // This does work
    struct {
    	volatile uint8_t a;
    	volatile uint8_t b;
    
    	uint8_t raw_buf[K * 2] __ALIGNED(4);
    } data_str;

    为确保可靠启动、初始化序列非常重要。 您应该首先开始 SPI DMA 接收、然后启动从计时器 (TIM8)、最后启动主计时器 (TIM2)。 此顺序可确保在信号开始流动之前所有元件都准备就绪。

    void addaq_data_init() {
    	HAL_SPI_Receive_DMA(&hspi2, data_str.raw_buf, BUF_SIZ_BYTES * 2);
    	osDelay(1);
    	HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2);
    	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
    }

    在正确设置所有内容后、系统可以正常工作、这一点通过在逻辑分析仪上捕获的波形证实。

    如果您注意到第一个时钟脉冲出现得太早、这是因为 TIM2(主器件)在 TIM8(从器件)之前启动。 只需反转初始化顺序(在 TIM2 之前启动 TIM8)即可解决此问题。

    进行该调整后、我收到了预期的 ADC 值 0x7FE0(对应于 0x7FE = 2046)、从而确认数据正在正确写入原始 DMA 缓冲器。

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

    很酷!

    感谢您让我们知道!