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.
工具与软件:
专家、您好! 新年快乐!
我正在开发用于写入和读取外部 存储器的固件(MB85RS256B 是 FRAM、Fujitsu)。
为此、我很幸运地在这里找到了一个示例(代码的第4行有链接)。 我能够读取存储器 ID、就像最初实现的示例一样。
然后、我 将示例中的一个小标题更改为合并写入过程。 我想说它仍然可以工作(示波器看起来正常吗?)、但是 gRxPacket 变量(我的代码的第80行)始终为零。
请、有人能给我任何关于我做错了什么的提示吗?
#include "ti_msp_dl_config.h" /* Code example: e2e.ti.com/.../5551850 peripheral: MB85RS256B is a FRAM, Fujitsu */ #define SPI_PACKET_SIZE_TX (5) #define SPI_PACKET_SIZE_RX (2) /* Data for SPI to transmit */ uint8_t gTxPacket1[SPI_PACKET_SIZE_TX-2] = {0x03, 0x00, 0x00}; // read package uint8_t gTxPacket2[SPI_PACKET_SIZE_TX] = {0x02, 0x00, 0x00, 0xaa, 0xaa}; // write package /* Data received from SPI Peripheral */ volatile uint8_t gRxPacket[SPI_PACKET_SIZE_RX]; uint8_t gRxPacketTemp[SPI_PACKET_SIZE_TX]; // OP-CODES for the MB85RS256B uint8_t WREN = {0x06}; // 0000 0110 - Set Write Enable Latch uint8_t WRDI = {0x04}; // 0000 0100 - Reset Write Enable Latch uint8_t dummy = {0xFF}; // 1111 1111 - dummy byte uint8_t msb = 0; uint8_t lsb = 0; uint16_t myVal = 0; int main(void) { SYSCFG_DL_init(); DL_GPIO_clearPins(GPIO_PORT, GPIO_LED_1_PIN | GPIO_SEL_MUX_PIN | GPIO_EN_MUX_PIN); DL_GPIO_setPins(GPIO_PORT, GPIO_CS_SPI_PIN); delay_cycles(1000); DL_GPIO_clearPins(GPIO_PORT, GPIO_CS_SPI_PIN); DL_SPI_transmitDataBlocking8(SPI_0_INST, WREN); while (DL_SPI_isBusy(SPI_0_INST)); DL_GPIO_setPins(GPIO_PORT, GPIO_CS_SPI_PIN); DL_GPIO_clearPins(GPIO_PORT, GPIO_CS_SPI_PIN); // DL_SPI_fillTXFIFO8(SPI_0_INST, &gTxPacket2[0], SPI_PACKET_SIZE_TX); // it works as well, why? // Maximum FIFO size is 4 for (uint8_t i = 0; i < SPI_PACKET_SIZE_TX; i++) { while (DL_SPI_isTXFIFOFull(SPI_0_INST)) ; // Put data into fifo DL_SPI_fillTXFIFO8(SPI_0_INST, &gTxPacket2[i], 1); } /* Wait until all bytes have been transmitted and the TX FIFO is empty */ while (DL_SPI_isBusy(SPI_0_INST)); gRxPacketTemp[0] = DL_SPI_receiveDataBlocking8(SPI_0_INST); DL_GPIO_setPins(GPIO_PORT, GPIO_CS_SPI_PIN); DL_GPIO_clearPins(GPIO_PORT, GPIO_CS_SPI_PIN); /* Fill TX FIFO with data and transmit to SPI Peripheral */ DL_SPI_fillTXFIFO8(SPI_0_INST, &gTxPacket1[0], SPI_PACKET_SIZE_TX-2); /* Wait until all bytes have been transmitted and the TX FIFO is empty */ while (DL_SPI_isBusy(SPI_0_INST)); gRxPacketTemp[0] = DL_SPI_receiveDataBlocking8(SPI_0_INST); // Wait to receive the SPI data // This loop expects SPI_PACKET_SIZE bytes for (uint8_t i = 0; i < SPI_PACKET_SIZE_RX; i++) { DL_SPI_transmitDataBlocking8(SPI_0_INST, dummy); while (DL_SPI_isBusy(SPI_0_INST)); gRxPacket[i] = DL_SPI_receiveDataBlocking8(SPI_0_INST); } msb = gRxPacket[0]; lsb = gRxPacket[1]; myVal = (msb << 8) | lsb; DL_GPIO_setPins(GPIO_PORT, GPIO_CS_SPI_PIN); /*DL_GPIO_clearPins(GPIO_PORT, GPIO_CS_SPI_PIN); DL_SPI_transmitDataBlocking8(SPI_0_INST, WRDI); while (DL_SPI_isBusy(SPI_0_INST)); DL_GPIO_setPins(GPIO_PORT, GPIO_CS_SPI_PIN);*/ /* If write and read were successful, toggle LED */ while (1) { DL_GPIO_togglePins(GPIO_PORT, GPIO_LED_1_PIN); delay_cycles(16000000); } }
安德烈、您好!
您是否获取 gRxPacketTemp 的任何数据? 您会想到一个即时解决方案:使用 DL_SPI_receiveData8函数而不是 行80中的 DL_SPI_receiveDataBlocking8、然后查看是否会使它接收数据。
此致、
Diego Abad
尊敬的 Diego:
对于 gRxPacketTemp、我也有零。 我认为可以、因为我在示波器上看不到数据。
嗯,我按照你的建议更改了函数,但仍然为零:(
如果我转到函数 DL_SPI_receiveDataBlocking8的定义、它应该会返回"the data in the RX FIFO"。 如果我转到函数 DL_SPI_receiveData8的定义、它应该会返回"SPI->RXDATA"。 我在示波器上看到数据、为什么这些寄存器的值为零? 我知道、我缺少了一些东西、但我无法理解。
谢谢你!!!
Andrea
安德烈、您好!
这两个函数都返回 SPI->RXDATA (更多信息、请查看其在 dl_spi.c 中的定义)我的下一个建议是确保您的芯片选择对于代码的 SPI 接收传输部分正常工作(尝试仅隔离接收部分、看看它是否有效。)
如果您注意到 SPI 接收不起作用、我建议更新 CCS、SDK 和 SysConfig、并确保设置正确的硬件(我认为该解决方案的上述 E2E 主题部分是添加上拉电阻器。)
此致、
Diego Abad
嗨、Diego、
嗯、我执行了你建议的操作。 我注释掉了写入部分。 不幸的是、一切都基本相同、SPI->RXDATA 中没有数据。
然后、我决定增加 RX 缓冲区、我完成了 #define SPI_PACKET_SIZE_RX (4)和 ta—da! 数据位于位置2和3、而不是位于0和1 (附有屏幕截图)。 什么? 如何实现? 为什么?
请帮助我了解这里发生了什么!
感谢您的支持;)
安德烈、您好!
这很奇怪。 让我和我的团队谈谈这件事、我将在星期一让您回来。
此致、
Diego Abad
SPI 本质上是双向的。 对于您发送的每个 Tx 字节、您都会收到一个 Rx 字节。 即使您对 Rx 字节不感兴趣、也会出现这种情况。
如果您正在执行"Tx Only"操作(对任何 Rx Rx 字节都不感兴趣)、Rx 字节会收集到 Rx FIFO 中(最多4个)、因此、当您接下来执行一个"Tx Only"事务时、您需要先读取这些(过时)字节。 因此、跟踪 Rx FIFO 并根据需要将其清除非常重要。
对于短事务、我通常编写一个小函数、该函数写入 Tx 字节、然后立即读取相应的 Rx 字节;调用者可以自由使用或扔掉 Rx 字节、但我始终知道对应的信息。 在本例中、它可能看起来如下所示:
uint8_t spix(uint8_t c) { DL_SPI_transmitDataBlocking8(SPI_0_INST, c); c = DL_SPI_receiveDataBlocking8(SPI_0_INST); return(c); }
然后、您可以像这样使用它:
>(void) spix (WREN); //写入启用、忽略结果
或者
> gRxPacket[i]=spix (dummy);//发送虚拟字节、捕获结果
嗨、Bruce、
是的,在我最近的测试中,我怀疑第73行(我的代码)不能正常工作(清理 RX FIFO),然后我在该行和 ta 后面添加了一个 DL_SPI_DRAXFIFO8()! 它工作正常(随附屏幕截图)。 这与您的建议有点相关。
我正在使用 FIFO 函数来传输大于1字节的数据、可能我有错误的印象、那就是"安全快速的方式"。 我错了吗? 在 MSPM0手册的第1430和1431页上、我们很少介绍 FIFO 的相关信息。 请您澄清一下还是告诉我您对使用 DL_SPI_transmitDataBlocking8或 DL_SPI_fillTXFIFO8的看法? 也许我只需根据您的建议使用 DL_SPI_transmitDataBlocking8、而不是 FIFO。
谢谢你和迭戈的帮助。
Andrea
现在您已了解问题/解决方案、我不会告诉您改变您正在做的事情。
我的论文是,对于快速(低) SPI [*]上的短交易,FIFO 不会给你带来太多的收益,需要额外的记账。 我建议的函数避免了所有的记账(你所面临的真正问题),是"足够快",并且(我认为)使非常可读的代码。 但你的方式也是好的。
[*]对于较长的事务和/或缓慢的 SPI、我建议使用 DMA。