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); } }
尊敬的 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 (附有屏幕截图)。 什么? 如何实现? 为什么?
请帮助我了解这里发生了什么!
感谢您的支持;)
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