/* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF); if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) {
DMA_Cmd(DMA_Channel2,ENABLE);
while(!DMA_GetFlagStatus(DMA_FLAG_TC2)) {
}
} } /* Get CRC bytes (not really needed by us, but required by MSD) */
MSD_ReadByte(); MSD_ReadByte();
/* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; DMA_Cmd(DMA_Channel2, DISABLE); /* MSD chip select high */ MSD_CS_HIGH();
/****************************************************************************** Description : Write byte in dma mode Fuctionname : WriteBlockInDMA(u8 *pBuffer,u32 WriteAddr, u16 NumByteToWrite) Input : pBuffer -- data buffer for send WriteAddr -- address to write NumByteToWrite -- data length of the data to write Output : None
/* Check if the MSD acknowledged the write block command: R1 response (0x00: no errors) */ if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Send a dummy byte */ MSD_WriteByte(DUMMY); /* Send the data token to signify the start of the data */ MSD_WriteByte(0xFE); /* Write the block data to MSD : write count data by block */ DMA_Cmd(DMA_Channel3, ENABLE); while(!DMA_GetFlagStatus(DMA_FLAG_TC3)); /* Put CRC bytes (not really needed by us, but required by MSD) */ MSD_ReadByte(); MSD_ReadByte(); /* Read data response */ if (MSD_GetDataResponse() == MSD_DATA_OK) { rvalue = MSD_RESPONSE_NO_ERROR; } }
/* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF); if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) {
使用DMA并不是为了获得速度,而是充分利用等待的空闲时间,所以我前面说再开启另一个DMA通道用于SPI的发送,发送的同时接收的DMA通道也在工作,完成数据的接收,不需CPU干预,CPU可完成其他任务。要说速度,我就算不用DMA,也照样可在约18026个CPU时钟周期内将512byte数据传到SD卡,或在17234(最快曾达到16401)个CPU时钟周期内将512byte数据从SD卡读到内存,此时速度约为512/(18026/72)=2.049(m/s)、512/(17234/72)=2.13(m/s),已非常接近2.25m/s的理论值。顺便说一下,SD卡的读写速度,除了与此处CPU与SD卡交换数据的速度有关外,还与以下2个操作密切相关: 读时: /* Now look for the data token to signify the start of the data */ if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) 写时: /* Read data response */ if (MSD_GetDataResponse() == MSD_DATA_OK) 此2操作花费的时间是惊人的,读时约需等10xxxCPU时钟,接近传512byte数据时间的2/3,写时约需等1xxxxx周期,是传512byte数据时间的10倍以上!仔细思考一下也是合理的,因写时会执行擦除操作,闪存的擦除时间是以ms计的。
楼上的说得很有道理,通过逻辑分析议抓数据后可以看到 /* Now look for the data token to signify the start of the data */ if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) 写时: /* Read data response */ if (MSD_GetDataResponse() == MSD_DATA_OK)确实占用较长的时间,不过接近读512字节的2/3时间还得看不同的卡,但是如果在dma开启后有dma控制器产生时钟信号好像很合理吧,因为放开速度不说,这样在dma开启后还得靠cpu发512字节的时钟信号,这样的操作好像并没有节省多少cpu时间,只有在开启dma后由dma控制器主动发时钟信号,这样在读512字节的数据时完全可以不用cpu来干预,因而才能真正地达到用cpu来处理其它任务的目的,不知道芯片设计的时候是怎么考虑的,当然如果存在其它编程算法而不是像12楼上那种方法来实现那到是有可能的?
SPI_DMACmd(SPI1, SPI_DMAReq_Rx, ENABLE); // DMA_ClearFlag(DMA_FLAG_TC2); /* Send CMD17 (MSD_READ_SINGLE_BLOCK) to read one block */
MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF); if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { /* Now look for the data token to signify the start of the data */
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ)) {