DSP论坛
直播中

jf_38841343

4年用户 3经验值
擅长:制造/封装
私信 关注

请问DSP28335怎么使用FIFO批量发送数据?

InitSpiaGpio_master();

spi_master_init();

Uint16 sdata[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};  // send data
Uint16 rdata[10];
Uint16 i;

for(i=0;i<10;i++)
{
    SpiaRegs.SPITXBUF = sdata[i];
}

SpiaRegs.SPIFFTX.bit.TXFIFO = 1;
while(SpiaRegs.SPIFFRX.bit.RXFFST != 10);
{

}

for(i=0;i<10;i++)
{
    rdata[i] = SpiaRegs.SPIRXBUF;
}
这个程序作为主机有问题吗?

回帖(1)

风尚男人

2025-10-29 18:24:59

您的程序存在几个关键问题,主要涉及FIFO的使用时序和配置。以下是详细分析和修正建议:


原程序问题分析:




  1. FIFO未正确初始化使能  



    • 在数据写入后才设置 SPIFFTX.bit.TXFIFO = 1,这会导致:

      • 前10次写入 SPITXBUF 时FIFO未生效(数据直接进入移位寄存器)

      • 批量发送功能未发挥作用





  2. 发送FIFO复位状态未处理  



    • FIFO默认处于复位状态(TXFFST 无法接收数据),需要清除重置标志




  3. 接收等待逻辑缺陷  



    • while(SpiaRegs.SPIFFRX.bit.RXFFST != 10) 存在风险:

      • 未处理接收超时或错误

      • 未考虑FIFO深度限制(28335的SPI FIFO深度为16)





  4. 读取方式效率低  



    • 未利用接收FIFO状态机,可能丢失数据






修正后的代码(主机模式):


#include "DSP2833x_Device.h"

void main(void)
{
    InitSysCtrl();
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();

    // 1. GPIO初始化
    InitSpiaGpio_master();  // 确保配置为SPI模式

    // 2. SPI主模式初始化
    spi_master_init();      // 配置时钟、极性等基本参数

    // 3. FIFO关键配置(必须在数据传输前设置!)
    SpiaRegs.SPIFFTX.all = 0xE040;  // 使能发送FIFO + 清除复位 + TX中断级别0
    SpiaRegs.SPIFFRX.all = 0x204F;  // 使能接收FIFO + 清除复位 + RXFFIL=15(几乎满中断)
    SpiaRegs.SPIFFCT.all = 0x0;     // 无延迟传输

    Uint16 sdata[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};
    Uint16 rdata[10] = {0};
    Uint16 i;

    // 4. 批量写入发送FIFO(检查FIFO剩余空间)
    for(i = 0; i < 10; i++)
    {
        // 等待发送FIFO有空间(深度16,TXFFST < 16)
        while(SpiaRegs.SPIFFTX.bit.TXFFST == 16) {}
        SpiaRegs.SPITXBUF = sdata[i];
    }

    // 5. 等待传输完成(发送FIFO空 + 移位寄存器空闲)
    while(SpiaRegs.SPIFFTX.bit.TXFFST != 0 || SpiaRegs.SPISTS.bit.BUFFULL_FLAG);

    // 6. 接收数据(检查接收FIFO计数)
    while(SpiaRegs.SPIFFRX.bit.RXFFST < 10) {}  // 等待10个数据到达

    for(i = 0; i < 10; i++)
    {
        rdata[i] = SpiaRegs.SPIRXBUF;  // 自动清除RXFFST标志
    }

    // 7. 可选:禁用FIFO恢复普通模式
    // SpiaRegs.SPIFFTX.bit.SPIFFEN = 0;
}



关键修改说明:




  1. FIFO初始化时序  


    SpiaRegs.SPIFFTX.all = 0xE040;  // 位15=1(使能FIFO), 位14=1(清除TX复位), 位8-7=00(中断阈值)
    SpiaRegs.SPIFFRX.all = 0x204F;  // 位15=1(使能FIFO), 位14=1(清除RX复位), 位8-0=0x4F(阈值)


    • 必须在数据传输前配置,否则FIFO功能不生效




  2. 发送数据时的等待机制  


    while(SpiaRegs.SPIFFTX.bit.TXFFST == 16) {} // 等待FIFO有空位


    • 防止FIFO溢出(深度=16)




  3. 传输完成判定  


    while(SpiaRegs.SPIFFTX.bit.TXFFST != 0 || SpiaRegs.SPISTS.bit.BUFFULL_FLAG);


    • 双重检查确保:

      • 发送FIFO完全清空

      • 移位寄存器最后一字节发送完成





  4. 接收优化  



    • 使用 RXFFST 状态位判断接收数量,避免忙等






补充建议:




  1. FIFO深度匹配  



    • 如果连续发送超过16字节,需分段发送:
      #define MAX_FIFO_DEPTH 16
      for(int seg=0; seg<10; seg+=MAX_FIFO_DEPTH){
      int len = (10-seg > MAX_FIFO_DEPTH) ? MAX_FIFO_DEPTH : 10-seg;
      // 填充当前段数据...
      }




  2. 错误处理

    增加超时检测防止死锁:


    Uint16 timeout = 0;
    while(SpiaRegs.SPIFFRX.bit.RXFFST < 10 && timeout++ < 1000) {}
    if(timeout >= 1000) { /* 错误处理 */ }



  3. 时钟配置验证

    确保 spi_master_init() 中波特率配置合理:


    SpiaRegs.SPIBRR = 63;  // 示例:LSPCLK=37.5MHz时, 波特率≈300Kbps



  4. 全双工注意事项  



    • SPI发送和接收同步进行,rdata 包含从机返回数据

    • 从机需配合主机时钟返回有效数据





? 重要提示:实际运行前需确认:



  1. 从机设备支持连续传输

  2. SPI时钟极性/相位匹配(CPOL/CPHA)

  3. GPIO复用引脚已配置为SPI功能



修正后的程序充分利用了28335的FIFO硬件加速机制,可实现高效批量传输。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分