SD SPI 发送命令 API 如下,所有实现代码参考附件。
/** * @brief Send 6 bytes command to the SD card. * @param Cmd: The command send to SD card. * @param argument: The command argument. * @param response_type: the SPI command response type. * @param *response: the SPI response returned. * @retval The SD Response. */ uint8_t ARC_sd_send_command(uint8_t cmd, uint32_t argument, SD_Response response_type, uint8_t *response) { int32_t i = 0; uint8_t crc = 0x01; int8_t response_length = 0; uint8_t tmp; uint8_t Frame[6];
if (cmd & 0x80) /* Send a CMD55 prior to ACMD<n> */ { cmd &= 0x7F; ARC_sd_send_command(SD_CMD_APP_CMD, 0, R1, response); if (response[0] > 0x1) { ARC_SD_CS_HIGH(); ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); return response[0]; } } ARC_SD_CS_LOW();
if(cmd == SD_CMD_GO_IDLE_STATE) crc = 0x95; if(cmd == SD_CMD_SEND_IF_COND) crc = 0x87; /* All data is sent MSB first, and MSb first */ /* cmd Format: cmd[7:6] : 01 cmd[5:0] : command */
Frame[0] = ((cmd & 0x3F) | 0x40); /*!< Construct byte 1 */
Frame[1] = (uint8_t)(argument >> 24); /*!< Construct byte 2 */
Frame[2] = (uint8_t)(argument >> 16); /*!< Construct byte 3 */
Frame[3] = (uint8_t)(argument >> 8); /*!< Construct byte 4 */
Frame[4] = (uint8_t)(argument); /*!< Construct byte 5 */
Frame[5] = (uint8_t)(crc); /*!< Construct CRC: byte 6 */
for (i = 0; i < 6; i++) { ARC_SPI_SendByte(SPI1, Frame); /*!< Send the Cmd bytes */ } switch (response_type) { case R1: case R1B: response_length = 1; break; case R2: response_length = 2; break; case R3: case R7: response_length = 5; break; default: break; } /* Wait for a response. A response can be recognized by the start bit (a zero) */ i = 0xFF; do { tmp = ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); }while ((tmp & 0x80) && --i);
response[0] = tmp; /* Just bail if we never got a response */ if (i == 0) { ARC_SD_CS_HIGH(); ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); return response[0]; }
if((response[0] & SD_ILLEGAL_COMMAND) == SD_ILLEGAL_COMMAND) { ARC_SD_CS_HIGH(); ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); return response[0]; }
i = 1; while(i < response_length) { tmp = ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); response = tmp; i++; } /* If the response is a "busy" type (R1B), then there's some * special handling that needs to be done. The card will * output a continuous stream of zeros, so the end of the BUSY * state is signaled by any nonzero response. The bus idles * high. */ if (response_type == R1B) { do { tmp = ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE);; }while (tmp != 0xFF);
ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); } ARC_SD_CS_HIGH(); ARC_SPI_SendByte(SPI1, SD_DUMMY_BYTE); return response[0]; } |