285 lines
7.6 KiB
C
285 lines
7.6 KiB
C
#include "sd.h"
|
||
#include "sdio.h"
|
||
#include "fatfs.h"
|
||
#include <string.h>
|
||
|
||
SD_HandleTypeDef _handle;
|
||
|
||
#define NUM_OF_BLOCKS 1
|
||
#define TEST_ADDRESS 0
|
||
#define TEST_BLOCK_SIZE ((BLOCKSIZE * NUM_OF_BLOCKS) >> 2) // 定义数据大小,SD块大小为512字节,因为是32位的数组,所以这里除以4
|
||
|
||
BOOL sd_fatfs_test(void)
|
||
{
|
||
uint32_t byteswritten; /* File write counts */
|
||
uint32_t bytesread; /* File read counts */
|
||
uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
|
||
uint8_t rtext[100]; /* File read buffers */
|
||
char filename[] = "STM32cube.txt";
|
||
char SensorBuff[100];
|
||
printf("********* STM32CubeMX FatFs Example *********\r\n\r\n");
|
||
if (f_mount(&SDFatFS, SDPath, 1) == FR_OK)
|
||
{
|
||
printf("f_mount sucess!!! \r\n");
|
||
if (f_open(&SDFile, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||
{
|
||
printf("f_open file sucess!!! \r\n");
|
||
if (f_write(&SDFile, wtext, sizeof(wtext), &byteswritten) == FR_OK)
|
||
{
|
||
printf("f_write file sucess!!! \r\n");
|
||
printf("f_write Data : %s\r\n", wtext);
|
||
if (f_close(&SDFile) == FR_OK)
|
||
printf("f_close sucess!!! \r\n");
|
||
else
|
||
printf("f_close error : %d\r\n", retSD);
|
||
}
|
||
else
|
||
printf("f_write file error\r\n");
|
||
}
|
||
else
|
||
printf("f_open file error\r\n");
|
||
}
|
||
else
|
||
{
|
||
printf("f_mount error : %d \r\n", retSD);
|
||
return FALSE;
|
||
}
|
||
|
||
retSD = f_open(&SDFile, filename, FA_READ);
|
||
if (retSD)
|
||
{
|
||
printf("f_open file error : %d\r\n", retSD);
|
||
return FALSE;
|
||
}
|
||
else
|
||
printf("f_open file sucess!!! \r\n");
|
||
|
||
retSD = f_read(&SDFile, rtext, sizeof(rtext), (UINT *)&bytesread);
|
||
if (retSD)
|
||
{
|
||
printf("f_read error!!! %d\r\n", retSD);
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
printf("f_read sucess!!! \r\n");
|
||
printf("f_read Data : %s\r\n", rtext);
|
||
}
|
||
|
||
retSD = f_close(&SDFile);
|
||
if (retSD)
|
||
{
|
||
printf("f_close error!!! %d\r\n", retSD);
|
||
return FALSE;
|
||
}
|
||
else
|
||
printf("f_close sucess!!! \r\n");
|
||
|
||
if (bytesread == byteswritten)
|
||
printf("FatFs is working well!!!\r\n");
|
||
|
||
if (f_open(&SDFile, (const char *)"Sensor.csv", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||
{
|
||
printf("Sensor.csv was opened/created!!!\r\n");
|
||
sprintf(SensorBuff, "Item,Temp,Humi,Light\r\n");
|
||
f_write(&SDFile, SensorBuff, strlen(SensorBuff), &byteswritten);
|
||
|
||
for (int i = 0; i < 10; i++)
|
||
{
|
||
sprintf(SensorBuff, "%d,%d,%d,%d\r\n", i + 1, i + 20, i + 30, i + 40);
|
||
f_write(&SDFile, SensorBuff, strlen(SensorBuff), &byteswritten);
|
||
f_sync(&SDFile);
|
||
}
|
||
f_close(&SDFile);
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL sd_test(void)
|
||
{
|
||
BOOL res = FALSE;
|
||
uint32_t i = 0;
|
||
uint32_t write_buffer[TEST_BLOCK_SIZE];
|
||
uint32_t read_buffer[TEST_BLOCK_SIZE];
|
||
for (i = 0; i < TEST_BLOCK_SIZE; i++) // 将要写入SD卡的数据写入数组
|
||
{
|
||
write_buffer[i] = i + 3;
|
||
}
|
||
|
||
res = sd_erase(TEST_ADDRESS, NUM_OF_BLOCKS);
|
||
if (res == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
while (sd_get_card_state() == FALSE)
|
||
;
|
||
|
||
res = sd_write_blocks(write_buffer, TEST_ADDRESS, NUM_OF_BLOCKS); // 写入数据
|
||
if (res == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
while (sd_get_card_state() == FALSE)
|
||
;
|
||
|
||
res = sd_read_blocks(read_buffer, TEST_ADDRESS, NUM_OF_BLOCKS); // 读取数据
|
||
if (res == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
while (sd_get_card_state() == FALSE)
|
||
;
|
||
|
||
// 验证写入和读取的数据是否一致
|
||
for (i = 0; i < TEST_BLOCK_SIZE; i++)
|
||
{
|
||
if (read_buffer[i] != write_buffer[i])
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void sd_info(void)
|
||
{
|
||
// SD卡信息结构体变量
|
||
HAL_SD_CardInfoTypeDef cardInfo;
|
||
HAL_StatusTypeDef res = HAL_SD_GetCardInfo(&_handle, &cardInfo);
|
||
if (res != HAL_OK)
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
|
||
void sd_init(void)
|
||
{
|
||
// MX_SDIO_SD_Init有问题,这里重新初始化
|
||
_handle.Instance = SDIO;
|
||
_handle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||
_handle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||
_handle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||
_handle.Init.BusWide = SDIO_BUS_WIDE_1B; // CUBEMX生成默认是4B,此处改为1B
|
||
_handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||
_handle.Init.ClockDiv = 4;
|
||
|
||
if (HAL_SD_Init(&_handle) != HAL_OK)
|
||
{
|
||
Error_Handler();
|
||
}
|
||
if (HAL_SD_ConfigWideBusOperation(&_handle, SDIO_BUS_WIDE_4B) != HAL_OK)
|
||
{
|
||
Error_Handler();
|
||
}
|
||
|
||
sd_info();
|
||
}
|
||
|
||
/**
|
||
* @brief 获取SD卡的状态
|
||
*
|
||
* 该函数用于获取SD卡的当前状态,并返回一个布尔值表示SD卡是否处于传输状态。
|
||
*
|
||
* @return BOOL - 如果SD卡处于传输状态,则返回TRUE,否则返回FALSE。
|
||
*/
|
||
BOOL sd_get_card_state(void)
|
||
{
|
||
HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&_handle);
|
||
return (state == HAL_SD_CARD_TRANSFER) ? TRUE : FALSE;
|
||
}
|
||
|
||
/**
|
||
* @brief 擦除SD卡指定地址范围的数据
|
||
*
|
||
* 该函数用于擦除SD卡上从指定的起始地址到结束地址之间的数据。
|
||
*
|
||
* @param start_address - 擦除操作的起始地址
|
||
* @param end_address - 擦除操作的结束地址
|
||
* @return BOOL - 如果擦除操作成功,则返回TRUE,否则返回FALSE。
|
||
*/
|
||
BOOL sd_erase(uint32_t start_address, uint32_t end_address)
|
||
{
|
||
if (HAL_SD_Erase(&_handle, start_address, end_address) != HAL_OK)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
BOOL sd_write_blocks(uint32_t *data, uint32_t write_address, uint32_t blocks)
|
||
{
|
||
if (HAL_SD_WriteBlocks(&_handle, (uint8_t *)data, write_address, blocks, 1000) != HAL_OK)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
BOOL sd_read_blocks(uint32_t *data, uint32_t read_address, uint32_t blocks)
|
||
{
|
||
if (HAL_SD_ReadBlocks(&_handle, (uint8_t *)data, read_address, blocks, 1000) != HAL_OK)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 使用DMA方式从SD卡读取多个数据块
|
||
*
|
||
* 该函数用于通过DMA方式从SD卡的指定地址读取多个数据块,并将数据存储在指定的缓冲区中。
|
||
*
|
||
* @param data - 指向存储读取数据的缓冲区的指针
|
||
* @param read_address - 读取操作的起始地址
|
||
* @param blocks - 要读取的数据块数量
|
||
* @return BOOL - 如果读取操作成功,则返回TRUE,否则返回FALSE。
|
||
*/
|
||
BOOL sd_read_blocks_dma(uint32_t *data, uint32_t read_address, uint32_t blocks)
|
||
{
|
||
if (HAL_SD_ReadBlocks_DMA(&_handle, (uint8_t *)data, read_address, blocks) != HAL_OK)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 使用DMA方式向SD卡写入多个数据块
|
||
*
|
||
* 该函数用于通过DMA方式向SD卡的指定地址写入多个数据块。
|
||
*
|
||
* @param data - 指向要写入数据的缓冲区的指针
|
||
* @param write_address - 写入操作的起始地址
|
||
* @param blocks - 要写入的数据块数量
|
||
* @return BOOL - 如果写入操作成功,则返回TRUE,否则返回FALSE。
|
||
*/
|
||
BOOL sd_write_blocks_dma(uint32_t *data, uint32_t write_address, uint32_t blocks)
|
||
{
|
||
if (HAL_SD_WriteBlocks_DMA(&_handle, (uint8_t *)data, write_address, blocks) != HAL_OK)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|