0

我正在尝试为 AD7768-4 ADC 创建一个合适的 SPI 从接口。ADC 有一个 SPI 接口,但它不通过 SPI 输出转换。取而代之的是,数据输出在各个 GPIO 引脚上同步输出。所以我基本上需要bit-bang数据,并输出到SPI以获得正确的从属SPI接口。请不要问我为什么要这样做,它是分配给我的。

我遇到的问题是中断。我使用的是 STM32F767ZI 处理器——它以 216 MHz 运行,我的 ADC 数据必须以 20MHz 时钟输出。我已经设置了我的 NMI,但我没有看到系统调用或指向中断处理程序的位置。

我使用 STMCubeMX 软件分配引脚并生成设置代码,并在stm32F7xx.c文件中显示了该NMI_Handler()功能,但我在系统文件的任何地方都没有看到指向它的指针。我还在 中找到了 voidHAL_GPIO_EXTI_IRQHandler()函数STM32F7xx_hal_gpio.c,它似乎检查引脚是否已被断言,并清除任何未决位,但它没有重置中断标志,也没有检查它,我再次看到没有指向该函数的指针。

为了使事情更复杂,我有 10 个时钟周期来确定设置了哪个标志(一次两个标志中的一个),重置它,增加一个变量,并从 GPIO 寄存器移动数据。我相信这是可能的,但同样,一旦中断被触发,我就不确定系统在做什么。

有没有人有在这个处理器上处理外部中断的经验,可以阐明这个特定系统如何处理事情?再一次 - 10 个时钟周期来做我需要做的事情......移动数据应该只需要我 1-2 个时钟周期,让我 8 来处理中断......

编辑:

我们将 DCLK 速度更改为 5.12 MHz(20.48 MHz MCLK/4),因为在 2.56 MHz 时,我们正好有 12.5 微秒的时间来输出数据并为下一个 DRDY 脉冲进行设置,而 80 kHz 的速度正好为我们提供了零余量。在 5.12 MHz 时,我有 41 个时钟周期来运行中断例程,如果我跳过检查第二个标志而只处理传入数据,我可以稍微减少它。但我觉得我至少必须使用 DRDY 标志检查,并使用例程启用第二个中断,否则我将不断中断,因为 ADC 上的 DCLK 一直在运行。这让我有 6.12 微秒的时间来读取数据,并在下一个 DRDY 脉冲之前有 6.25 微秒的时间将其洗牌。我应该能够在 32 MHz SPI 时钟(从属)下做到这一点,但很可能会在 50 MHz 下做到这一点。这是我当前的中断代码:

void NMI_Handler(void)
{
    if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)         
     {
         count = 0;                                             
         __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);                  
         HAL_GPIO_EXTI_Callback(GPIO_PIN_0);                        
         //     __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);             

         HAL_NVIC_EnableIRQ(GPIO_PIN_1);                            
     }  
    else
  {  
        if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_1) != RESET)         
          {
             data_pad[count] = GPIOF->IDR;                      
             count++;                                           
             if (count == 31)
              {
                data_send = !data_send;                     
                HAL_NVIC_DisableIRQ(GPIO_PIN_1);            
              }
        __  HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);         
        HAL_GPIO_EXTI_Callback(GPIO_PIN_1); 
//      __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0); 
          }
   }
}  

我仍然担心时钟周期,如果我假设唯一会触发的其他 EXTI 标志是时钟引脚,我相信我可以只检查 DRDY 标志。虽然我质疑如果 SYS_TICK 在后台运行这将如何工作......我必须找出答案。

我们正在研究一种更快的处理器来处理位碰撞,但现在,如果 PI3 运行 Linux,它看起来将无法处理它,而且我不知道有太多更快的处理器运行非常小的可靠 RTOS,或者可以在紧要关头进行裸机编程......

4

3 回答 3

3

10 个时钟周期来做我需要做的事情......移动数据应该只需要我 1-2 个时钟周期,让我 8 来处理中断......

没门。即使在 Cortex-M7 上,中断入口(推送寄存器、获取向量和填充流水线)也需要 10-12 个周期。然后考虑一个非常简单的中断处理程序,只需将输入数据位移动到缓冲区并清除中断标志:

uint32_t *p;
void handler(void) {
    *p++ = GPIOA->IDR;
    EXTI->PR = 0x10;
}

它被翻译成这样的东西

handler:
    ldr     r0, .addr_of_idr // load &GPIOA->IDR
    ldr     r1, [r0]         // load GPIOA->IDR
    ldr     r2, .addr_ofr_p  // load &p
    ldr     r3, [r2]         // load p
    str     r1, [r3]         // store the value from IDR to *p
    adds    r3, r3, #4       // increment p
    str     r3, [r2]         // store p
    ldr     r0, .addr_of_pr  // load &EXTI->PR
    movs    r1, #0x10
    str     r1, [r0]         // store 0x10 to EXTI->PR
    bx      lr
.addr_of_p:
    .word   p
.addr_of_idr
    .word   0x40020010
.addr_of_pr
    .word   0x40013C14

所以它是 11 条指令,每条指令至少需要一个周期,中断进入之后。这是假设代码、向量表和堆栈都在最快的 RAM 区域中。我不确定文字池是否在 ITCM 中工作,使用立即文字会增加 3 个周期。忘了它。

这必须通过硬件来解决。

控制器有 6 个 SPI 接口,选择其中 4 个。连接DRDY到所有四个NSS引脚,连接到DCLK所有SCK引脚,并且每个DOUT引脚连接到一个MISO引脚。现在每个 SPI 接口处理一个通道,并且可以在其内部 FIFO 中收集多达 32 位。

NSS然后我会在其中一个引脚的上升沿设置中断(EXTI即使引脚处于备用功能模式仍然有效),并立即读取所有数据。

编辑

NSS事实证明,STM32 SPI 需要在下降和上升之间有过多的延迟SCK,而 AD7768 不提供,因此它无法工作。

Sigma-Delta 接口

STM32F767 有一个 DFSDM 外设,设计用于从外部 ADC 接收数据。它可以接收多达 8 个 20 MHz 的串行数据通道,它甚至可以执行您的应用程序可能需要的一些预处理。

问题是 DFSDM 没有DRDY输入,我不知道如何同步数据传输。它可以通过断言START#信号来重置通信来工作。

如果这不起作用,那么您可以尝试使用计时器和 DMA 启动 DFSDM 通道。连接DRDYTIM1or的外部触发器TIM8(其他定时器不起作用,因为它们连接到较慢的 APB1 总线和另一个 DMA 控制器),在 的上升沿启动它ETR,并让它在 ~20 ns 后生成一个 DMA 请求. 然后让 DMA 将启动通道所需的值写入 DFSDM 通道配置寄存器。对其他三个通道重复此操作。

于 2018-11-14T21:59:18.363 回答
0

在编译之前会生成一个启动文件:startup_stm32f767xx.s- 其中包含所有指向函数的指针。

标记g_pfnVectors:下方 .word NMI_Handler指向一个用于处理非屏蔽中断的函数,以及另外两个指针,.word EXTI0_IRQHandler.word EXTI1_IRQHandler作为指向外部中断处理程序的向量。在同一个文件的更下方,是以下编译器指令:

.weak      NMI_Handler  
.thumb_set NMI_Handler,Default_Handler

.weak      EXTI0_IRQHandler         
.thumb_set EXTI0_IRQHandler,Default_Handler

.weak      EXTI1_IRQHandler         
.thumb_set EXTI1_IRQHandler,Default_Handler  

这是我正在寻找能够以更精确和更少时钟周期控制我的中断的信息。

于 2018-11-14T15:57:49.480 回答
0

我仔细阅读了AD7768 DS,发现它可以将四个通道的数据发送到一个DOUT引脚。所以,我再次谈论串行音频接口(SAI)。

如果您可以将DCLK频率降低到 2.5MHz,而不是在完整的 ADC 时钟下以 1:8 的比率(比率为 2.5MHz 到 20MHz)降低采样率,则可以降低采样率。

如果您将所有 4 个通道路由到一个输出 DOUT0,您会以 1:4 的比例降低采样率。

AD7768-4 DS

第 53 页

在 AD7768 上,该接口可配置为在一个、两个或八个 DOUTx 引脚上输出转换数据。AD7768 的 DOUTx 配置是使用 FORMATx 引脚选择的(见表 33)。

第 66 页表 34:(对于 AD7768-4)第 67 页图 98:

FORMAT0 = 1所有通道在 DOUT0 引脚上输出,在 TDM 输出中。只有 DOUT0 正在使用。

您可以使用SAI=FSDRDY四个插槽,32 位/插槽

于 2018-11-16T20:27:14.650 回答