SDIO设置了硬件流控制发送数据就出现CRC错误,怎么解决?

2019-07-20 13:47发布

本帖最后由 kokoromi 于 2017-6-23 13:05 编辑

用 SDIO的时候配置如下:

[mw_shl_code=c,true]uint8_t BSP_SD_Init()
{
  uint8_t sd_state = 1;

  //设置 DMA2的流 3中断优先级并使能中断
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 15, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  //设置 SDIO传输时使用的 DMA流 3
  hDMA_SDIO_Tx.Instance = DMA2_Stream3;                             //设置 DMA2的流 3,用于发送数据到 SDIO
  hDMA_SDIO_Tx.Init.Channel = DMA_CHANNEL_4;                        //使用 通道 4
  hDMA_SDIO_Tx.Init.Direction = DMA_MEMORY_TO_PERIPH;               //传输方向为存储器到外设(SDIO)
  hDMA_SDIO_Tx.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址不变
  hDMA_SDIO_Tx.Init.MemInc = DMA_MINC_ENABLE;                       //存储器地址增加
  hDMA_SDIO_Tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;      //外设数据为字(字对齐)
  hDMA_SDIO_Tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;         //存储器数据为字节
  hDMA_SDIO_Tx.Init.Mode = DMA_PFCTRL;                              //流控制器为外设(SDIO)
  hDMA_SDIO_Tx.Init.Priority = DMA_PRIORITY_LOW;                    //传输优先级为低
  hDMA_SDIO_Tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;                 //使能 FIFO
  hDMA_SDIO_Tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;        //FIFO阈值为满
  hDMA_SDIO_Tx.Init.MemBurst = DMA_MBURST_INC16;                    //存储器为 16节拍单次突发传输
  hDMA_SDIO_Tx.Init.PeriphBurst = DMA_PBURST_INC4;                  //外设为 4节拍单次突发传输
  //初始化发送 DMA
  if(HAL_DMA_Init(&hDMA_SDIO_Tx) != HAL_OK) return 1;
  //链接 DMA到 SDIO
  __HAL_LINKDMA(&hSD, hdmatx, hDMA_SDIO_Tx);


  //设置 DMA2的流 6中断优先级并使能中断
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 15, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
  //设置 SDIO传输时使用的 DMA流 6
  hDMA_SDIO_Rx.Instance = DMA2_Stream6;                             //设置 DMA2的流 6,用于从 SDIO接收数据
  hDMA_SDIO_Rx.Init.Channel = DMA_CHANNEL_4;                        //使用通道 4
  hDMA_SDIO_Rx.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向为外设(SDIO)到存储器
  hDMA_SDIO_Rx.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址不变
  hDMA_SDIO_Rx.Init.MemInc = DMA_MINC_ENABLE;                       //存储器地址增加
  hDMA_SDIO_Rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;      //外设数据为字(字对齐)
  hDMA_SDIO_Rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;         //存储器数据为字节
  hDMA_SDIO_Rx.Init.Mode = DMA_PFCTRL;                              //流控制器为外设(SDIO)
  hDMA_SDIO_Rx.Init.Priority = DMA_PRIORITY_LOW;                    //传输优先级为低
  hDMA_SDIO_Rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;                 //使能 FIFO
  hDMA_SDIO_Rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;        //FIFO阈值为满
  hDMA_SDIO_Rx.Init.MemBurst = DMA_MBURST_INC16;                    //存储器为 16节拍单次突发传输
  hDMA_SDIO_Rx.Init.PeriphBurst = DMA_PBURST_INC4;                  //外设为 4节拍单次突发传输
  //初始化接收 DMA
  if(HAL_DMA_Init(&hDMA_SDIO_Rx) != HAL_OK) return 1;
  //链接 DMA到 SDIO
  __HAL_LINKDMA(&hSD, hdmarx, hDMA_SDIO_Rx);


  //配置 SDIO中断优先级为 14(必须高于 DMA2流 3和流 6,否则无法抢占 DMA2流中断,导致死锁)
  HAL_NVIC_SetPriority(SDIO_IRQn, 14, 0);
  HAL_NVIC_EnableIRQ(SDIO_IRQn);
  //设置 SDIO的初始化参数
  hSD.Instance = SDIO;                                              //指定 SDIO设备
  hSD.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;                      //上升沿有效
  hSD.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;                 //禁止旁路模式,使能时钟分频
  hSD.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE;           //使能节能模式
  hSD.Init.BusWide = SDIO_BUS_WIDE_1B;                              //设置 SDIO总线为 1位
  hSD.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; //使能 SDIO硬件流控制
  hSD.Init.ClockDiv = 0;                                            //时钟分频为 0,即 SDIO_CK = SDIOCLK/(2 + 0)
  //初始化 SD卡
  if(HAL_SD_Init(&hSD, &SDCardInfo) == SD_OK)
  {
    //使能 SD宽总线模式(4线)
    if(HAL_SD_WideBusOperation_Config(&hSD, SDIO_BUS_WIDE_4B) == SD_OK)
      sd_state = 0;
    else
      sd_state = 1;
  }

  return sd_state;
}[/mw_shl_code]



数据传输是使用 DMA方式的。现在的问题是,我读取 SD卡数据没问题,但是向 SD卡写入数据每次都提示 CRC错误,奇怪的是如果我关闭了硬件流控制,写入数据就正常了,这是怎么回事?有人遇到过这个问题吗?


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。