赞
踩
配置USART1
配置SPI1
配置FATFS
GPIO配置
时钟配置
Serial Wire配置
生成工程
将SDdriver.c
和SDdriver.h
文件添加到工程中
复制到与工程同一路径后后,在工程里面添加SDdriver.c
文件,并添加包含该文件的路径。
①添加包含的头文件
#include "diskio.h" /* Declarations of disk functions */
#include "SDdriver.h"
接下来分别对USER_initialize、USER_status、USER_read、USE_WRITE、USE_IOCTL函数进行修改,将其内容替换为下面对应函数相关内容
②修改USER_initialize
函数
uint8_t res;
res = SD_init();//SD_Initialize()
if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
{
SPI_setspeed(SPI_BAUDRATEPRESCALER_256);
spi_readwrite(0xff);//提供额外的8个时钟
SPI_setspeed(SPI_BAUDRATEPRESCALER_2);
}
if(res)
return STA_NOINIT;
else
return RES_OK; //初始化成功
③修改USER_status
函数
switch (pdrv)
{
case 0 :
return RES_OK;
case 1 :
return RES_OK;
case 2 :
return RES_OK;
default:
return STA_NOINIT;
}
④修改USER_read
函数
uint8_t res; if( !count ) { return RES_PARERR; /* count不能等于0,否则返回参数错误 */ } switch (pdrv) { case 0: res=SD_ReadDisk(buff,sector,count); if(res == 0){ return RES_OK; }else{ return RES_ERROR; } default: return RES_ERROR; }
⑤修改USE_WRITE
函数
uint8_t res; if( !count ) { return RES_PARERR; /* count不能等于0,否则返回参数错误 */ } switch (pdrv) { case 0: res=SD_WriteDisk((uint8_t *)buff,sector,count); if(res == 0){ return RES_OK; }else{ return RES_ERROR; } default:return RES_ERROR; }
⑥修改USE_IOCTL
函数
DRESULT res; switch(cmd) { case CTRL_SYNC: SD_CS(1); do{ HAL_Delay(20); }while(spi_readwrite(0xFF)!=0xFF); res=RES_OK; SD_CS(0); break; case GET_SECTOR_SIZE: *(WORD*)buff = 512; res = RES_OK; break; case GET_BLOCK_SIZE: *(WORD*)buff = 8; res = RES_OK; break; case GET_SECTOR_COUNT: *(DWORD*)buff = SD_GetSectorCount(); res = RES_OK; break; default: res = RES_PARERR; break; } return res;
包含头文件
#include "SDdriver.h"
在main函数前添加变量与函数定义
uint16_t uart_value[3]; uint8_t aRxBuffer1; //uart rx buff void WritetoSD(BYTE write_buff[],uint8_t bufSize); char SD_FileName[] = "test.txt"; uint8_t WriteBuffer[] = "山有木兮\r\n"; //uint8_t test_sd =0; //用于测试格式化 uint8_t write_cnt =0; //写SD卡次数 void WritetoSD(BYTE write_buff[],uint8_t bufSize) { FATFS fs; FIL file; uint8_t res=0; UINT Bw; res = SD_init(); //SD卡初始化 if(res == 1) { printf("SD卡初始化失败! \r\n"); } res=f_mount(&fs,"0:",1); //挂载 // if(test_sd == 0) //用于测试格式化 if(res == FR_NO_FILESYSTEM) //没有文件系统,格式化 { // test_sd =1; //用于测试格式化 printf("没有文件系统! \r\n"); res = f_mkfs("", 0, 0); //格式化sd卡 if(res == FR_OK) { //printf("格式化成功! \r\n"); res = f_mount(NULL,"0:",1); //格式化后先取消挂载 res = f_mount(&fs,"0:",1); //重新挂载 if(res == FR_OK) { //printf("SD卡已经成功挂载,可以进进行文件写入测试!\r\n"); } } else { printf("格式化失败! \r\n"); } } else if(res == FR_OK) { //printf("挂载成功! \r\n"); } else { printf("挂载失败! \r\n"); } res = f_open(&file,SD_FileName,FA_OPEN_ALWAYS |FA_WRITE); if((res & FR_DENIED) == FR_DENIED) { printf("卡存储已满,写入失败!\r\n"); } f_lseek(&file, f_size(&file));//确保写词写入不会覆盖之前的数据 if(res == FR_OK) { //printf("打开成功/创建文件成功! \r\n"); res = f_write(&file,write_buff,bufSize,&Bw); //写数据到SD卡 if(res == FR_OK) { printf("文件写入成功! \r\n"); } else { printf("文件写入失败! \r\n"); } } else { printf("打开文件失败!\r\n"); } f_close(&file); //关闭文件 f_mount(NULL,"0:",1); //取消挂载 } void Get_SDCard_Capacity(void) { FRESULT result; FATFS FS; FATFS *fs; DWORD fre_clust,AvailableSize,UsedSize; uint16_t TotalSpace; uint8_t res; res = SD_init(); //SD卡初始化 if(res == 1) { printf("SD卡初始化失败! \r\n"); } else { printf("SD卡初始化成功! \r\n"); } /* 挂载 */ res=f_mount(&FS,"0:",1); //挂载 if (res != FR_OK) { printf("FileSystem Mounted Failed (%d)\r\n", result); } res = f_getfree("0:", &fre_clust, &fs); /* 根目录 */ if ( res == FR_OK ) { TotalSpace=(uint16_t)(((fs->n_fatent - 2) * fs->csize ) / 2 /1024); AvailableSize=(uint16_t)((fre_clust * fs->csize) / 2 /1024); UsedSize=TotalSpace-AvailableSize; /* Print free space in unit of MB (assuming 512 bytes/sector) */ printf("\r\n%d MB total drive space.\r\n""%d MB available.\r\n""%d MB used.\r\n",TotalSpace, AvailableSize,UsedSize); } else { printf("Get SDCard Capacity Failed (%d)\r\n", result); } }
将main函数替代为以下内容
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_SPI1_Init(); MX_FATFS_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart1,&aRxBuffer1,1); //enable uart printf(" mian \r\n"); Get_SDCard_Capacity(); //得到使用内存并选择格式化 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { WritetoSD(WriteBuffer,sizeof(WriteBuffer)); printf("writing\r\n"); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
在usart.c中重定向printf()函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (unsigned char *)&ch, 1, 0xFFFF); //修改【4】,串口重定向
return ch;
}
在usart.h声明并包含头文件stdio.h
打开Micro LIB
编译完成即可
本实验是基于源码自己重新新建了一个工程,如果怕麻烦,可直接下载源码
接线方式
SD卡 | stm32系统板 |
---|---|
CS | PA4 |
SCK | PA5 |
MISO | PA6 |
MOSI | PA7 |
VCC | 5V |
GND | GND |
上位机显示
初始化成功,正在写入数据
写数据成功,查看已写好的数据
驱动SD卡的时候,最好将供电电压提高到5V,提高更强的驱动能力。我之前默认使用3.3v由于驱动能力不够,所以一直初始化失败,卡顿了好久。所以基于硬件,稍微有一点有错就会导致整体失败,要特别注意细节。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。