本帖最后由 kokoromi 于 2017-6-23 13:10 编辑 SDIO和DMA的配置如下: 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; } 数据传输是使用 DMA方式的。现在的问题是,我读取 SD卡数据没问题,但是向 SD卡写入数据每次都提示 CRC错误,奇怪的是如果我关闭了硬件流控制,写入数据就正常了,这是怎么回事?有人遇到过这个问题吗? |
再加一个现象,时钟分频我原来设置的是 0,也就是说 SDIO_CK = 45M/(2+0) = 22.5M,我把分频设置为 1也是不好使,但是我把分频设置到 2或者大于2,发送数据就不会出CRC错了,一切正常了....
这是为什么?难道要使用硬件流控制 SDIO_CK的频率不能太高?感觉像ST芯片的硬件BUG。
评分
查看全部评分
或者是卡的速度跟不上。
评分
查看全部评分
不是F7,用的是F439。