芯源半导体CW32
直播中

wufan931111

11年用户 1240经验值
擅长:370217
私信 关注
[问答]

CW32F030 芯片 SPI DMA BULK发送问题,是什么原因导致的?

在CW32F030芯片上用SPI DMA发送,Block模式没有问题,可以调试出来,但是因为每个字节最后一位会插入一个大约60ns的时间,这个时间会导致数据出错。看到规格书有说BULK模式,但是我将代码设置成BULK模式之后,数据传输不成功,有时能传两个字节,有时一个字节也传不了。
SPI和DMA的初始化代码如下:
void SPI_Configuration(void)
{
    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly;         // 单工发送
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // 主机模式
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // 帧数据长度为8bit
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                            // 时钟空闲电平为低
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                          // 第一个边沿采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // 片选信号由SSI寄存器控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    // 波特率为PCLK的8分频        // 64 / 4 = 8Mhz
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // 最高有效位 MSB 收发在前
    SPI_InitStructure.SPI_Speed = SPI_Speed_High;                         // 高速SPI
    SPI_Init(CW_SPI1,  SPI_InitStructure);
    SPI_DMACmd(CW_SPI1, SPI_DMAReq_Tx, ENABLE);
    SPI_Cmd(CW_SPI1, ENABLE);
    // SPI_NSSInternalSoftwareConfig(CW_SPI1, SPI_NSSInternalSoft_Reset);
}

DMA_InitTypeDef DMA_InitStructure;
void DMA_Configuration(void)
{
    // 初始化SPI DMA TX
    DMA_InitStructure.DMA_Mode = DMA_MODE_BULK/* DMA_MODE_BLOCK */;
    DMA_InitStructure.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT;
    DMA_InitStructure.DMA_SrcInc = DMA_SrcAddress_Increase;
    DMA_InitStructure.DMA_DstInc = DMA_DstAddress_Fix;
    DMA_InitStructure.TrigMode = DMA_HardTrig/* DMA_SWTrig */;
    DMA_InitStructure.HardTrigSource = DMA_HardTrig_SPI1_TXBufferE/* DMA_HardTrig_GTIM1_OVERINT */;
    DMA_InitStructure.DMA_TransferCnt = SPI_TX_SIZE;
    DMA_InitStructure.DMA_SrcAddress = (uint32_t)TxBuffer1;
    DMA_InitStructure.DMA_DstAddress = (uint32_t) CW_SPI1->DR;
    DMA_Init(CW_DMACHANNEL2,  DMA_InitStructure);
    DMA_ClearITPendingBit(DMA_IT_ALL);
    DMA_ITConfig(CW_DMACHANNEL2, DMA_IT_TC | DMA_IT_TE, ENABLE);            // 使能DMA_CHANNEL1中断
    DMA_Cmd(CW_DMACHANNEL2, ENABLE);
}
发送过程是一个外部中断触发,定时器,在定时器中断中使能发送的:
void GTIM1_IRQHandlerCallBack(void)
{
    if (GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV)) {
        GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
        if (HSync > SCAN_UP_POS_START    HSync < SCAN_UP_POS_END) {
            CW_DMACHANNEL2->CSR |= DMA_CHANNEL_EN;
            // CW_DMACHANNEL2->TRIG |= DMA_SOFTTRIG_EN;
        }
    }
}

void GPIOA_IRQHandlerCallback(void)
{
    if (CW_GPIOA->ISR_f.PIN0) {     // 行同步
        GPIOA_INTFLAG_CLR(bv0);

            CW_GTIM1->CR0_f.EN  = ENABLE;
            CW_GPIOA->BRR |= GPIO_PIN_7;
  
                CW_DMACHANNEL2->SRCADDR = (uint32_t)(TxBuffer1);         // 重置目的地址
                CW_DMACHANNEL2->CNT = bv16 | SPI_TX_SIZE;                // 重置CNT计数
            // CW_DMACHANNEL2->CSR |= DMA_CHANNEL_EN;

    }
}
DMA打开发送完成中断和错误中断,能看到DMA发送完成了,但是SPI的MOSI上输出的波形不正确,接收端接受的数据也是错误的。
目前搞不清是什么原因导致的。

回帖(1)

笑尽往事

2025-11-28 18:13:21

在CW32F030芯片上使用SPI DMA的BULK模式传输失败,可能由以下原因导致:


1. BULK模式未正确使能



  • 关键点:BULK模式需要显式启用,仅靠SPI初始化参数不足。

  • 解决方法:在SPI初始化后添加使能BULK模式的代码:
     SPI_BulkModeCmd(SPI, ENABLE); // 启用BULK连续传输模式


2. DMA配置错误



  • 关键点:DMA配置必须严格匹配BULK模式要求:

    • 传输宽度对齐:确保SPI数据寄存器 (DR) 与内存的数据宽度一致(通常为8位)。

    • 传输长度匹配:DMA传输长度应等于实际数据长度(BULK模式依赖此值控制片选信号)。


  • 修正后的DMA配置示例
     DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI->DR); // 目标地址 = SPI数据寄存器
    DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)txBuffer;   // 源地址 = 内存数据数组
    DMA_InitStructure.DMA_BufferSize         = dataSize;             // 传输长度 = 数据字节数
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable; // 外设地址固定
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;      // 内存地址递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8位宽度
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;    // 8位宽度
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;            // 非循环模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
    DMA_Init(DMA_CHx, &DMA_InitStructure); // 初始化DMA通道(CHx需匹配SPI映射)
    SPI_DMACmd(SPI, SPI_DMAReq_Tx, ENABLE); // 使能SPI的DMA发送请求


3. 片选信号 (SSN) 冲突



  • 关键点:BULK模式要求硬件自动控制片选,但代码中启用了软件NSS (SPI_NSS_Soft) 且使能了硬件SSN控制 (SPI_SSNCmd),可能导致冲突。

  • 解决方法

    • 禁用软件NSS:改用硬件片选控制。

    • 修改SPI初始化
      SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; // 使用硬件NSS控制
      SPI_Init(SPI, &SPI_InitStructure);
      SPI_SSNCmd(SPI, ENABLE); // 确保硬件SSN使能(BULK模式必须)



4. SPI时钟配置与BULK模式冲突



  • 关键点:过高的SPI时钟频率可能导致BULK模式时序不稳定(尤其在分频系数较小如 SPI_BaudRatePrescaler_2 时)。

  • 解决方法

    • 暂时降低SPI时钟分频系数(如改为 SPI_BaudRatePrescaler_8)。

    • 验证问题是否消失,逐步调整至合适频率。



5. DMA传输未及时启动



  • 关键点:BULK模式需在DMA就绪后手动触发SPI传输。

  • 解决方法:在DMA使能后,向SPI数据寄存器写入一个字节启动传输:
     DMA_Cmd(DMA_CHx, ENABLE);   // 先使能DMA
    SPI->DR = 0x00;             // 写入DR寄存器,启动BULK传输(值不影响)


6. 中断干扰



  • 关键点:若启用DMA中断但未及时处理,可能导致传输卡死。

  • 解决方法

    • 检查中断服务函数是否正确清除标志。

    • 测试阶段可暂时关闭中断:
      DMA_ITConfig(DMA_CHx, DMA_IT_TC, DISABLE); // 禁用DMA传输完成中断





完整修复步骤:




  1. SPI配置修正


    void SPI_Configuration(void) {
    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; // 硬件NSS控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // 降低时钟测试
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_Init(SPI, &SPI_InitStructure);

    SPI_SSNCmd(SPI, ENABLE);     // 硬件SSN使能
    SPI_BulkModeCmd(SPI, ENABLE); // 关键!启用BULK模式
    SPI_Cmd(SPI, ENABLE);         // 最后使能SPI
    }


  2. DMA配置修正:确保数据宽度、长度、地址递增正确。

  3. 启动传输
    DMA_Cmd(DMA_CHx, ENABLE);   // 使能DMA
    SPI->DR = 0x00;             // 触发BULK传输


调试建议:



  • 用逻辑分析仪检查:

    • SCK/MOSI信号:观察是否输出完整数据。

    • SSN信号:BULK模式下应仅在传输开始时拉低、结束时拉高(单次脉冲)。


  • 检查DMA传输完成标志 (DMA_FLAG_TCx) 是否置位,确认传输是否被完整执行。


通过以上调整,BULK模式应能消除字节间的60ns间隙,实现连续稳定传输。如果问题仍存在,建议检查芯片勘误手册(Errata)中SPI-DMA相关的已知问题。

举报

更多回帖

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