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.
您好!
我正在学习该 TI 微控制器的工作原理、在 尝试设置 SPI 通信时、我在理解 FIFO 功能如何工作时遇到问题。
我将连接 Launchpad 的2个 SPI 接口、并想使用 FIFO 中断从主器件(控制器)传输一个由8个 uint16_t 类型元素组成的数组(外设)。 我的配置和代码如下(我使用的是 SysConfig):
// Included Files /************************************************************************/ #include "driverlib.h" #include "device.h" #include "board.h" #include "c2000ware_libraries.h" /******************************************************************************************/ // Defines /*******************************************************************************/ /******************************************************************************************/ // Prototypes /****************************************************************************/ __interrupt void INT_mySPI0_TX_ISR(); __interrupt void INT_mySPI1_RX_ISR(); __interrupt void INT_mySPI0_RX_ISR(); __interrupt void INT_mySPI1_TX_ISR(); /******************************************************************************************/ // Global Variables /**********************************************************************/ uint16_t dim = 8; uint16_t rx_B[8]; uint16_t tx_A[8]; uint16_t tracker = 0; /******************************************************************************************/ // Main /**********************************************************************************/ void main(void) { // Local Variable uint16_t i; // Initialization of data for(i = 0; i < dim; i++) { tx_A[i] = i; rx_B[i]= 0; } // Initialize device clock and peripherals Device_init(); // Initialize PIE and clear PIE registers. Disables CPU interrupts. Interrupt_initModule(); // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). Interrupt_initVectorTable(); // PinMux and Peripheral Initialization Board_init(); // Enable Global Interrupt (INTM) and real time interrupt (DBGM) EINT; ERTM; // Infinite Loop while(1) { } } /******************************************************************************************/ // Interrupts /****************************************************************************/ __interrupt void INT_mySPI0_TX_ISR(){ // Local Variable uint16_t i; // TX for(i=0;i<dim;i++){ SPI_writeDataBlockingFIFO(mySPI0_BASE, tx_A[i]); } // Update Data for(i=0;i<dim;i++){ tx_A[i] += 1; } // Clear Interrupt SPI_clearInterruptStatus(mySPI0_BASE, SPI_INT_TXFF); Interrupt_clearACKGroup(INT_mySPI0_TX_INTERRUPT_ACK_GROUP); } __interrupt void INT_mySPI1_RX_ISR(){ // Local Variable uint16_t i; // TX for(i=0;i<dim;i++){ rx_B[i] = SPI_readDataBlockingFIFO(mySPI1_BASE); } // Check for(i=0;i<dim;i++){ if(rx_B[i] != (tracker + i)){ ESTOP0; } } // Update tracker tracker ++; // Clear Interrupt SPI_clearInterruptStatus(mySPI1_BASE, SPI_INT_RXFF); Interrupt_clearACKGroup(INT_mySPI1_RX_INTERRUPT_ACK_GROUP); } __interrupt void INT_mySPI1_TX_ISR(){ } __interrupt void INT_mySPI0_RX_ISR(){ } /******************************************************************************************/ // End of File
我希望代码已清除(在某种程度上遵循示例 spi_ex4 drivelib 示例)。 我将调用 TX ISR、在这里我使用命令 WriteDataBlockingFIFO 写入所有数据、然后在传输之后、通过缓冲器的每个元素进行更新。 然后在 RX ISR 中、我想读取我发送的所有数据(使用 ReadDataBlockingFIFO)并将其保存在与我发送的数据尺寸相同的数组中、然后我使用"tracker"变量检查我接收到的元素是否为预期的元素。
我设置的比特率为10MHz 是因为我还要为未来的项目实现快速通信。
(中断 ISR 的名称紧跟在最后一个镜像中的第一个名称之后)
我期望中断按如下方式触发:
-当 TX FIFO 中有8/16个位置被占用时、就会触发 TX ISR、因为我 将 SPI0 (控制器)"Transmitt Interrrupt Level"设置为"8/16 FIFO";
-当 RX FIFO 中的8/16个位置空闲时、就会触发 RX ISR、因为 我 将 SPI1 (外设)在"8/16 FIFO"上设置为"接收中断级别"。
当我调试时得到的结果是、在 RX ISR 生效时、只有 TX ISR 被触发。 我已经阅读了 SPI 的参考手册部分、但我不知道我的操作哪里有问题。 我附加了调试视图图片:
我不知道我是否误解了中断的调用方式、也不知道我在代码中使用的读取和写入函数、甚至只是协议的代码流。 您能帮助我理解我哪里出了问题以及 FIFO 缓冲区的工作原理吗?
提前感谢您 。
此致、
Edoardo
Edoardo,
我假设您要尝试让同一器件内的 SPIA 和 SPIB 彼此通信。 对吧?
如果是、这正是 spi_ex4_external_loopback_fifo_interrupts 代码的作用? 您是否能够在 launchpad 中使用此示例代码? 如果没有、这将是第一步。 只要您对示例有充分的了解、就可以根据您的要求修改代码。
此致、
Manoj
尊敬的 Manoj:
是的、假设正确、我希望使同一设备的两个接口进行通信。 我还能够得到 您提到的示例、从而发挥作用、我想我理解它。 不过、我有一个问题、我想请您检查我是否正确理解了所有内容:
1) FIFO 能够包含最多16个元素、最多16位(这应该是您在 SysConfig 中配置的数据宽度)。 因此、根据您需要传输的数据数量、您可以相应地设置 FIFO 中断级别。 考虑一个 n 维的 uint16数组: 对于传输、中断级别必须设置为(16 - n) 、这意味着 当 TX_FIFO (n)被占用并且(16 - n)空闲时调用 TX 中断。 对于接收、必须将电平设置为(n)、这意味着当 RX_FIFO (array_dimension)空闲时调用 RX 中断、而其余的位置仍然可以从之前的传输中占用。 我是对吗?
2)根据前一个点、这意味着 SPI 能够在单个 FIFO 中断传输中发送最多16个16位元素的逐位数据包、或者可以发送更多的元素(例如、一个由64个元素组成的 uint16数组)?
3) 3)"非阻塞"和"BlockingFIFO"函数之间的区别是、在第一种情况下、数据在 SPITXBUF/SPITXBUF 中写入/读取、而在另一种情况下在 FIFOTXBUF/FIFORXBUF 中写入/读取?
另外、 我想说的是、我发现如果 降低比特率、我设置的通信将正常工作。 问题在于、在这种情况下、我可以达到的比特率最大值是1MHz、而我想改用10MHz 比特率通信、原则上应该是可行的。 你是否知道为什么我在达到那个速度时遇到了问题? 可能是因为我连接了同一电路板的2个 SPI?
提前感谢您。
此致、
Edoardo
此外, 我想说的是,我发现如果 降低比特率,我设置的通信将正常工作。 问题在于、在这种情况下、我可以达到的比特率最大值是1MHz、而我想改用10MHz 比特率通信、原则上应该是可行的。 你是否知道为什么我在达到那个速度时遇到了问题? 可能是因为我连接了同一电路板的2个 SPI? [/报价]您的 LSPCLK 速度是多少?
尊敬的 Manoj:
这里是我的时钟树的图片。 LSPCLK 设置为100MHz、并且我也激活了"器件支持"功能、如上图所示。
我还想补充一点、如果我 使用示波器查看控制器或外设板上的 SPICLK 引脚、我可以有效地看到10MHz 的波形。 最后、在第一篇文章的最后一张图片中、我想知道只有 TX_A 变量会更新这一事实是否是调试器可视化问题。
谢谢你。
此致、
Edoardo
Edoardo,
您是否能够在@ 10MHz 的频率下发送/接收16个字节的数据而不会出现任何问题? 您之前发表的文章建议您这样做。
此致、
Manoj
尊敬的 Manoj:
最后、从示波器上看、似乎是这样。 然而、在调试器中看不到接收到的数据变量的任何变化、这仍然使我对是否真正接收数据产生疑问。 您是否认为调试器由于高比特率而无法显示接收到的数据? 或者这可能是另一个原因吗?
提前感谢您。
此致、
Edoardo
Edaordo、
您观察的似乎是 SPICLK 信号。 观察总线中的所有 SPI 信号。
此致、
Manoj
尊敬的 Manoj:
是的、我可以看到一些数据、这些数据看起来是正确的、因此在这种情况下、调试器可能无法保持通信的速度。
感谢您的支持。
此致、
Edoardo
您能否确认您是否在 SPI RX 缓冲区中接收到数据?
尊敬的 Manoj:
我可以看到该缓冲区中的数据、但与实际传输相比、SPIRXBUFF 的更新似乎非常慢、并且我确实可以看到它的值变化非常缓慢。 不过,我认为是可行的。
我会告诉您我何时能够更好地将我的下一个项目中的数据可视化。
非常感谢您的帮助。
祝你度过美好的一天。
此致、
Edoardo
在10MHz 时、高速填满 RX 缓冲器。 CCS 中的刷新率比 RX 缓冲区填充率慢很多。 正确的数据、RX 缓冲区就会变得非常高。 这才是最重要的。
我现在将关闭此主题。
此致、
Manoj