STM32H750 SD卡SPI模式例程
时间: 2023-10-29 13:05:10 浏览: 97
以下是STM32H750 SD卡SPI模式的例程,供参考:
```c
#include "stm32h7xx_hal.h"
#include "fatfs.h"
/* SPI1 init function */
static void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
/* GPIO init function */
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PA5 PA6 PA7 */
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void SD_SPI_Init(void)
{
/* SPI1 parameter configuration*/
MX_SPI1_Init();
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
/*Configure GPIO pin : PA4 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PA5 PA6 PA7 */
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void SD_SPI_DeInit(void)
{
HAL_SPI_DeInit(&hspi1);
}
void SD_SPI_SetSpeed(uint8_t speed)
{
hspi1.Init.BaudRatePrescaler = speed;
HAL_SPI_Init(&hspi1);
}
uint8_t SPI_RW(uint8_t data)
{
uint8_t tmp;
HAL_SPI_TransmitReceive(&hspi1, &data, &tmp, 1, 1000);
return tmp;
}
uint8_t SD_SPI_ReadWriteByte(uint8_t byte)
{
uint8_t res;
HAL_SPI_TransmitReceive(&hspi1,&byte,&res,1,HAL_MAX_DELAY);
return res;
}
void SD_SPI_WriteByte(uint8_t byte)
{
HAL_SPI_Transmit(&hspi1,&byte,1,HAL_MAX_DELAY);
}
uint8_t SD_SPI_ReadByte(void)
{
uint8_t byte = 0xFF;
HAL_SPI_TransmitReceive(&hspi1,&byte,&byte,1,HAL_MAX_DELAY);
return byte;
}
uint8_t SD_SPI_WaitReady(void)
{
uint8_t res;
uint32_t retry=0;
do
{
res = SD_SPI_ReadByte();
retry++;
if(retry > 0x1FFFFFFF)
return 0x01;
}while(res!=0xFF);
return 0;
}
uint8_t SD_SPI_Deselect(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
SD_SPI_ReadByte();
return 0;
}
uint8_t SD_SPI_Select(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
if(SD_SPI_WaitReady())
{
SD_SPI_Deselect();
return 1;
}
return 0;
}
uint8_t SD_SPI_SendCommand(uint8_t cmd, uint32_t arg, uint8_t crc)
{
uint8_t r1;
uint8_t retry = 0;
SD_SPI_Deselect();
if(SD_SPI_Select())
return 0x01;
SD_SPI_WriteByte(cmd | 0x40);
SD_SPI_WriteByte(arg >> 24);
SD_SPI_WriteByte(arg >> 16);
SD_SPI_WriteByte(arg >> 8);
SD_SPI_WriteByte(arg);
SD_SPI_WriteByte(crc);
while((r1 = SD_SPI_ReadByte()) == 0xFF)
{
retry++;
if(retry > 0xFE)
{
SD_SPI_Deselect();
return 0x01;
}
}
if(r1 != 0x00)
{
SD_SPI_Deselect();
return r1;
}
return 0;
}
uint8_t SD_SPI_SendCommand_NoDeassert(uint8_t cmd, uint32_t arg, uint8_t crc)
{
uint8_t r1;
uint8_t retry = 0;
if(SD_SPI_Select())
return 0x01;
SD_SPI_WriteByte(cmd | 0x40);
SD_SPI_WriteByte(arg >> 24);
SD_SPI_WriteByte(arg >> 16);
SD_SPI_WriteByte(arg >> 8);
SD_SPI_WriteByte(arg);
SD_SPI_WriteByte(crc);
while((r1 = SD_SPI_ReadByte()) == 0xFF)
{
retry++;
if(retry > 0xFE)
{
SD_SPI_Deselect();
return 0x01;
}
}
if(r1 != 0x00)
{
SD_SPI_Deselect();
return r1;
}
return 0;
}
uint8_t SD_SPI_ReceiveData(uint8_t *data, uint16_t len, uint8_t release)
{
uint8_t retry = 0x1F;
do
{
*data = SD_SPI_ReadByte();
data++;
*data = SD_SPI_ReadByte();
data++;
len -= 2;
} while(len && retry--);
if(release)
SD_SPI_Deselect();
return len ? 0x01 : 0;
}
uint8_t SD_SPI_SendData(const uint8_t *data, uint8_t token)
{
uint8_t r1;
if(!SD_SPI_Select())
return 0x01;
SD_SPI_WriteByte(token);
if(token != 0xFD)
{
while(SD_SPI_ReadByte() == 0xFF);
do
{
SD_SPI_WriteByte(*data++);
SD_SPI_WriteByte(*data++);
} while(--token);
SD_SPI_ReadByte();
SD_SPI_ReadByte();
r1 = SD_SPI_ReadByte() & 0x1F;
if(r1 == 0x05)
{
r1 = 0;
if(SD_SPI_WaitReady())
return 0x01;
}
if(SD_SPI_Deselect())
return 0x01;
return r1;
}
else
{
SD_SPI_Deselect();
return 0x00;
}
}
uint8_t SD_SPI_SendCmd(uint8_t cmd, uint32_t arg, uint8_t crc, uint8_t *resp, uint8_t resplen)
{
uint8_t retry = 0x1F;
uint8_t ret;
if(cmd & 0x80)
{
ret = SD_SPI_SendCommand(cmd, arg, crc);
if(ret)
return ret;
}
if(resp)
{
do
{
*resp = SD_SPI_ReadByte();
resp++;
resplen--;
} while(resplen && (*resp == 0xFF) && retry--);
if(resplen == 0)
return 0x01;
}
return 0x00;
}
uint8_t SD_SPI_Initialize(void)
{
uint8_t r1;
uint32_t retry;
SD_SPI_SetSpeed(SPI_BAUDRATEPRESCALER_256);
for(retry = 0; retry < 0x100; retry++)
SD_SPI_ReadByte();
HAL_Delay(100);
retry = 0x1FFF;
do
{
r1 = SD_SPI_SendCommand_NoDeassert(SD_CMD_GO_IDLE_STATE, 0, 0x95);
retry--;
} while((r1 != 0x01) && retry);
if(!retry)
return 0x01;
retry = 0xFFFF;
do
{
r1 = SD_SPI_SendCommand_NoDeassert(SD_CMD_SEND_IF_COND, 0x000001aa, 0x87);
retry--;
} while((r1 != 0x01) && retry);
if(retry == 0)
return 0x01;
if(SD_SPI_SendCmd(SD_CMD_APP_CMD, 0, 0, NULL, 0x00) == 0x01)
{
r1 = SD_SPI_SendCmd(SD_CMD_SD_SEND_OP_COND, 0x40300000, 0, NULL, 0x00);
if(r1 == 0x00)
{
r1 = SD_SPI_SendCmd(SD_CMD_READ_OCR, 0, 0, NULL, 0x00);
if(r1 == 0x00)
{
return 0x00;
}
}
}
return 0x01;
}
```
这是一个简单的SD卡SPI模式的例程,包括了SD卡的初始化、命令发送、数据读写等操作。需要注意的是,这个例程是基于HAL库编写的,如果你使用的是其他的库,可能需要进行一些适当的修改。另外,这个例程只是一个参考,具体的实现方式还需要根据自己的实际需求进行调整和完善。
阅读全文