我一直在使用Teensy 3.6微控制器板(180 MHz ARM Cortex-M4处理器)来尝试实现传感器驱动程序。传感器通过SPI控制,当命令进行测量时,它将通过DOUT和PCLK两行发送数据。 PCLK是一个5 MHz时钟信号,并且在PCLK信号的下降沿上通过DOUT发送这些位。数据帧本身包含1,024个16位值。
我的第一次尝试是一个相对简单的方法:我在PCLK引脚上附加了一个中断,以寻找下降沿。当检测到下降沿时,它会将一个布尔值设置为有新位可用,并将另一个布尔值设置为DOUT线的值。程序的主循环从这些位生成uint_16值,并为整个测量帧收集这些值的1,024。
但是,该程序几乎立即锁定了Teensy。从我的实验来看,似乎在插入中断后立即将其锁定。我相信微处理器会被中断淹没。
我认为正确的方法是使用Teensy的DMA控制器。我一直在阅读Paul Stoffregen的DMAChannel库,但我听不懂。我需要从PCLK数字引脚触发DMA测量,并从DOUT数字引脚读取它的位。有人可以告诉我我是否以正确的方式看待这个问题?我是否正在忽略某些东西,应该查看哪些资源以更好地了解Teensy上的DMA?
谢谢!
我将其放在软件工程堆栈交换上是因为我认为这主要是编程问题,但是如果是EE问题,请随时将其移至EE SE。
最佳答案
DMA是在微处理器上接收高速数字数据的正确方法吗?
“高速数字数据”的来源不止一个。 DMA并不是针对所有数据的全局正确解决方案,但它可以是一种解决方案。
它通过DOUT和PCLK两行发送数据。 PCLK是一个5 MHz时钟信号,并且在PCLK信号的下降沿上通过DOUT发送这些位。
我在PCLK引脚上附加了一个中断,以寻找下降沿。当检测到下降沿时,它会将一个布尔值设置为有新位可用,并将另一个布尔值设置为DOUT线的值。
这种方法称为“位扑灭”。您正在使用CPU物理测量引脚。我看到许多经验丰富的开发人员都采用了最坏的解决方案。它可以与任何硬件连接一起使用。幸运的是,Kinetis K66具有一些外围设备,也许可以为您提供帮助。
具体来说,FTM,CMP,I2C,SPI和UART模块可能有用。这些硬件模块能够减少从处理每个位到一组位的工作量。例如,FTM支持捕获模式。这个想法是忽略PCLK信号,而只是测量边沿之间的时间。这些时间将固定在位周期/ CLK中。如果计时器捕获到一个两位周期,则说明已发送两个1或0。
同样,您的信号看起来像SSI,这是一个“数字音频”通道。不幸的是,K66没有SSI模块。典型的I2C是开漏的,并且始终具有起始位和固定的字长。如果您对数据有一定了解,并且/或者可以将电路附加到伪造一些位(稍后再删除),则可以使用此功能。
您可以使用UART和字符之间的时间来捕获数据。时间将不是起始位。但是,看起来该UART模块需要停止位(SIM功能可能非常有限)。
完成此操作后,即可在DMA,中断和轮询之间做出决定。如果CPU使用数据,则没有比轮询更快的速度了。如果需要将CPU与数据传输复用,则需要DMA和中断。如果CPU不需要对大多数数据进行操作,或者CPU所做的工作不占用大量内存(数字运算),则DMA会更好。中断取决于您的上下文,从而节省了开销。根据您的主线使用的设施,可以将其最小化。
某些使信号适应K66模块之一的胶合电路可能会大大有助于制定更有效的解决方案。如果您无法更改信号,则另一个带有SSI模块的(NXP?)SOC可以很好地工作。恩智浦模块通常支持链接到eDMA模块以及中断。
关于arduino - DMA是在微处理器上接收高速数字数据的正确方法吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45178655/