生成SPI驱动的SD卡的代码
时间: 2023-07-10 09:03:18 浏览: 160
STM32-SPI方式驱动SD卡,包含标准库、HAL库、LL库三种另加HAL库的FATFS代码,共4个工程
5星 · 资源好评率100%
以下是一个基本的SPI驱动程序,可用于SD卡的读/写:
```c
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "driver/spi_master.h"
#include "driver/gpio.h"
// SPI总线的引脚定义
#define PIN_NUM_MISO 25 // MasterIn SlaveOut
#define PIN_NUM_MOSI 23 // MasterOut SlaveIn
#define PIN_NUM_CLK 19 // 时钟
#define PIN_NUM_CS 22 // 片选
// SD卡命令定义
#define CMD_GO_IDLE_STATE 0x00
#define CMD_SEND_OP_COND 0x01
#define CMD_SEND_IF_COND 0x08
#define CMD_SEND_CSD 0x09
#define CMD_SEND_CID 0x0A
#define CMD_STOP_TRANSMISSION 0x0C
#define CMD_SEND_STATUS 0x0D
#define CMD_SET_BLOCKLEN 0x10
#define CMD_READ_SINGLE_BLOCK 0x11
#define CMD_WRITE_BLOCK 0x18
#define CMD_APP_CMD 0x37
#define CMD_READ_OCR 0x3A
// SD卡响应标志定义
#define R1_IDLE_STATE 0x01
#define R1_ILLEGAL_COMMAND 0x04
#define R1_CRC_ERROR 0x08
#define R1_ERASE_SEQUENCE_ERROR 0x10
#define R1_ADDRESS_ERROR 0x20
#define R1_PARAMETER_ERROR 0x40
// SD卡状态标志定义
#define STATUS_READY 0x00
#define STATUS_IDLE 0x01
#define STATUS_ERASE_RESET 0x02
#define STATUS_ILLEGAL_COMMAND 0x04
#define STATUS_CRC_ERROR 0x08
#define STATUS_ERASE_SEQUENCE_ERROR 0x10
#define STATUS_ADDRESS_ERROR 0x20
#define STATUS_PARAMETER_ERROR 0x40
#define STATUS_APP_CMD 0x80
// 定义SPI总线句柄
static spi_device_handle_t spi;
// 初始化SPI总线
static void spi_init(void)
{
esp_err_t ret;
// 配置SPI总线参数
spi_bus_config_t buscfg = {
.miso_io_num = PIN_NUM_MISO,
.mosi_io_num = PIN_NUM_MOSI,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4096,
};
// 初始化SPI总线
ret = spi_bus_initialize(VSPI_HOST, &buscfg, 1);
ESP_ERROR_CHECK(ret);
// 配置SPI设备参数
spi_device_interface_config_t devcfg = {
.mode = 0, // SPI模式0
.clock_speed_hz = 400000, // 时钟频率400kHz
.spics_io_num = PIN_NUM_CS, // 片选引脚
.queue_size = 1,
};
// 添加SPI设备
ret = spi_bus_add_device(VSPI_HOST, &devcfg, &spi);
ESP_ERROR_CHECK(ret);
}
// 发送SD卡命令
static uint8_t sdcard_cmd(uint8_t cmd, uint32_t arg)
{
uint8_t buf[6];
memset(buf, 0, sizeof(buf));
// 构造命令
buf[0] = cmd | 0x40;
buf[1] = (uint8_t)(arg >> 24);
buf[2] = (uint8_t)(arg >> 16);
buf[3] = (uint8_t)(arg >> 8);
buf[4] = (uint8_t)arg;
buf[5] = 0x95;
// 发送命令
spi_transaction_t t = {
.length = 48,
.tx_buffer = buf,
.flags = SPI_TRANS_USE_TXDATA,
};
spi_device_transmit(spi, &t);
// 接收响应
uint8_t response;
t.length = 8;
t.rx_buffer = &response;
spi_device_transmit(spi, &t);
return response;
}
// 初始化SD卡
static bool sdcard_init(void)
{
uint8_t response;
uint32_t i;
bool success = false;
// 发送CMD0命令,使SD卡进入空闲状态
for (i = 0; i < 10; ++i) {
response = sdcard_cmd(CMD_GO_IDLE_STATE, 0);
if (response == R1_IDLE_STATE) {
success = true;
break;
}
}
if (!success) {
return false;
}
// 发送CMD8命令,检测SD卡是否支持高容量
response = sdcard_cmd(CMD_SEND_IF_COND, 0x1AA);
if (response != R1_IDLE_STATE) {
return false;
}
// 发送ACMD41命令,激活SD卡
for (i = 0; i < 10; ++i) {
response = sdcard_cmd(CMD_APP_CMD, 0);
if (response != R1_IDLE_STATE) {
continue;
}
response = sdcard_cmd(CMD_SEND_OP_COND, 0x40000000);
if (response == R1_IDLE_STATE) {
success = true;
break;
}
}
if (!success) {
return false;
}
// 发送CMD58命令,读取SD卡OCR
response = sdcard_cmd(CMD_READ_OCR, 0);
if (response != R1_IDLE_STATE) {
return false;
}
// SD卡初始化成功
return true;
}
// 读取指定扇区的数据
static bool sdcard_read_block(uint32_t sector, uint8_t *buffer)
{
uint8_t response;
uint32_t i;
// 发送CMD17命令,读取单个扇区
response = sdcard_cmd(CMD_READ_SINGLE_BLOCK, sector << 9);
if (response != R1_IDLE_STATE) {
return false;
}
// 接收数据
spi_transaction_t t = {
.rxlength = 512*8,
.rx_buffer = buffer,
};
spi_device_transmit(spi, &t);
// 读取响应
for (i = 0; i < 8; ++i) {
spi_device_transmit(spi, &t);
}
// 检查响应
if ((response = sdcard_cmd(CMD_SEND_STATUS, 0)) != R1_IDLE_STATE) {
return false;
}
if ((response = sdcard_cmd(CMD_STOP_TRANSMISSION, 0)) != R1_IDLE_STATE) {
return false;
}
// 读取成功
return true;
}
// 写入数据到指定扇区
static bool sdcard_write_block(uint32_t sector, const uint8_t *buffer)
{
uint8_t response;
uint32_t i;
// 发送CMD24命令,写入单个扇区
response = sdcard_cmd(CMD_WRITE_BLOCK, sector << 9);
if (response != R1_IDLE_STATE) {
return false;
}
// 发送数据
spi_transaction_t t = {
.length = 512*8,
.tx_buffer = buffer,
};
spi_device_transmit(spi, &t);
// 发送CRC
uint8_t crc[2] = { 0xFF, 0xFF };
t.length = 16;
t.tx_buffer = crc;
spi_device_transmit(spi, &t);
// 读取响应
for (i = 0; i < 8; ++i) {
spi_device_transmit(spi, &t);
}
// 检查响应
if ((response = sdcard_cmd(CMD_SEND_STATUS, 0)) != R1_IDLE_STATE) {
return false;
}
// 写入成功
return true;
}
```
这只是一个基本的SPI驱动程序,需要根据实际情况进行修改和完善。具体的SD卡操作流程和命令可以参考SD卡规范。
阅读全文