主题中讨论的其他器件:ADS8910B、
我们使用 MSP432E401Y 连接 TI ADS8910B ADC、并尝试采样@ 1MSPS。 我们将 QSSI 与 ADS8910B 一起在四路数据模式下使用。 ADC CONVST 信号连接到 MSP432上的 PWM 引脚、运行周期为1us。 在每个转换周期后、我们都将硬件中断设置为该 PWM 信号的最高优先级、以便从 ADC 读取数据。
我们能够使 QSSI 接口在不使用 DMA 的情况下工作@ 500kSPS (2us PWM 间隔)。 然而、在1us 采样时、我们的时序变得更加关键、我们决定使用 UDMA 来处理来自 ADC 的 QSSI 数据传输。
从 ADS8910B 数据表中可以看出、在 CONVST 上升沿之前30ns 和之后20ns 的窗口中、数字信号无法切换。 这是 ADC 对输入信号进行采样的时间、在此期间切换的数字信号可能会将噪声耦合到正在进行的转换中。 由于这一要求、我们需要对 QSSI 数据传输发生的时间进行严格的时序控制。 请参阅下面的 SSI DMA 初始化和 PWM IRQ 处理程序代码以了解我们当前的实现:
void initSSIuDMA (void) { MAP_SysCtlPeripheralEnable (SYSCTL_Periph_UDMA); map_uDMAEnable(); map_uDMAControlBaseSet (pui8ControlTable); //从 udma_demo.c 中提取并仅针对 SSI2 RX 进行修改 MAP_SSIDMAEnable (SSI2_base、SSI_DMA_RX | SSI_DMA_TX); MAP_uDMAChannelAttributeDisable (UDMA_CH12_SSI2RX、 UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIOR| UDMA_ATTR_REQMASK); //启用以保持数据流动 MAP_uDMAChannelAttributeEnable (UDMA_CH12_SSI2RX、UDMA_ATTR_USEBURST); MAP_uDMAChannelControlSet (UDMA_CH12_SSI2RX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1 | UDMA_NEW_USEBURST); MAP_uDMAChannelTransferSet (UDMA_CH12_SSI2RX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、 (空*)(&SSI2->DR)、 Receive_data、3); MAP_uDMAChannelAttributeDisable (UDMA_CH13_SSI2TX、 UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIOR| UDMA_ATTR_REQMASK); //启用以保持数据流动 MAP_uDMAChannelAttributeEnable (UDMA_CH13_SSI2TX、UDMA_ATTR_USEBURST); MAP_uDMAChannelControlSet (UDMA_CH13_SSI2TX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1 | UDMA_NEW_USEBURST); MAP_uDMAChannelTransferSet (UDMA_CH13_SSI2TX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、 SEND_DATA、 (void *)(&SSI2->DR)、3); MAP_uDMAChannelAssign (UDMA_CH12_SSI2RX); MAP_uDMAChannelEnable (UDMA_CH12_SSI2RX); MAP_uDMAChannelAssign (UDMA_CH13_SSI2TX); MAP_uDMAChannelEnable (UDMA_CH13_SSI2TX); }
void PWM0_0_IRQHandler (UARg 参数) { // PWM 中的时序 INT:340ns // GPIOP->data |= 0x01; //获取中断状态 getIntStatus = HWREG (PWM0_ADDR + PWM_O_X_ISC); //清除 FSSHLD 以使 CS 无效 HWREG (SSI2_base + SSI_O_CR1)&=~(SSI_CR1_FSSHLDFRM); reads[buff ->writeIndex+]=(receive_data[2]<< 16)|(receive_data[1]<< 8)|(receive_data[0]); //以下行执行下面注释的 if 语句代码。 这可以在380ns 至340ns 范围内节省10%的时间 //参考:swrp146"使用 MSP432讲座进行软件设计" buff ->writeIndex =((((((((((()->size == buff ->writeIndex )<<31 )>> 31)&0)|((((((!(buff ->size == buff ->writeIndex )<<31 )>1)&buff ->writeIndex); // if (buff ->writeIndex>/) bux->writeIndex = 0; //} //为下一个事务重置 DMA pui8ControlTable[216]= 0x29;// TX pui8ControlTable[200]= 0x29;// RX HWREG (UDMA_ENASET)= 0x3000;//重新启用这两个 //清除中断 HWREG (PWM0_ADDR + PWM_O_X_ISC)= getIntStatus; //将 FSSHLD 设置为使整个数据传输帧的 CS 有效 HWREG (SSI2_base + SSI_O_CR1)|= SSI_CR1_FSSHLDFRM; // GPIOP->DATA &&~(0x01); }
在上述实现中、控制 QSSI 数据传输的时序时遇到问题。 请参阅以下示波器捕获、了解使用上述代码的 QSSI 信号的时序。 QSSI 数据传输发生在转换周期的末尾、切换过于接近下一个 CONVST 上升沿的开始、因此我们违反了 ADS8910B 规范。
在 PWM 中断中复位 DMA 后、QSSI 控制器和 DMA 控制器接管并完成数据传输。 我已经尝试移动中断内复位 DMA 的3行代码、但这并没有产生兼容的时序、 在最坏的情况下、如果我将复位移到中断处理程序的顶部附近、则某些转换周期不会发生数据传输。
我遇到的另一个问题是 CS 信号。 我们希望 CS 信号在传输开始时(当 CLK 开始切换时)置为低电平、并在传输完成后立即取消置为高电平。 当我们在没有 DMA 的情况下实现 QSSI 时、这不是一个问题、但是对于 DMA、我们一直很难让 CS 按照我们想要的方式运行。 当 FFSHLDFRM = 1时、CS 信号为恒定低电平。 当 FSSHLDFRM = 0时、CS 信号在传输的每个字节之间失效(参见下面的捕捉):
我们使用的权变措施是设置和清除 PWM 中断中的 FSSHLDFRM 位。 我在 FSSHLDFRM = 1的情况下尝试设置 SSICR1中的 EOM 位、但成功的机会有限、因为我不能完全确定 DMA 何时完成数据传输。
关于这个问题,我有两个主要问题:
- 是否有办法可以更好地控制使用 DMA 进行的 QSSI 数据传输?
- 是否有办法控制 CS 信号、以便在数据传输开始时将其置为低电平、并在数据传输结束后立即取消置位?
我们已经考虑过使用 QSSI 中断来判断数据传输何时完成、但我们的时序预算对于1us 采样非常严格、我认为我们没有足够的时序裕度来处理另一个中断。 PWM 中断的中断延迟+中断服务时间为700ns、不包括中断终止时间、因此 PWM 中断占用了70%以上的 CPU 时间。