cube sdio fatfs 初始化sd卡_【STM32】SD卡读写(五)-STM32CubeMX HAL库SPI操作 SD卡带FATFS...

1、添加SD卡SPI模式驱动

  1. /**
  2. * @brief SPI1 Initialization Function
  3. * @param None
  4. * @retval None
  5. */
  6. static void MX_SPI1_Init(void)
  7. {
  8. /* USER CODE BEGIN SPI1_Init 0 */
  9. /* USER CODE END SPI1_Init 0 */
  10. /* USER CODE BEGIN SPI1_Init 1 */
  11. /* USER CODE END SPI1_Init 1 */
  12. /* SPI1 parameter configuration*/
  13. hspi1.Instance = SPI1;
  14. hspi1.Init.Mode = SPI_MODE_MASTER;
  15. hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  16. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  17. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  18. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  19. hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
  20. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  21. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  22. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  23. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  24. hspi1.Init.CRCPolynomial = 10;
  25. if (HAL_SPI_Init(&hspi1) != HAL_OK)
  26. {
  27. Error_Handler();
  28. }
  29. /* USER CODE BEGIN SPI1_Init 2 */
  30. /* USER CODE END SPI1_Init 2 */
  31. }

编写SD卡SPI驱动 SDCard.c

  1. #include "main.h"
  2. #include "SDCard.h"
  3. /* USER CODE BEGIN 0 */
  4. /* USER CODE END 0 */
  5. /* USART1 init function */
  6. /**************************************************************************/
  7. #define Dummy_Byte 0xFF
  8. /* 私有变量 ------------------------------------------------------------------*/
  9. SPI_HandleTypeDef hspiflash;
  10. extern SPI_HandleTypeDef hspi1;
  11. u8 SD_Type=0;
  12. /* function ------------------------------------------------------------------*/
  13. /**
  14. * 函数功能: 从串行Flash读取一个字节数据
  15. * 输入参数: 无
  16. * 返 回 值: uint8_t:读取到的数据
  17. * 说 明:This function must be used only if the Start_Read_Sequence
  18. * function has been previously called.
  19. */
  20. uint8_t SPI_FLASH_ReadByte(void)
  21. {
  22. uint8_t d_read,d_send=Dummy_Byte;
  23. if(HAL_SPI_TransmitReceive(&hspiflash,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
  24. d_read=Dummy_Byte;
  25. return d_read;
  26. }
  27. void SPI_I2S_SendData(SPI_TypeDef* SPIx, u16 Data)
  28. {
  29. /* Check the parameters */
  30. assert_param(IS_SPI_ALL_PERIPH(SPIx));
  31. /* Write in the DR register the data to be sent */
  32. SPIx->DR = Data;
  33. }
  34. u16 SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
  35. {
  36. /* Check the parameters */
  37. assert_param(IS_SPI_ALL_PERIPH(SPIx));
  38. //assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
  39. /* Return the data in the DR register */
  40. return SPIx->DR;
  41. }
  42. /**
  43. * 函数功能: 往串行Flash读取写入一个字节数据并接收一个字节数据
  44. * 输入参数: byte:待发送数据
  45. * 返 回 值: uint8_t:接收到的数据
  46. * 说 明:无
  47. */
  48. uint8_t SPI_FLASH_SendByte(uint8_t byte)
  49. {
  50. uint8_t d_read,d_send=byte;
  51. // if(HAL_SPI_TransmitReceive(&hspiflash,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
  52. //{
  53. //d_read=Dummy_Byte;
  54. //}
  55. //等待发送缓冲区空
  56. // while(__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE));
  57. //发一个字节
  58. // SPI_I2S_SendData(SPI1, d_send);
  59. HAL_SPI_Transmit(&hspi1,&d_send,1,1000);
  60. //HAL_SPI_Receive(&hspi1,&d_read,1,1000);
  61. //等待数据接收
  62. while(__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE));
  63. //取数据
  64. d_read = SPI_I2S_ReceiveData(SPI1);
  65. return d_read;
  66. }
  67. /*******************************************************************************
  68. * Function Name : SD_WaitReady
  69. * Description : 等待SD卡Ready
  70. * Input : None
  71. * Output : None
  72. * Return : u8
  73. * 0: 成功
  74. * other:失败
  75. *******************************************************************************/
  76. u8 SD_WaitReady(void)
  77. {
  78. u8 r1;
  79. u16 retry;
  80. retry = 0;
  81. do
  82. {
  83. r1 = SPI_FLASH_SendByte(0xFF);
  84. if(retry==0xfffe)
  85. {
  86. return 1;
  87. }
  88. }while(r1!=0xFF);
  89. return 0;
  90. }
  91. /*******************************************************************************
  92. * Function Name : SD_SendCommand
  93. * Description : 向SD卡发送一个命令
  94. * Input : u8 cmd 命令
  95. * u32 arg 命令参数
  96. * u8 crc crc校验值
  97. * Output : None
  98. * Return : u8 r1 SD卡返回的响应
  99. *******************************************************************************/
  100. u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
  101. {
  102. unsigned char r1;
  103. unsigned char Retry = 0;
  104. //????????
  105. SPI_FLASH_SendByte(0xff);
  106. //片选端置低,选中SD卡
  107. FLASH_SPI_CS_ENABLE();
  108. //发送
  109. SPI_FLASH_SendByte(cmd | 0x40); //分别写入命令
  110. SPI_FLASH_SendByte(arg >> 24);
  111. SPI_FLASH_SendByte(arg >> 16);
  112. SPI_FLASH_SendByte(arg >> 8);
  113. SPI_FLASH_SendByte(arg);
  114. SPI_FLASH_SendByte(crc);
  115. //等待响应,或超时退出
  116. while((r1 = SPI_FLASH_SendByte(0xFF))==0xFF)
  117. {
  118. Retry++;
  119. if(Retry > 200)
  120. {
  121. break;
  122. }
  123. }
  124. //关闭片选
  125. FLASH_SPI_CS_DISABLE();
  126. //在总线上额外增加8个时钟,让SD卡完成剩下的工作
  127. SPI_FLASH_SendByte(0xFF);
  128. //返回状态值
  129. return r1;
  130. }
  131. /*******************************************************************************
  132. * Function Name : SD_SendCommand_NoDeassert
  133. * Description : 向SD卡发送一个命令(结束是不失能片选,还有后续数据传来)
  134. * Input : u8 cmd 命令
  135. * u32 arg 命令参数
  136. * u8 crc crc校验值
  137. * Output : None
  138. * Return : u8 r1 SD卡返回的响应
  139. *******************************************************************************/
  140. u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
  141. {
  142. unsigned char r1;
  143. unsigned char Retry = 0;
  144. //????????
  145. SPI_FLASH_SendByte(0xff);
  146. //片选端置低,选中SD卡
  147. FLASH_SPI_CS_ENABLE();
  148. //发送
  149. SPI_FLASH_SendByte(cmd | 0x40); //分别写入命令
  150. SPI_FLASH_SendByte(arg >> 24);
  151. SPI_FLASH_SendByte(arg >> 16);
  152. SPI_FLASH_SendByte(arg >> 8);
  153. SPI_FLASH_SendByte(arg);
  154. SPI_FLASH_SendByte(crc);
  155. //等待响应,或超时退出
  156. while((r1 = SPI_FLASH_SendByte(0xFF))==0xFF)
  157. {
  158. Retry++;
  159. if(Retry > 200)
  160. {
  161. break;
  162. }
  163. }
  164. //返回响应值
  165. return r1;
  166. }
  167. void SPI_SetSpeed(u8 SpeedSet)
  168. {
  169. hspi1.Instance = SPI1;
  170. hspi1.Init.Mode = SPI_MODE_MASTER;
  171. hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  172. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  173. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  174. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  175. hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
  176. //如果速度设置输入0,则低速模式,非0则高速模式
  177. if(SpeedSet==SPI_SPEED_LOW)
  178. {
  179. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  180. }
  181. else
  182. {
  183. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  184. }
  185. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  186. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  187. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  188. hspi1.Init.CRCPolynomial = 10;
  189. if (HAL_SPI_Init(&hspi1) != HAL_OK)
  190. {
  191. Error_Handler();
  192. }
  193. // if(SpeedSet==SPI_SPEED_LOW)
  194. //{
  195. // hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  196. //}
  197. //else
  198. //{
  199. //hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  200. //}
  201. //HAL_SPI_Init(&hspi1);
  202. //moon.mp3: 4707774 Byte size 目标文件 设为buffer[512]
  203. //speed:实验测试数据,最大速度 392314 Byte/S,
  204. //Prescaler_128, 59592 Byte/S
  205. //Prescaler_64, 104617 Byte/S
  206. //Prescaler_32, 168134 Byte/S 162337 Byte/S
  207. //Prescaler_16, 261543 Byte/S 247777 Byte/S
  208. //Prescaler_8, 313851 Byte/S 336269 Byte/S
  209. //Prescaler_4, 392314 Byte/S 392314 Byte/S
  210. //Prescaler_2, 392314 Byte/S
  211. }
  212. /*******************************************************************************
  213. * Function Name : SD_Init
  214. * Description : 初始化SD卡
  215. * Input : None
  216. * Output : None
  217. * Return : u8
  218. * 0:NO_ERR
  219. * 1:TIME_OUT
  220. * 99:NO_CARD
  221. *******************************************************************************/
  222. u8 SD_Init(void)
  223. {
  224. u16 i; // 用来循环计数
  225. u8 r1; // 存放SD卡的返回值
  226. u16 retry; // 用来进行超时计数
  227. u8 buff[6];
  228. //如果没有检测到卡插入,直接退出,返回错误标志
  229. // if(!SD_DET())
  230. // {
  231. // //return 99;
  232. // return STA_NODISK; // FatFS错误标志:没有插入磁盘
  233. // }
  234. //SD卡上电
  235. //SD_PWR_ON();
  236. // 纯延时,等待SD卡上电完成
  237. //for(i=0;i<0xf00;i++);
  238. /*******************************************************
  239. //这个地方要加一句,设置SPI速度为低速。
  240. //为什么有的卡可以呢?因为SPI初始化时是低速的,SD卡初始化
  241. //完成后设置为高速,有的卡只要初始化一次就行,程序就ok;
  242. //但有的卡需要多次复位,呵呵,这个地方差这一句,
  243. //这种卡就用不成咯!
  244. *******************************************************/
  245. SPI_SetSpeed(0); //设置SPI速度为低速
  246. //先产生>74个脉冲,让SD卡自己初始化完成
  247. for(i=0;i<100;i++)
  248. {
  249. SPI_FLASH_SendByte(0xFF);
  250. }
  251. //-----------------SD卡复位到idle开始-----------------
  252. //循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态
  253. //超时则直接退出
  254. retry = 0;
  255. do
  256. {
  257. //发送CMD0,让SD卡进入IDLE状态
  258. r1 = SD_SendCommand(CMD0, 0, 0x95);
  259. retry++;
  260. }while((r1 != 0x01) && (retry<200));
  261. //跳出循环后,检查原因:初始化成功?or 重试超时?
  262. if(retry==200)
  263. {
  264. return 1; //超时返回1
  265. }
  266. //-----------------SD卡复位到idle结束-----------------
  267. //获取卡片的SD版本信息
  268. r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);
  269. //如果卡片版本信息是v1.0版本的,即r1=0x05,则进行以下初始化
  270. if(r1 == 0x05)
  271. {
  272. printf(" SD卡版本信息:V1.0 ");
  273. //设置卡类型为SDV1.0,如果后面检测到为MMC卡,再修改为MMC
  274. SD_Type = SD_TYPE_V1;
  275. //如果是V1.0卡,CMD8指令后没有后续数据
  276. //片选置高,结束本次命令
  277. FLASH_SPI_CS_DISABLE();
  278. //多发8个CLK,让SD结束后续操作
  279. SPI_FLASH_SendByte(0xFF);
  280. //-----------------SD卡、MMC卡初始化开始-----------------
  281. //发卡初始化指令CMD55+ACMD41
  282. // 如果有应答,说明是SD卡,且初始化完成
  283. // 没有回应,说明是MMC卡,额外进行相应初始化
  284. retry = 0;
  285. do
  286. {
  287. //先发CMD55,应返回0x01;否则出错
  288. r1 = SD_SendCommand(CMD55, 0, 0);
  289. if(r1 != 0x01)
  290. {
  291. return r1;
  292. }
  293. //得到正确响应后,发ACMD41,应得到返回值0x00,否则重试200次
  294. r1 = SD_SendCommand(ACMD41, 0, 0);
  295. retry++;
  296. }while((r1!=0x00) && (retry<400));
  297. // 判断是超时还是得到正确回应
  298. // 若有回应:是SD卡;没有回应:是MMC卡
  299. //----------MMC卡额外初始化操作开始------------
  300. if(retry==400)
  301. {
  302. printf(" SD卡信息: MMC卡 ");
  303. retry = 0;
  304. //发送MMC卡初始化命令(没有测试)
  305. do
  306. {
  307. r1 = SD_SendCommand(1, 0, 0);
  308. retry++;
  309. }while((r1!=0x00)&& (retry<400));
  310. if(retry==400)
  311. {
  312. return 1; //MMC卡初始化超时
  313. }
  314. //写入卡类型
  315. SD_Type = SD_TYPE_MMC;
  316. }
  317. else
  318. {
  319. printf(" SD卡信息: SD卡 ");
  320. }
  321. //----------MMC卡额外初始化操作结束------------
  322. //设置SPI为高速模式
  323. SPI_SetSpeed(1);
  324. SPI_FLASH_SendByte(0xFF);
  325. //禁止CRC校验
  326. /*
  327. r1 = SD_SendCommand(CMD59, 0, 0x01);
  328. if(r1 != 0x00)
  329. {
  330. return r1; //命令错误,返回r1
  331. }
  332. */
  333. //设置Sector Size
  334. r1 = SD_SendCommand(CMD16, 512, 0xff);
  335. if(r1 != 0x00)
  336. {
  337. return r1; //命令错误,返回r1
  338. }
  339. //-----------------SD卡、MMC卡初始化结束-----------------
  340. }//SD卡为V1.0版本的初始化结束
  341. //下面是V2.0卡的初始化
  342. //其中需要读取OCR数据,判断是SD2.0还是SD2.0HC卡
  343. else if(r1 == 0x01)
  344. {
  345. printf(" SD卡版本信息:V2.0 ");
  346. //V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
  347. buff[0] = SPI_FLASH_SendByte(0xFF); //should be 0x00
  348. buff[1] = SPI_FLASH_SendByte(0xFF); //should be 0x00
  349. buff[2] = SPI_FLASH_SendByte(0xFF); //should be 0x01
  350. buff[3] = SPI_FLASH_SendByte(0xFF); //should be 0xAA
  351. FLASH_SPI_CS_DISABLE();
  352. //the next 8 clocks
  353. SPI_FLASH_SendByte(0xFF);
  354. //判断该卡是否支持2.7V-3.6V的电压范围
  355. if(buff[2]==0x01 && buff[3]==0xAA)
  356. {
  357. //支持电压范围,可以操作
  358. retry = 0;
  359. //发卡初始化指令CMD55+ACMD41
  360. do
  361. {
  362. r1 = SD_SendCommand(CMD55, 0, 0);
  363. if(r1!=0x01)
  364. {
  365. return r1;
  366. }
  367. r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
  368. if(retry>200)
  369. {
  370. return r1; //超时则返回r1状态
  371. }
  372. }while(r1!=0);
  373. //初始化指令发送完成,接下来获取OCR信息
  374. //-----------鉴别SD2.0卡版本开始-----------
  375. r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
  376. if(r1!=0x00)
  377. {
  378. return r1; //如果命令没有返回正确应答,直接退出,返回应答
  379. }
  380. //读OCR指令发出后,紧接着是4字节的OCR信息
  381. buff[0] = SPI_FLASH_SendByte(0xFF);
  382. buff[1] = SPI_FLASH_SendByte(0xFF);
  383. buff[2] = SPI_FLASH_SendByte(0xFF);
  384. buff[3] = SPI_FLASH_SendByte(0xFF);
  385. //OCR接收完成,片选置高
  386. FLASH_SPI_CS_DISABLE();
  387. SPI_FLASH_SendByte(0xFF);
  388. //检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
  389. //如果CCS=1:SDHC CCS=0:SD2.0
  390. if(buff[0]&0x40) //检查CCS
  391. {
  392. SD_Type = SD_TYPE_V2HC;
  393. printf(" SD卡信息: SDHC ");
  394. }
  395. else
  396. {
  397. SD_Type = SD_TYPE_V2;
  398. printf(" SD卡信息: SD2.0 ");
  399. }
  400. //-----------鉴别SD2.0卡版本结束-----------
  401. //设置SPI为高速模式
  402. SPI_SetSpeed(1);
  403. }
  404. }
  405. return r1;
  406. }
  407. /*******************************************************************************
  408. * Function Name : SD_ReceiveData
  409. * Description : 从SD卡中读回指定长度的数据,放置在给定位置
  410. * Input : u8 *data(存放读回数据的内存>len)
  411. * u16 len(数据长度)
  412. * u8 release(传输完成后是否释放总线CS置高 0:不释放 1:释放)
  413. * Output : None
  414. * Return : u8
  415. * 0:NO_ERR
  416. * other:错误信息
  417. *******************************************************************************/
  418. u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
  419. {
  420. u16 retry;
  421. u8 r1;
  422. // 启动一次传输
  423. FLASH_SPI_CS_ENABLE();
  424. //等待SD卡发回数据起始令牌0xFE
  425. retry = 0;
  426. do
  427. {
  428. r1 = SPI_FLASH_SendByte(0xFF);
  429. retry++;
  430. if(retry>2000) //2000次等待后没有应答,退出报错
  431. {
  432. FLASH_SPI_CS_DISABLE();
  433. return 1;
  434. }
  435. }while(r1 != 0xFE);
  436. //开始接收数据
  437. while(len--)
  438. {
  439. *data = SPI_FLASH_SendByte(0xFF);
  440. data++;
  441. }
  442. //下面是2个伪CRC(dummy CRC)
  443. SPI_FLASH_SendByte(0xFF);
  444. SPI_FLASH_SendByte(0xFF);
  445. //按需释放总线,将CS置高
  446. if(release == RELEASE)
  447. {
  448. //传输结束
  449. FLASH_SPI_CS_DISABLE();
  450. SPI_FLASH_SendByte(0xFF);
  451. }
  452. return 0;
  453. }
  454. /*******************************************************************************
  455. * Function Name : SD_GetCID
  456. * Description : 获取SD卡的CID信息,包括制造商信息
  457. * Input : u8 *cid_data(存放CID的内存,至少16Byte)
  458. * Output : None
  459. * Return : u8
  460. * 0:NO_ERR
  461. * 1:TIME_OUT
  462. * other:错误信息
  463. *******************************************************************************/
  464. u8 SD_GetCID(u8 *cid_data)
  465. {
  466. u8 r1;
  467. //发CMD10命令,读CID
  468. r1 = SD_SendCommand(CMD10, 0, 0xFF);
  469. if(r1 != 0x00)
  470. {
  471. return r1; //没返回正确应答,则退出,报错
  472. }
  473. //接收16个字节的数据
  474. SD_ReceiveData(cid_data, 16, RELEASE);
  475. return 0;
  476. }
  477. /*******************************************************************************
  478. * Function Name : SD_GetCSD
  479. * Description : 获取SD卡的CSD信息,包括容量和速度信息
  480. * Input : u8 *cid_data(存放CID的内存,至少16Byte)
  481. * Output : None
  482. * Return : u8
  483. * 0:NO_ERR
  484. * 1:TIME_OUT
  485. * other:错误信息
  486. *******************************************************************************/
  487. u8 SD_GetCSD(u8 *csd_data)
  488. {
  489. u8 r1;
  490. //发CMD9命令,读CSD
  491. r1 = SD_SendCommand(CMD9, 0, 0xFF);
  492. if(r1 != 0x00)
  493. {
  494. return r1; //没返回正确应答,则退出,报错
  495. }
  496. //接收16个字节的数据
  497. SD_ReceiveData(csd_data, 16, RELEASE);
  498. return 0;
  499. }
  500. /*******************************************************************************
  501. * Function Name : SD_GetCapacity
  502. * Description : 获取SD卡的容量
  503. * Input : None
  504. * Output : None
  505. * Return : u32 capacity
  506. * 0: 取容量出错
  507. *******************************************************************************/
  508. u32 SD_GetCapacity(void)
  509. {
  510. u8 csd[16];
  511. u32 Capacity;
  512. u8 r1;
  513. u16 i;
  514. u16 temp;
  515. //取CSD信息,如果期间出错,返回0
  516. if(SD_GetCSD(csd)!=0)
  517. {
  518. return 0;
  519. }
  520. //如果为SDHC卡,按照下面方式计算
  521. if((csd[0]&0xC0)==0x40)
  522. {
  523. Capacity = ((((u32)csd[8])<<8) + (u32)csd[9] + 1)*(u32)1024;
  524. }
  525. else
  526. {
  527. //下面代码为网上版本
  528. formula of the capacity///
  529. //
  530. // memory capacity = BLOCKNR * BLOCK_LEN
  531. //
  532. //BLOCKNR = (C_SIZE + 1)* MULT
  533. //
  534. // C_SIZE_MULT+2
  535. //MULT = 2
  536. //
  537. // READ_BL_LEN
  538. //BLOCK_LEN = 2
  539. /**********************************************/
  540. //C_SIZE
  541. i = csd[6]&0x03;
  542. i<<=8;
  543. i += csd[7];
  544. i<<=2;
  545. i += ((csd[8]&0xc0)>>6);
  546. //C_SIZE_MULT
  547. r1 = csd[9]&0x03;
  548. r1<<=1;
  549. r1 += ((csd[10]&0x80)>>7);
  550. //BLOCKNR
  551. r1+=2;
  552. temp = 1;
  553. while(r1)
  554. {
  555. temp*=2;
  556. r1--;
  557. }
  558. Capacity = ((u32)(i+1))*((u32)temp);
  559. // READ_BL_LEN
  560. i = csd[5]&0x0f;
  561. //BLOCK_LEN
  562. temp = 1;
  563. while(i)
  564. {
  565. temp*=2;
  566. i--;
  567. }
  568. //The final result
  569. Capacity *= (u32)temp;
  570. //Capacity /= 512;
  571. }
  572. return (u32)Capacity;
  573. }
  574. /*******************************************************************************
  575. * Function Name : SD_ReadSingleBlock
  576. * Description : 读SD卡的一个block
  577. * Input : u32 sector 取地址(sector值,非物理地址)
  578. * u8 *buffer 数据存储地址(大小至少512byte)
  579. * Output : None
  580. * Return : u8 r1
  581. * 0: 成功
  582. * other:失败
  583. *******************************************************************************/
  584. u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
  585. {
  586. u8 r1;
  587. //设置为高速模式
  588. SPI_SetSpeed(SPI_SPEED_HIGH);
  589. //如果不是SDHC,将sector地址转成byte地址
  590. //sector = sector<<9;
  591. r1 = SD_SendCommand(CMD17, sector, 0);//读命令
  592. if(r1 != 0x00)
  593. {
  594. return r1;
  595. }
  596. r1 = SD_ReceiveData(buffer, 512, RELEASE);
  597. if(r1 != 0)
  598. {
  599. return r1; //读数据出错!
  600. }
  601. else
  602. {
  603. return 0;
  604. }
  605. }
  606. /*******************************************************************************
  607. * Function Name : SD_WriteSingleBlock
  608. * Description : 写入SD卡的一个block
  609. * Input : u32 sector 扇区地址(sector值,非物理地址)
  610. * u8 *buffer 数据存储地址(大小至少512byte)
  611. * Output : None
  612. * Return : u8 r1
  613. * 0: 成功
  614. * other:失败
  615. *******************************************************************************/
  616. u8 SD_WriteSingleBlock(u32 sector, const u8 *data)
  617. {
  618. u8 r1;
  619. u16 i;
  620. u16 retry;
  621. //设置为高速模式
  622. SPI_SetSpeed(SPI_SPEED_HIGH);
  623. //如果不是SDHC,给定的是sector地址,将其转换成byte地址
  624. // if(SD_Type!=SD_TYPE_V2HC)
  625. // {
  626. // sector = sector<<9;
  627. // }
  628. r1 = SD_SendCommand(CMD24, sector, 0x00);
  629. if(r1 != 0x00)
  630. {
  631. return r1; //应答不正确,直接返回
  632. }
  633. //开始准备数据传输
  634. FLASH_SPI_CS_ENABLE();
  635. //先放3个空数据,等待SD卡准备好
  636. SPI_FLASH_SendByte(0xff);
  637. SPI_FLASH_SendByte(0xff);
  638. SPI_FLASH_SendByte(0xff);
  639. //放起始令牌0xFE
  640. SPI_FLASH_SendByte(0xFE);
  641. //放一个sector的数据
  642. for(i=0;i<512;i++)
  643. {
  644. SPI_FLASH_SendByte(*data++);
  645. }
  646. //发2个Byte的dummy CRC
  647. SPI_FLASH_SendByte(0xff);
  648. SPI_FLASH_SendByte(0xff);
  649. //等待SD卡应答
  650. r1 = SPI_FLASH_SendByte(0xff);
  651. if((r1&0x1F)!=0x05)
  652. {
  653. FLASH_SPI_CS_DISABLE();
  654. return r1;
  655. }
  656. //等待操作完成
  657. retry = 0;
  658. while(!SPI_FLASH_SendByte(0xff))
  659. {
  660. retry++;
  661. if(retry>0xfffe) //如果长时间写入没有完成,报错退出
  662. {
  663. FLASH_SPI_CS_DISABLE();
  664. return 1; //写入超时返回1
  665. }
  666. }
  667. //写入完成,片选置1
  668. FLASH_SPI_CS_DISABLE();
  669. SPI_FLASH_SendByte(0xff);
  670. return 0;
  671. }
  672. /*******************************************************************************
  673. * Function Name : SD_ReadMultiBlock
  674. * Description : 读SD卡的多个block
  675. * Input : u32 sector 取地址(sector值,非物理地址)
  676. * u8 *buffer 数据存储地址(大小至少512byte)
  677. * u8 count 连续读count个block
  678. * Output : None
  679. * Return : u8 r1
  680. * 0: 成功
  681. * other:失败
  682. *******************************************************************************/
  683. u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)
  684. {
  685. u8 r1;
  686. //设置为高速模式
  687. SPI_SetSpeed(SPI_SPEED_HIGH);
  688. //如果不是SDHC,将sector地址转成byte地址
  689. // sector = sector<<9;
  690. //SD_WaitReady();
  691. //发读多块命令
  692. r1 = SD_SendCommand(CMD18, sector, 0);//读命令
  693. if(r1 != 0x00)
  694. {
  695. return r1;
  696. }
  697. //开始接收数据
  698. do
  699. {
  700. if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)
  701. {
  702. break;
  703. }
  704. buffer += 512;
  705. } while(--count);
  706. //全部传输完毕,发送停止命令
  707. SD_SendCommand(CMD12, 0, 0);
  708. //释放总线
  709. FLASH_SPI_CS_DISABLE();
  710. SPI_FLASH_SendByte(0xFF);
  711. if(count != 0)
  712. {
  713. return count; //如果没有传完,返回剩余个数
  714. }
  715. else
  716. {
  717. return 0;
  718. }
  719. }
  720. /*******************************************************************************
  721. * Function Name : SD_WriteMultiBlock
  722. * Description : 写入SD卡的N个block
  723. * Input : u32 sector 扇区地址(sector值,非物理地址)
  724. * u8 *buffer 数据存储地址(大小至少512byte)
  725. * u8 count 写入的block数目
  726. * Output : None
  727. * Return : u8 r1
  728. * 0: 成功
  729. * other:失败
  730. *******************************************************************************/
  731. u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count)
  732. {
  733. u8 r1;
  734. u16 i;
  735. //设置为高速模式
  736. SPI_SetSpeed(SPI_SPEED_HIGH);
  737. //如果不是SDHC,给定的是sector地址,将其转换成byte地址
  738. // if(SD_Type != SD_TYPE_V2HC)
  739. // {
  740. // sector = sector<<9;
  741. // }
  742. //如果目标卡不是MMC卡,启用ACMD23指令使能预擦除
  743. if(SD_Type != SD_TYPE_MMC)
  744. {
  745. r1 = SD_SendCommand(ACMD23, count, 0x00);
  746. }
  747. //发多块写入指令
  748. r1 = SD_SendCommand(CMD25, sector, 0x00);
  749. if(r1 != 0x00)
  750. {
  751. return r1; //应答不正确,直接返回
  752. }
  753. //开始准备数据传输
  754. FLASH_SPI_CS_ENABLE();
  755. //先放3个空数据,等待SD卡准备好
  756. SPI_FLASH_SendByte(0xff);
  757. SPI_FLASH_SendByte(0xff);
  758. //--------下面是N个sector写入的循环部分
  759. do
  760. {
  761. //放起始令牌0xFC 表明是多块写入
  762. SPI_FLASH_SendByte(0xFC);
  763. //放一个sector的数据
  764. for(i=0;i<512;i++)
  765. {
  766. SPI_FLASH_SendByte(*data++);
  767. }
  768. //发2个Byte的dummy CRC
  769. SPI_FLASH_SendByte(0xff);
  770. SPI_FLASH_SendByte(0xff);
  771. //等待SD卡应答
  772. r1 = SPI_FLASH_SendByte(0xff);
  773. if((r1&0x1F)!=0x05)
  774. {
  775. FLASH_SPI_CS_DISABLE(); //如果应答为报错,则带错误代码直接退出
  776. return r1;
  777. }
  778. //等待SD卡写入完成
  779. if(SD_WaitReady()==1)
  780. {
  781. FLASH_SPI_CS_DISABLE(); //等待SD卡写入完成超时,直接退出报错
  782. return 1;
  783. }
  784. //本sector数据传输完成
  785. }while(--count);
  786. //发结束传输令牌0xFD
  787. r1 = SPI_FLASH_SendByte(0xFD);
  788. if(r1==0x00)
  789. {
  790. count = 0xfe;
  791. }
  792. if(SD_WaitReady())
  793. {
  794. while(1)
  795. {
  796. }
  797. }
  798. //写入完成,片选置1
  799. FLASH_SPI_CS_DISABLE();
  800. SPI_FLASH_SendByte(0xff);
  801. return count; //返回count值,如果写完则count=0,否则count=1
  802. }
  803. /* USER CODE END 1 */

SDCard.h 根据YS-F1Pro SPI Flash 改写 SD

  1. /* Define to prevent recursive inclusion -------------------------------------*/
  2. #ifndef __SDCard_H
  3. #define __SDCard_H
  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif
  7. /* Includes ------------------------------------------------------------------*/
  8. #include "main.h"
  9. /* USER CODE BEGIN Includes */
  10. /* 包含头文件 ----------------------------------------------------------------*/
  11. #include "stm32f1xx_hal.h"
  12. /* USER CODE END Includes */
  13. /* 类型定义 ------------------------------------------------------------------*/
  14. /* 宏定义 --------------------------------------------------------------------*/
  15. //#define SPI_FLASH_ID 0xEF3015 //W25X16 2MB
  16. //#define SPI_FLASH_ID 0xEF4015 //W25Q16 4MB
  17. //#define SPI_FLASH_ID 0XEF4017 //W25Q64 8MB
  18. #define SPI_FLASH_ID 0XEF4018 //W25Q128 16MB YS-F1Pro开发默认使用
  19. #define FLASH_SPIx SPI1
  20. #define FLASH_SPIx_RCC_CLK_ENABLE() __HAL_RCC_SPI1_CLK_ENABLE()
  21. #define FLASH_SPIx_RCC_CLK_DISABLE() __HAL_RCC_SPI1_CLK_DISABLE()
  22. #define FLASH_SPI_GPIO_ClK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
  23. #define FLASH_SPI_GPIO_PORT GPIOA
  24. #define FLASH_SPI_SCK_PIN GPIO_PIN_5
  25. #define FLASH_SPI_MISO_PIN GPIO_PIN_6
  26. #define FLASH_SPI_MOSI_PIN GPIO_PIN_7
  27. #define FLASH_SPI_CS_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
  28. #define FLASH_SPI_CS_PORT GPIOA
  29. #define FLASH_SPI_CS_PIN GPIO_PIN_4
  30. #define FLASH_SPI_CS_ENABLE() HAL_GPIO_WritePin(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN, GPIO_PIN_RESET)
  31. #define FLASH_SPI_CS_DISABLE() HAL_GPIO_WritePin(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN, GPIO_PIN_SET)
  32. /* 扩展变量 ------------------------------------------------------------------*/
  33. extern SPI_HandleTypeDef hspiflash;
  34. /* 函数声明 ------------------------------------------------------------------*/
  35. /* USER CODE BEGIN Private defines */
  36. /* USER CODE END Private defines */
  37. #define u8 uint8_t
  38. #define u16 uint16_t
  39. #define u32 uint32_t
  40. /* Private define ------------------------------------------------------------*/
  41. /* SD卡类型定义 */
  42. #define SD_TYPE_MMC 0
  43. #define SD_TYPE_V1 1
  44. #define SD_TYPE_V2 2
  45. #define SD_TYPE_V2HC 4
  46. /* SPI总线速度设置*/
  47. #define SPI_SPEED_LOW 0
  48. #define SPI_SPEED_HIGH 1
  49. /* SD传输数据结束后是否释放总线宏定义 */
  50. #define NO_RELEASE 0
  51. #define RELEASE 1
  52. /* SD卡指令表 */
  53. #define CMD0 0 //卡复位
  54. #define CMD9 9 //命令9 ,读CSD数据
  55. #define CMD10 10 //命令10,读CID数据
  56. #define CMD12 12 //命令12,停止数据传输
  57. #define CMD16 16 //命令16,设置SectorSize 应返回0x00
  58. #define CMD17 17 //命令17,读sector
  59. #define CMD18 18 //命令18,读Multi sector
  60. #define ACMD23 23 //命令23,设置多sector写入前预先擦除N个block
  61. #define CMD24 24 //命令24,写sector
  62. #define CMD25 25 //命令25,写Multi sector
  63. #define ACMD41 41 //命令41,应返回0x00
  64. #define CMD55 55 //命令55,应返回0x01
  65. #define CMD58 58 //命令58,读OCR信息
  66. #define CMD59 59 //命令59,使能/禁止CRC,应返回0x00
  67. /* Private macro -------------------------------------------------------------*/
  68. //SD卡CS片选使能端操作:
  69. #define SD_CS_ENABLE() GPIO_ResetBits(GPIOA,GPIO_PIN_4) //选中SD卡
  70. #define SD_CS_DISABLE() GPIO_SetBits(GPIOA,GPIO_PIN_4) //不选中SD卡
  71. //#define SD_PWR_ON() GPIO_ResetBits(GPIOD,GPIO_Pin_10) //SD卡上电
  72. //#define SD_PWR_OFF() GPIO_SetBits(GPIOD,GPIO_Pin_10) //SD卡断电
  73. //#define SD_DET() !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //检测有卡
  74. //1-有 0-无
  75. /* Private function prototypes -----------------------------------------------*/
  76. void SPI_Configuration(void);
  77. void SPI_SetSpeed(u8 SpeedSet);
  78. u8 SPI_ReadWriteByte(u8 TxData); //SPI总线读写一个字节
  79. u8 SD_WaitReady(void); //等待SD卡就绪
  80. u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc); //SD卡发送一个命令
  81. u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);
  82. u8 SD_Init(void); //SD卡初始化
  83. //
  84. u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡读数据
  85. u8 SD_GetCID(u8 *cid_data); //读SD卡CID
  86. u8 SD_GetCSD(u8 *csd_data); //读SD卡CSD
  87. u32 SD_GetCapacity(void); //取SD卡容量
  88. u8 SD_ReadSingleBlock(u32 sector, u8 *buffer); //读一个sector
  89. u8 SD_WriteSingleBlock(u32 sector, const u8 *buffer); //写一个sector
  90. u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count); //读多个sector
  91. u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count); //写多个sector
  92. /* USER CODE BEGIN Prototypes */
  93. extern u8 SD_Init(void);
  94. /* USER CODE END Prototypes */
  95. #ifdef __cplusplus
  96. }
  97. #endif
  98. #endif /*__ usart_H */

2、添加FATFS文件系统

7bebf0540f1e775cbc74cd38d1859365.png

3、修改FATFS文件系统SD卡驱动部分sdcard_diskio.c

  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "main.h"
  3. #include
  4. #include "SDCard.h"
  5. #include "ff_gen_drv.h"
  6. /* 私有类型定义 --------------------------------------------------------------*/
  7. /* 私有宏定义 ----------------------------------------------------------------*/
  8. #define BLOCK_SIZE 512
  9. /* 私有变量 ------------------------------------------------------------------*/
  10. static volatile DSTATUS Stat = STA_NOINIT;
  11. /* 扩展变量 ------------------------------------------------------------------*/
  12. /* 私有函数原形 --------------------------------------------------------------*/
  13. DSTATUS SD_initialize (BYTE);
  14. DSTATUS SD_status (BYTE);
  15. DRESULT SD_read (BYTE, BYTE*, DWORD, UINT);
  16. #if _USE_WRITE == 1 // 如果允许写操作
  17. DRESULT SD_write (BYTE, const BYTE*, DWORD, UINT);
  18. #endif /* _USE_WRITE == 1 */
  19. #if _USE_IOCTL == 1 // 如果输入输出操作控制
  20. DRESULT SD_ioctl (BYTE, BYTE, void*);
  21. #endif /* _USE_IOCTL == 1 */
  22. /* 定义SD卡接口函数 */
  23. const Diskio_drvTypeDef SD_Driver =
  24. {
  25. SD_initialize, // SD卡初始化
  26. SD_status, // SD卡状态获取
  27. SD_read, // SD卡读数据
  28. #if _USE_WRITE == 1
  29. SD_write, // SD卡写数据
  30. #endif /* _USE_WRITE == 1 */
  31. #if _USE_IOCTL == 1
  32. SD_ioctl, // 获取SD卡信息
  33. #endif /* _USE_IOCTL == 1 */
  34. };
  35. /* 函数体 --------------------------------------------------------------------*/
  36. /**
  37. * 函数功能: SD卡初始化配置
  38. * 输入参数: 无
  39. * 返 回 值: 无
  40. * 说 明: 无
  41. */
  42. //extern void MX_SPI1_Init(void);
  43. DSTATUS SD_initialize(BYTE lun)
  44. {
  45. Stat = STA_NOINIT;
  46. /* 初始化SDIO外设 */
  47. // MX_SPI1_Init();
  48. /* 获取SD卡状态 */
  49. int result;
  50. result = SD_Init();
  51. // if(HAL_SD_GetStatus(&hsdcard)==SD_TRANSFER_OK)
  52. // {
  53. // Stat &= ~STA_NOINIT;
  54. // }
  55. if (result == 0)
  56. {
  57. Stat = RES_OK;
  58. }
  59. else
  60. {
  61. Stat = RES_ERROR;
  62. }
  63. return Stat;
  64. }
  65. /**
  66. * 函数功能: SD卡状态获取
  67. * 输入参数: lun : 不用
  68. * 返 回 值: DSTATUS:SD卡状态返回值
  69. * 说 明: 无
  70. */
  71. DSTATUS SD_status(BYTE lun)
  72. {
  73. Stat = STA_NOINIT;
  74. // if(HAL_SD_GetStatus(&hsdcard) == SD_TRANSFER_OK)
  75. // {
  76. // Stat &= ~STA_NOINIT;
  77. // }
  78. Stat = RES_OK;
  79. return Stat;
  80. }
  81. /**
  82. * 函数功能: 从SD卡读取数据到缓冲区
  83. * 输入参数: lun : 不用
  84. * buff:存放读取到数据缓冲区指针
  85. * sector:扇区地址(LBA)
  86. * count:扇区数目
  87. * 返 回 值: DSTATUS:操作结果
  88. * 说 明: SD卡读操作使用DMA传输
  89. */
  90. DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
  91. {
  92. DRESULT res = RES_OK;
  93. // if((DWORD)buff&3)
  94. // {
  95. // DWORD scratch[BLOCK_SIZE/4];
  96. // while (count--)
  97. // {
  98. // res = SD_read(lun,(void *)scratch, sector++, 1);
  99. // if (res != RES_OK)
  100. // {
  101. // break;
  102. // }
  103. // memcpy(buff, scratch, BLOCK_SIZE);
  104. // buff += BLOCK_SIZE;
  105. // }
  106. // return res;
  107. // }
  108. //
  109. // if(HAL_SD_ReadBlocks_DMA(&hsdcard,(uint32_t*)buff,(uint64_t)(sector * BLOCK_SIZE),BLOCK_SIZE,count) != SD_OK)
  110. // {
  111. // res = RES_ERROR;
  112. // }
  113. // if(res==RES_OK)
  114. // {
  115. // if(HAL_SD_CheckReadOperation(&hsdcard, 0xFFFFFFFF) != SD_OK)
  116. // {
  117. // res = RES_ERROR;
  118. // }
  119. // }
  120. int result;
  121. if(count==1)
  122. {
  123. result=SD_ReadSingleBlock(sector,buff);
  124. }
  125. else
  126. {
  127. result = SD_ReadMultiBlock(sector, buff, count);
  128. }
  129. if (result == 0)
  130. {
  131. res = RES_OK;
  132. }
  133. else
  134. {
  135. res = RES_ERROR;
  136. }
  137. return res;
  138. }
  139. /**
  140. * 函数功能: 将缓冲区数据写入到SD卡内
  141. * 输入参数: lun : 不用
  142. * buff:存放待写入数据的缓冲区指针
  143. * sector:扇区地址(LBA)
  144. * count:扇区数目
  145. * 返 回 值: DSTATUS:操作结果
  146. * 说 明: SD卡写操作没有使用DMA传输
  147. */
  148. #if _USE_WRITE == 1
  149. DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
  150. {
  151. DRESULT res = RES_OK;
  152. // if((DWORD)buff&3)
  153. // {
  154. // DRESULT res = RES_OK;
  155. // DWORD scratch[BLOCK_SIZE / 4];
  156. // while (count--)
  157. // {
  158. // memcpy( scratch,buff,BLOCK_SIZE);
  159. // res = SD_write(lun,(void *)scratch, sector++, 1);
  160. // if (res != RES_OK)
  161. // {
  162. // break;
  163. // }
  164. // buff += BLOCK_SIZE;
  165. // }
  166. // return res;
  167. // }
  168. //
  169. // if(HAL_SD_WriteBlocks(&hsdcard,(uint32_t*)buff,(uint64_t)(sector * BLOCK_SIZE),BLOCK_SIZE, count) != SD_OK)
  170. // {
  171. // res = RES_ERROR;
  172. // }
  173. int result;
  174. if(count==1)
  175. {
  176. result=SD_WriteSingleBlock(sector, buff);
  177. }
  178. else
  179. {
  180. result = SD_WriteMultiBlock(sector, buff, count);
  181. }
  182. if (result == 0)
  183. {
  184. res = RES_OK;
  185. }
  186. else
  187. {
  188. res = RES_ERROR;
  189. }
  190. return res;
  191. }
  192. #endif /* _USE_WRITE == 1 */
  193. /**
  194. * 函数功能: 输入输出控制操作(I/O control operation)
  195. * 输入参数: lun : 不用
  196. * cmd:控制命令
  197. * buff:存放待写入或者读取数据的缓冲区指针
  198. * 返 回 值: DSTATUS:操作结果
  199. * 说 明: 无
  200. */
  201. #if _USE_IOCTL == 1
  202. DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff)
  203. {
  204. DRESULT res = RES_ERROR;
  205. // if (Stat & STA_NOINIT) return RES_NOTRDY;
  206. //
  207. // switch (cmd)
  208. // {
  209. // /* Make sure that no pending write process */
  210. // case CTRL_SYNC :
  211. //FLASH_SPI_CS_ENABLE();
  212. //if(SD_WaitReady()==0)
  213. //{
  214. //res = RES_OK;
  215. //}
  216. //else
  217. //{
  218. //res = RES_ERROR;
  219. //}
  220. FLASH_SPI_CSDISABLE();
  221. // break;
  222. //
  223. // /* 获取SD卡总扇区数目(DWORD) */
  224. // case GET_SECTOR_COUNT :
  225. //*(WORD*)buff = 512;
  226. //res = RES_OK;
  227. // break;
  228. //
  229. // /* 获取读写扇区大小(WORD) */
  230. // case GET_SECTOR_SIZE :
  231. //*(DWORD*)buff = SD_GetCapacity();
  232. //res = RES_OK;
  233. // break;
  234. //
  235. // /* 获取擦除块大小(DWORD) */
  236. // case GET_BLOCK_SIZE :
  237. // *(DWORD*)buff = BLOCK_SIZE;
  238. // break;
  239. //
  240. // default:
  241. // res = RES_PARERR;
  242. // }
  243. uint8_t CSD[16] = {0};
  244. uint8_t csddata[16] = {0};
  245. uint32_t csize;
  246. uint32_t Capacity;
  247. switch (cmd)
  248. {
  249. case CTRL_SYNC:
  250. res = RES_OK;
  251. break;
  252. case GET_SECTOR_COUNT:
  253. SD_GetCID(CSD);
  254. SD_GetCSD(csddata);
  255. //SDGetCIDCSD(CSD, csddata);
  256. csize = csddata[9] + ((uint32_t)csddata[8] << 8) + ((uint32_t)(csddata[7] & 0x3f) << 16) + 1;
  257. Capacity = csize << 9;
  258. *((DWORD *)buff) = Capacity;
  259. res = RES_OK;
  260. break;
  261. case GET_SECTOR_SIZE:
  262. *(WORD *)buff = 512; //spi flash的扇区大小是 512 Bytes
  263. return RES_OK;
  264. case GET_BLOCK_SIZE:
  265. *((DWORD *)buff) = 4096;
  266. res = RES_OK;
  267. break;
  268. default:
  269. res = RES_PARERR;
  270. break;
  271. }
  272. return res;
  273. }
  274. #endif /* _USE_IOCTL == 1 */

4、在Main.c文件中添加 测试应用程序

  1. char SPIFLASHPath[4]; /* 串行Flash逻辑设备路径 */
  2. char SDPath[4]; /* SD卡逻辑设备路径 */
  3. FATFS fs;/* FatFs文件系统对象 */
  4. FIL file;/* 文件对象 */
  5. FRESULT f_res; /* 文件操作结果 */
  6. UINT fnum; /* 文件成功读写数量 */
  7. BYTE ReadBuffer[1024]={0}; /* 读缓冲区 */
  8. BYTE WriteBuffer[]= "欢迎使用硬石STM32开发板 今天是个好日子,新建文件系统测试文件";/* 写缓冲区*/
  9. extern Diskio_drvTypeDef SD_Driver;

添加文件系统操作结果处理

  1. /**
  2. * 函数功能: FatFS文件系统操作结果信息处理.
  3. * 输入参数: FatFS文件系统操作结果:FRESULT
  4. * 返 回 值: 无
  5. * 说 明: 无
  6. */
  7. static void printf_fatfs_error(FRESULT fresult)
  8. {
  9. switch(fresult)
  10. {
  11. case FR_OK: //(0)
  12. printf("》操作成功。");
  13. break;
  14. case FR_DISK_ERR: //(1)
  15. printf("!!硬件输入输出驱动出错。");
  16. break;
  17. case FR_INT_ERR: //(2)
  18. printf("!!断言错误。");
  19. break;
  20. case FR_NOT_READY: //(3)
  21. printf("!!物理设备无法工作。");
  22. break;
  23. case FR_NO_FILE: //(4)
  24. printf("!!无法找到文件。");
  25. break;
  26. case FR_NO_PATH: //(5)
  27. printf("!!无法找到路径。");
  28. break;
  29. case FR_INVALID_NAME: //(6)
  30. printf("!!无效的路径名。");
  31. break;
  32. case FR_DENIED: //(7)
  33. case FR_EXIST: //(8)
  34. printf("!!拒绝访问。");
  35. break;
  36. case FR_INVALID_OBJECT: //(9)
  37. printf("!!无效的文件或路径。");
  38. break;
  39. case FR_WRITE_PROTECTED: //(10)
  40. printf("!!逻辑设备写保护。");
  41. break;
  42. case FR_INVALID_DRIVE: //(11)
  43. printf("!!无效的逻辑设备。");
  44. break;
  45. case FR_NOT_ENABLED: //(12)
  46. printf("!!无效的工作区。");
  47. break;
  48. case FR_NO_FILESYSTEM: //(13)
  49. printf("!!无效的文件系统。");
  50. break;
  51. case FR_MKFS_ABORTED: //(14)
  52. printf("!!因函数参数问题导致f_mkfs函数操作失败。");
  53. break;
  54. case FR_TIMEOUT: //(15)
  55. printf("!!操作超时。");
  56. break;
  57. case FR_LOCKED: //(16)
  58. printf("!!文件被保护。");
  59. break;
  60. case FR_NOT_ENOUGH_CORE: //(17)
  61. printf("!!长文件名支持获取堆空间失败。");
  62. break;
  63. case FR_TOO_MANY_OPEN_FILES: //(18)
  64. printf("!!打开太多文件。");
  65. break;
  66. case FR_INVALID_PARAMETER: // (19)
  67. printf("!!参数无效。");
  68. break;
  69. }
  70. }

添加测试程序:

  1. /* 注册一个FatFS设备:SD卡 */
  2. if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
  3. {
  4. //在SD卡挂载文件系统,文件系统挂载时会对SD卡初始化
  5. f_res = f_mount(&fs,(TCHAR const*)SDPath,1);
  6. printf_fatfs_error(f_res);
  7. /*----------------------- 格式化测试 ---------------------------*/
  8. /* 如果没有文件系统就格式化创建创建文件系统 */
  9. if(f_res == FR_NO_FILESYSTEM)
  10. {
  11. printf("》SD卡还没有文件系统,即将进行格式化...");
  12. /* 格式化 */
  13. f_res=f_mkfs((TCHAR const*)SDPath,0,0);
  14. if(f_res == FR_OK)
  15. {
  16. printf("》SD卡已成功格式化文件系统。");
  17. /* 格式化后,先取消挂载 */
  18. f_res = f_mount(NULL,(TCHAR const*)SDPath,1);
  19. /* 重新挂载*/
  20. f_res = f_mount(&fs,(TCHAR const*)SDPath,1);
  21. }
  22. else
  23. {
  24. printf("《《格式化失败。》》");
  25. while(1);
  26. }
  27. }
  28. else if(f_res!=FR_OK)
  29. {
  30. printf("!!SD卡挂载文件系统失败。(%d)",f_res);
  31. printf_fatfs_error(f_res);
  32. while(1);
  33. }
  34. else
  35. {
  36. printf("》文件系统挂载成功,可以进行读写测试");
  37. }
  38. /*----------------------- 文件系统测试:写测试 -----------------------------*/
  39. /* 打开文件,如果文件不存在则创建它 */
  40. printf("****** 即将进行文件写入测试... ******");
  41. f_res = f_open(&file, "FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );
  42. if ( f_res == FR_OK )
  43. {
  44. printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。");
  45. /* 将指定存储区内容写入到文件内 */
  46. f_res=f_write(&file,WriteBuffer,sizeof(WriteBuffer),&fnum);
  47. if(f_res==FR_OK)
  48. {
  49. printf("》文件写入成功,写入字节数据:%d",fnum);
  50. printf("》向文件写入的数据为:%s",WriteBuffer);
  51. }
  52. else
  53. {
  54. printf("!!文件写入失败:(%d)",f_res);
  55. }
  56. /* 不再读写,关闭文件 */
  57. f_close(&file);
  58. }
  59. else
  60. {
  61. printf("!!打开/创建文件失败。");
  62. }
  63. /*------------------- 文件系统测试:读测试 ------------------------------------*/
  64. printf("****** 即将进行文件读取测试... ******");
  65. f_res = f_open(&file, "FatFs读写测试文件.txt", FA_OPEN_EXISTING | FA_READ);
  66. if(f_res == FR_OK)
  67. {
  68. printf("》打开文件成功。");
  69. f_res = f_read(&file, ReadBuffer, sizeof(ReadBuffer), &fnum);
  70. if(f_res==FR_OK)
  71. {
  72. printf("》文件读取成功,读到字节数据:%d",fnum);
  73. printf("》读取得的文件数据为:%s ", ReadBuffer);
  74. }
  75. else
  76. {
  77. printf("!!文件读取失败:(%d)",f_res);
  78. }
  79. }
  80. else
  81. {
  82. printf("!!打开文件失败。");
  83. }
  84. /* 不再读写,关闭文件 */
  85. f_close(&file);
  86. /* 不再使用,取消挂载 */
  87. f_res = f_mount(NULL,(TCHAR const*)SDPath,1);
  88. }
  89. /* 注销一个FatFS设备:SD卡 */
  90. FATFS_UnLinkDriver(SDPath);

3、使用串口查看测试结果

d29ca11f39a63657e34cf48376ebc5c6.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值