1、添加SD卡SPI模式驅動
- /**
- * @brief SPI1 Initialization Function
- * @param None
- * @retval None
- */
- static void MX_SPI1_Init(void)
- {
- /* USER CODE BEGIN SPI1_Init 0 */
- /* USER CODE END SPI1_Init 0 */
- /* USER CODE BEGIN SPI1_Init 1 */
- /* USER CODE END SPI1_Init 1 */
- /* SPI1 parameter configuration*/
- 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_HARD_OUTPUT;
- 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();
- }
- /* USER CODE BEGIN SPI1_Init 2 */
- /* USER CODE END SPI1_Init 2 */
- }
編寫SD卡SPI驅動 SDCard.c
- #include "main.h"
- #include "SDCard.h"
- /* USER CODE BEGIN 0 */
- /* USER CODE END 0 */
- /* USART1 init function */
- /**************************************************************************/
- #define Dummy_Byte 0xFF
- /* 私有變量 ------------------------------------------------------------------*/
- SPI_HandleTypeDef hspiflash;
- extern SPI_HandleTypeDef hspi1;
- u8 SD_Type=0;
- /* function ------------------------------------------------------------------*/
- /**
- * 函數功能: 從串行Flash讀取一個字節數據
- * 輸入參數: 無
- * 返 回 值: uint8_t:讀取到的數據
- * 說 明:This function must be used only if the Start_Read_Sequence
- * function has been previously called.
- */
- uint8_t SPI_FLASH_ReadByte(void)
- {
- uint8_t d_read,d_send=Dummy_Byte;
- if(HAL_SPI_TransmitReceive(&hspiflash,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
- d_read=Dummy_Byte;
- return d_read;
- }
- void SPI_I2S_SendData(SPI_TypeDef* SPIx, u16 Data)
- {
- /* Check the parameters */
- assert_param(IS_SPI_ALL_PERIPH(SPIx));
- /* Write in the DR register the data to be sent */
- SPIx->DR = Data;
- }
- u16 SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
- {
- /* Check the parameters */
- assert_param(IS_SPI_ALL_PERIPH(SPIx));
- //assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
- /* Return the data in the DR register */
- return SPIx->DR;
- }
- /**
- * 函數功能: 往串行Flash讀取寫入一個字節數據並接收一個字節數據
- * 輸入參數: byte:待發送數據
- * 返 回 值: uint8_t:接收到的數據
- * 說 明:無
- */
- uint8_t SPI_FLASH_SendByte(uint8_t byte)
- {
- uint8_t d_read,d_send=byte;
- // if(HAL_SPI_TransmitReceive(&hspiflash,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
- //{
- //d_read=Dummy_Byte;
- //}
- //等待發送緩衝區空
- // while(__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE));
- //發一個字節
- // SPI_I2S_SendData(SPI1, d_send);
- HAL_SPI_Transmit(&hspi1,&d_send,1,1000);
- //HAL_SPI_Receive(&hspi1,&d_read,1,1000);
- //等待數據接收
- while(__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE));
- //取數據
- d_read = SPI_I2S_ReceiveData(SPI1);
- return d_read;
- }
- /*******************************************************************************
- * Function Name : SD_WaitReady
- * Description : 等待SD卡Ready
- * Input : None
- * Output : None
- * Return : u8
- * 0: 成功
- * other:失敗
- *******************************************************************************/
- u8 SD_WaitReady(void)
- {
- u8 r1;
- u16 retry;
- retry = 0;
- do
- {
- r1 = SPI_FLASH_SendByte(0xFF);
- if(retry==0xfffe)
- {
- return 1;
- }
- }while(r1!=0xFF);
- return 0;
- }
- /*******************************************************************************
- * Function Name : SD_SendCommand
- * Description : 向SD卡發送一個命令
- * Input : u8 cmd 命令
- * u32 arg 命令參數
- * u8 crc crc校驗值
- * Output : None
- * Return : u8 r1 SD卡返回的響應
- *******************************************************************************/
- u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
- {
- unsigned char r1;
- unsigned char Retry = 0;
- //????????
- SPI_FLASH_SendByte(0xff);
- //片選端置低,選中SD卡
- FLASH_SPI_CS_ENABLE();
- //發送
- SPI_FLASH_SendByte(cmd | 0x40); //分別寫入命令
- SPI_FLASH_SendByte(arg >> 24);
- SPI_FLASH_SendByte(arg >> 16);
- SPI_FLASH_SendByte(arg >> 8);
- SPI_FLASH_SendByte(arg);
- SPI_FLASH_SendByte(crc);
- //等待響應,或超時退出
- while((r1 = SPI_FLASH_SendByte(0xFF))==0xFF)
- {
- Retry++;
- if(Retry > 200)
- {
- break;
- }
- }
- //關閉片選
- FLASH_SPI_CS_DISABLE();
- //在總線上額外增加8個時鐘,讓SD卡完成剩下的工作
- SPI_FLASH_SendByte(0xFF);
- //返回狀態值
- return r1;
- }
- /*******************************************************************************
- * Function Name : SD_SendCommand_NoDeassert
- * Description : 向SD卡發送一個命令(結束是不失能片選,還有後續數據傳來)
- * Input : u8 cmd 命令
- * u32 arg 命令參數
- * u8 crc crc校驗值
- * Output : None
- * Return : u8 r1 SD卡返回的響應
- *******************************************************************************/
- u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
- {
- unsigned char r1;
- unsigned char Retry = 0;
- //????????
- SPI_FLASH_SendByte(0xff);
- //片選端置低,選中SD卡
- FLASH_SPI_CS_ENABLE();
- //發送
- SPI_FLASH_SendByte(cmd | 0x40); //分別寫入命令
- SPI_FLASH_SendByte(arg >> 24);
- SPI_FLASH_SendByte(arg >> 16);
- SPI_FLASH_SendByte(arg >> 8);
- SPI_FLASH_SendByte(arg);
- SPI_FLASH_SendByte(crc);
- //等待響應,或超時退出
- while((r1 = SPI_FLASH_SendByte(0xFF))==0xFF)
- {
- Retry++;
- if(Retry > 200)
- {
- break;
- }
- }
- //返回響應值
- return r1;
- }
- void SPI_SetSpeed(u8 SpeedSet)
- {
- 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_HARD_OUTPUT;
- //如果速度設置輸入0,則低速模式,非0則高速模式
- if(SpeedSet==SPI_SPEED_LOW)
- {
- hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
- }
- else
- {
- hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
- }
- 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();
- }
- // if(SpeedSet==SPI_SPEED_LOW)
- //{
- // hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
- //}
- //else
- //{
- //hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
- //}
- //HAL_SPI_Init(&hspi1);
- //moon.mp3: 4707774 Byte size 目標文件 設為buffer[512]
- //speed:實驗測試數據,最大速度 392314 Byte/S,
- //Prescaler_128, 59592 Byte/S
- //Prescaler_64, 104617 Byte/S
- //Prescaler_32, 168134 Byte/S 162337 Byte/S
- //Prescaler_16, 261543 Byte/S 247777 Byte/S
- //Prescaler_8, 313851 Byte/S 336269 Byte/S
- //Prescaler_4, 392314 Byte/S 392314 Byte/S
- //Prescaler_2, 392314 Byte/S
- }
- /*******************************************************************************
- * Function Name : SD_Init
- * Description : 初始化SD卡
- * Input : None
- * Output : None
- * Return : u8
- * 0:NO_ERR
- * 1:TIME_OUT
- * 99:NO_CARD
- *******************************************************************************/
- u8 SD_Init(void)
- {
- u16 i; // 用來循環計數
- u8 r1; // 存放SD卡的返回值
- u16 retry; // 用來進行超時計數
- u8 buff[6];
- //如果沒有檢測到卡插入,直接退出,返回錯誤標誌
- // if(!SD_DET())
- // {
- // //return 99;
- // return STA_NODISK; // FatFS錯誤標誌:沒有插入磁盤
- // }
- //SD卡上電
- //SD_PWR_ON();
- // 純延時,等待SD卡上電完成
- //for(i=0;i<0xf00;i++);
- /*******************************************************
- //這個地方要加一句,設置SPI速度為低速。
- //為什麼有的卡可以呢?因為SPI初始化時是低速的,SD卡初始化
- //完成後設置為高速,有的卡只要初始化一次就行,程序就ok;
- //但有的卡需要多次復位,呵呵,這個地方差這一句,
- //這種卡就用不成咯!
- *******************************************************/
- SPI_SetSpeed(0); //設置SPI速度為低速
- //先產生>74個脈衝,讓SD卡自己初始化完成
- for(i=0;i<100;i++)
- {
- SPI_FLASH_SendByte(0xFF);
- }
- //-----------------SD卡復位到idle開始-----------------
- //循環連續發送CMD0,直到SD卡返回0x01,進入IDLE狀態
- //超時則直接退出
- retry = 0;
- do
- {
- //發送CMD0,讓SD卡進入IDLE狀態
- r1 = SD_SendCommand(CMD0, 0, 0x95);
- retry++;
- }while((r1 != 0x01) && (retry<200));
- //跳出循環後,檢查原因:初始化成功?or 重試超時?
- if(retry==200)
- {
- return 1; //超時返回1
- }
- //-----------------SD卡復位到idle結束-----------------
- //獲取卡片的SD版本信息
- r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);
- //如果卡片版本信息是v1.0版本的,即r1=0x05,則進行以下初始化
- if(r1 == 0x05)
- {
- printf("\\r\\n SD卡版本信息:V1.0 \\r\\n");
- //設置卡類型為SDV1.0,如果後面檢測到為MMC卡,再修改為MMC
- SD_Type = SD_TYPE_V1;
- //如果是V1.0卡,CMD8指令後沒有後續數據
- //片選置高,結束本次命令
- FLASH_SPI_CS_DISABLE();
- //多發8個CLK,讓SD結束後續操作
- SPI_FLASH_SendByte(0xFF);
- //-----------------SD卡、MMC卡初始化開始-----------------
- //髮卡初始化指令CMD55+ACMD41
- // 如果有應答,說明是SD卡,且初始化完成
- // 沒有回應,說明是MMC卡,額外進行相應初始化
- retry = 0;
- do
- {
- //先發CMD55,應返回0x01;否則出錯
- r1 = SD_SendCommand(CMD55, 0, 0);
- if(r1 != 0x01)
- {
- return r1;
- }
- //得到正確響應後,發ACMD41,應得到返回值0x00,否則重試200次
- r1 = SD_SendCommand(ACMD41, 0, 0);
- retry++;
- }while((r1!=0x00) && (retry<400));
- // 判斷是超時還是得到正確回應
- // 若有回應:是SD卡;沒有回應:是MMC卡
- //----------MMC卡額外初始化操作開始------------
- if(retry==400)
- {
- printf("\\r\\n SD卡信息: MMC卡 \\r\\n");
- retry = 0;
- //發送MMC卡初始化命令(沒有測試)
- do
- {
- r1 = SD_SendCommand(1, 0, 0);
- retry++;
- }while((r1!=0x00)&& (retry<400));
- if(retry==400)
- {
- return 1; //MMC卡初始化超時
- }
- //寫入卡類型
- SD_Type = SD_TYPE_MMC;
- }
- else
- {
- printf("\\r\\n SD卡信息: SD卡 \\r\\n");
- }
- //----------MMC卡額外初始化操作結束------------
- //設置SPI為高速模式
- SPI_SetSpeed(1);
- SPI_FLASH_SendByte(0xFF);
- //禁止CRC校驗
- /*
- r1 = SD_SendCommand(CMD59, 0, 0x01);
- if(r1 != 0x00)
- {
- return r1; //命令錯誤,返回r1
- }
- */
- //設置Sector Size
- r1 = SD_SendCommand(CMD16, 512, 0xff);
- if(r1 != 0x00)
- {
- return r1; //命令錯誤,返回r1
- }
- //-----------------SD卡、MMC卡初始化結束-----------------
- }//SD卡為V1.0版本的初始化結束
- //下面是V2.0卡的初始化
- //其中需要讀取OCR數據,判斷是SD2.0還是SD2.0HC卡
- else if(r1 == 0x01)
- {
- printf("\\r\\n SD卡版本信息:V2.0 \\r\\n");
- //V2.0的卡,CMD8命令後會傳回4字節的數據,要跳過再結束本命令
- buff[0] = SPI_FLASH_SendByte(0xFF); //should be 0x00
- buff[1] = SPI_FLASH_SendByte(0xFF); //should be 0x00
- buff[2] = SPI_FLASH_SendByte(0xFF); //should be 0x01
- buff[3] = SPI_FLASH_SendByte(0xFF); //should be 0xAA
- FLASH_SPI_CS_DISABLE();
- //the next 8 clocks
- SPI_FLASH_SendByte(0xFF);
- //判斷該卡是否支持2.7V-3.6V的電壓範圍
- if(buff[2]==0x01 && buff[3]==0xAA)
- {
- //支持電壓範圍,可以操作
- retry = 0;
- //髮卡初始化指令CMD55+ACMD41
- do
- {
- r1 = SD_SendCommand(CMD55, 0, 0);
- if(r1!=0x01)
- {
- return r1;
- }
- r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
- if(retry>200)
- {
- return r1; //超時則返回r1狀態
- }
- }while(r1!=0);
- //初始化指令發送完成,接下來獲取OCR信息
- //-----------鑑別SD2.0卡版本開始-----------
- r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
- if(r1!=0x00)
- {
- return r1; //如果命令沒有返回正確應答,直接退出,返回應答
- }
- //讀OCR指令發出後,緊接著是4字節的OCR信息
- buff[0] = SPI_FLASH_SendByte(0xFF);
- buff[1] = SPI_FLASH_SendByte(0xFF);
- buff[2] = SPI_FLASH_SendByte(0xFF);
- buff[3] = SPI_FLASH_SendByte(0xFF);
- //OCR接收完成,片選置高
- FLASH_SPI_CS_DISABLE();
- SPI_FLASH_SendByte(0xFF);
- //檢查接收到的OCR中的bit30位(CCS),確定其為SD2.0還是SDHC
- //如果CCS=1:SDHC CCS=0:SD2.0
- if(buff[0]&0x40) //檢查CCS
- {
- SD_Type = SD_TYPE_V2HC;
- printf("\\r\\n SD卡信息: SDHC \\r\\n");
- }
- else
- {
- SD_Type = SD_TYPE_V2;
- printf("\\r\\n SD卡信息: SD2.0 \\r\\n");
- }
- //-----------鑑別SD2.0卡版本結束-----------
- //設置SPI為高速模式
- SPI_SetSpeed(1);
- }
- }
- return r1;
- }
- /*******************************************************************************
- * Function Name : SD_ReceiveData
- * Description : 從SD卡中讀回指定長度的數據,放置在給定位置
- * Input : u8 *data(存放讀回數據的內存>len)
- * u16 len(數據長度)
- * u8 release(傳輸完成後是否釋放總線CS置高 0:不釋放 1:釋放)
- * Output : None
- * Return : u8
- * 0:NO_ERR
- * other:錯誤信息
- *******************************************************************************/
- u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
- {
- u16 retry;
- u8 r1;
- // 啟動一次傳輸
- FLASH_SPI_CS_ENABLE();
- //等待SD卡發回數據起始令牌0xFE
- retry = 0;
- do
- {
- r1 = SPI_FLASH_SendByte(0xFF);
- retry++;
- if(retry>2000) //2000次等待後沒有應答,退出報錯
- {
- FLASH_SPI_CS_DISABLE();
- return 1;
- }
- }while(r1 != 0xFE);
- //開始接收數據
- while(len--)
- {
- *data = SPI_FLASH_SendByte(0xFF);
- data++;
- }
- //下面是2個偽CRC(dummy CRC)
- SPI_FLASH_SendByte(0xFF);
- SPI_FLASH_SendByte(0xFF);
- //按需釋放總線,將CS置高
- if(release == RELEASE)
- {
- //傳輸結束
- FLASH_SPI_CS_DISABLE();
- SPI_FLASH_SendByte(0xFF);
- }
- return 0;
- }
- /*******************************************************************************
- * Function Name : SD_GetCID
- * Description : 獲取SD卡的CID信息,包括製造商信息
- * Input : u8 *cid_data(存放CID的內存,至少16Byte)
- * Output : None
- * Return : u8
- * 0:NO_ERR
- * 1:TIME_OUT
- * other:錯誤信息
- *******************************************************************************/
- u8 SD_GetCID(u8 *cid_data)
- {
- u8 r1;
- //發CMD10命令,讀CID
- r1 = SD_SendCommand(CMD10, 0, 0xFF);
- if(r1 != 0x00)
- {
- return r1; //沒返回正確應答,則退出,報錯
- }
- //接收16個字節的數據
- SD_ReceiveData(cid_data, 16, RELEASE);
- return 0;
- }
- /*******************************************************************************
- * Function Name : SD_GetCSD
- * Description : 獲取SD卡的CSD信息,包括容量和速度信息
- * Input : u8 *cid_data(存放CID的內存,至少16Byte)
- * Output : None
- * Return : u8
- * 0:NO_ERR
- * 1:TIME_OUT
- * other:錯誤信息
- *******************************************************************************/
- u8 SD_GetCSD(u8 *csd_data)
- {
- u8 r1;
- //發CMD9命令,讀CSD
- r1 = SD_SendCommand(CMD9, 0, 0xFF);
- if(r1 != 0x00)
- {
- return r1; //沒返回正確應答,則退出,報錯
- }
- //接收16個字節的數據
- SD_ReceiveData(csd_data, 16, RELEASE);
- return 0;
- }
- /*******************************************************************************
- * Function Name : SD_GetCapacity
- * Description : 獲取SD卡的容量
- * Input : None
- * Output : None
- * Return : u32 capacity
- * 0: 取容量出錯
- *******************************************************************************/
- u32 SD_GetCapacity(void)
- {
- u8 csd[16];
- u32 Capacity;
- u8 r1;
- u16 i;
- u16 temp;
- //取CSD信息,如果期間出錯,返回0
- if(SD_GetCSD(csd)!=0)
- {
- return 0;
- }
- //如果為SDHC卡,按照下面方式計算
- if((csd[0]&0xC0)==0x40)
- {
- Capacity = ((((u32)csd[8])<<8) + (u32)csd[9] + 1)*(u32)1024;
- }
- else
- {
- //下面代碼為網上版本
- ////////////formula of the capacity///////////////
- //
- // memory capacity = BLOCKNR * BLOCK_LEN
- //
- //BLOCKNR = (C_SIZE + 1)* MULT
- //
- // C_SIZE_MULT+2
- //MULT = 2
- //
- // READ_BL_LEN
- //BLOCK_LEN = 2
- /**********************************************/
- //C_SIZE
- i = csd[6]&0x03;
- i<<=8;
- i += csd[7];
- i<<=2;
- i += ((csd[8]&0xc0)>>6);
- //C_SIZE_MULT
- r1 = csd[9]&0x03;
- r1<<=1;
- r1 += ((csd[10]&0x80)>>7);
- //BLOCKNR
- r1+=2;
- temp = 1;
- while(r1)
- {
- temp*=2;
- r1--;
- }
- Capacity = ((u32)(i+1))*((u32)temp);
- // READ_BL_LEN
- i = csd[5]&0x0f;
- //BLOCK_LEN
- temp = 1;
- while(i)
- {
- temp*=2;
- i--;
- }
- //The final result
- Capacity *= (u32)temp;
- //Capacity /= 512;
- }
- return (u32)Capacity;
- }
- /*******************************************************************************
- * Function Name : SD_ReadSingleBlock
- * Description : 讀SD卡的一個block
- * Input : u32 sector 取地址(sector值,非物理地址)
- * u8 *buffer 數據存儲地址(大小至少512byte)
- * Output : None
- * Return : u8 r1
- * 0: 成功
- * other:失敗
- *******************************************************************************/
- u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
- {
- u8 r1;
- //設置為高速模式
- SPI_SetSpeed(SPI_SPEED_HIGH);
- //如果不是SDHC,將sector地址轉成byte地址
- //sector = sector<<9;
- r1 = SD_SendCommand(CMD17, sector, 0);//讀命令
- if(r1 != 0x00)
- {
- return r1;
- }
- r1 = SD_ReceiveData(buffer, 512, RELEASE);
- if(r1 != 0)
- {
- return r1; //讀數據出錯!
- }
- else
- {
- return 0;
- }
- }
- /*******************************************************************************
- * Function Name : SD_WriteSingleBlock
- * Description : 寫入SD卡的一個block
- * Input : u32 sector 扇區地址(sector值,非物理地址)
- * u8 *buffer 數據存儲地址(大小至少512byte)
- * Output : None
- * Return : u8 r1
- * 0: 成功
- * other:失敗
- *******************************************************************************/
- u8 SD_WriteSingleBlock(u32 sector, const u8 *data)
- {
- u8 r1;
- u16 i;
- u16 retry;
- //設置為高速模式
- SPI_SetSpeed(SPI_SPEED_HIGH);
- //如果不是SDHC,給定的是sector地址,將其轉換成byte地址
- // if(SD_Type!=SD_TYPE_V2HC)
- // {
- // sector = sector<<9;
- // }
- r1 = SD_SendCommand(CMD24, sector, 0x00);
- if(r1 != 0x00)
- {
- return r1; //應答不正確,直接返回
- }
- //開始準備數據傳輸
- FLASH_SPI_CS_ENABLE();
- //先放3個空數據,等待SD卡準備好
- SPI_FLASH_SendByte(0xff);
- SPI_FLASH_SendByte(0xff);
- SPI_FLASH_SendByte(0xff);
- //放起始令牌0xFE
- SPI_FLASH_SendByte(0xFE);
- //放一個sector的數據
- for(i=0;i<512;i++)
- {
- SPI_FLASH_SendByte(*data++);
- }
- //發2個Byte的dummy CRC
- SPI_FLASH_SendByte(0xff);
- SPI_FLASH_SendByte(0xff);
- //等待SD卡應答
- r1 = SPI_FLASH_SendByte(0xff);
- if((r1&0x1F)!=0x05)
- {
- FLASH_SPI_CS_DISABLE();
- return r1;
- }
- //等待操作完成
- retry = 0;
- while(!SPI_FLASH_SendByte(0xff))
- {
- retry++;
- if(retry>0xfffe) //如果長時間寫入沒有完成,報錯退出
- {
- FLASH_SPI_CS_DISABLE();
- return 1; //寫入超時返回1
- }
- }
- //寫入完成,片選置1
- FLASH_SPI_CS_DISABLE();
- SPI_FLASH_SendByte(0xff);
- return 0;
- }
- /*******************************************************************************
- * Function Name : SD_ReadMultiBlock
- * Description : 讀SD卡的多個block
- * Input : u32 sector 取地址(sector值,非物理地址)
- * u8 *buffer 數據存儲地址(大小至少512byte)
- * u8 count 連續讀count個block
- * Output : None
- * Return : u8 r1
- * 0: 成功
- * other:失敗
- *******************************************************************************/
- u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)
- {
- u8 r1;
- //設置為高速模式
- SPI_SetSpeed(SPI_SPEED_HIGH);
- //如果不是SDHC,將sector地址轉成byte地址
- // sector = sector<<9;
- //SD_WaitReady();
- //發讀多塊命令
- r1 = SD_SendCommand(CMD18, sector, 0);//讀命令
- if(r1 != 0x00)
- {
- return r1;
- }
- //開始接收數據
- do
- {
- if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)
- {
- break;
- }
- buffer += 512;
- } while(--count);
- //全部傳輸完畢,發送停止命令
- SD_SendCommand(CMD12, 0, 0);
- //釋放總線
- FLASH_SPI_CS_DISABLE();
- SPI_FLASH_SendByte(0xFF);
- if(count != 0)
- {
- return count; //如果沒有傳完,返回剩餘個數
- }
- else
- {
- return 0;
- }
- }
- /*******************************************************************************
- * Function Name : SD_WriteMultiBlock
- * Description : 寫入SD卡的N個block
- * Input : u32 sector 扇區地址(sector值,非物理地址)
- * u8 *buffer 數據存儲地址(大小至少512byte)
- * u8 count 寫入的block數目
- * Output : None
- * Return : u8 r1
- * 0: 成功
- * other:失敗
- *******************************************************************************/
- u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count)
- {
- u8 r1;
- u16 i;
- //設置為高速模式
- SPI_SetSpeed(SPI_SPEED_HIGH);
- //如果不是SDHC,給定的是sector地址,將其轉換成byte地址
- // if(SD_Type != SD_TYPE_V2HC)
- // {
- // sector = sector<<9;
- // }
- //如果目標卡不是MMC卡,啟用ACMD23指令使能預擦除
- if(SD_Type != SD_TYPE_MMC)
- {
- r1 = SD_SendCommand(ACMD23, count, 0x00);
- }
- //發多塊寫入指令
- r1 = SD_SendCommand(CMD25, sector, 0x00);
- if(r1 != 0x00)
- {
- return r1; //應答不正確,直接返回
- }
- //開始準備數據傳輸
- FLASH_SPI_CS_ENABLE();
- //先放3個空數據,等待SD卡準備好
- SPI_FLASH_SendByte(0xff);
- SPI_FLASH_SendByte(0xff);
- //--------下面是N個sector寫入的循環部分
- do
- {
- //放起始令牌0xFC 表明是多塊寫入
- SPI_FLASH_SendByte(0xFC);
- //放一個sector的數據
- for(i=0;i<512;i++)
- {
- SPI_FLASH_SendByte(*data++);
- }
- //發2個Byte的dummy CRC
- SPI_FLASH_SendByte(0xff);
- SPI_FLASH_SendByte(0xff);
- //等待SD卡應答
- r1 = SPI_FLASH_SendByte(0xff);
- if((r1&0x1F)!=0x05)
- {
- FLASH_SPI_CS_DISABLE(); //如果應答為報錯,則帶錯誤代碼直接退出
- return r1;
- }
- //等待SD卡寫入完成
- if(SD_WaitReady()==1)
- {
- FLASH_SPI_CS_DISABLE(); //等待SD卡寫入完成超時,直接退出報錯
- return 1;
- }
- //本sector數據傳輸完成
- }while(--count);
- //髮結束傳輸令牌0xFD
- r1 = SPI_FLASH_SendByte(0xFD);
- if(r1==0x00)
- {
- count = 0xfe;
- }
- if(SD_WaitReady())
- {
- while(1)
- {
- }
- }
- //寫入完成,片選置1
- FLASH_SPI_CS_DISABLE();
- SPI_FLASH_SendByte(0xff);
- return count; //返回count值,如果寫完則count=0,否則count=1
- }
- /* USER CODE END 1 */
SDCard.h 根據YS-F1Pro SPI Flash 改寫 SD
- /* Define to prevent recursive inclusion -------------------------------------*/
- #ifndef __SDCard_H
- #define __SDCard_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- /* USER CODE BEGIN Includes */
- /* 包含頭文件 ----------------------------------------------------------------*/
- #include "stm32f1xx_hal.h"
- /* USER CODE END Includes */
- /* 類型定義 ------------------------------------------------------------------*/
- /* 宏定義 --------------------------------------------------------------------*/
- //#define SPI_FLASH_ID 0xEF3015 //W25X16 2MB
- //#define SPI_FLASH_ID 0xEF4015 //W25Q16 4MB
- //#define SPI_FLASH_ID 0XEF4017 //W25Q64 8MB
- #define SPI_FLASH_ID 0XEF4018 //W25Q128 16MB YS-F1Pro開發默認使用
- #define FLASH_SPIx SPI1
- #define FLASH_SPIx_RCC_CLK_ENABLE() __HAL_RCC_SPI1_CLK_ENABLE()
- #define FLASH_SPIx_RCC_CLK_DISABLE() __HAL_RCC_SPI1_CLK_DISABLE()
- #define FLASH_SPI_GPIO_ClK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
- #define FLASH_SPI_GPIO_PORT GPIOA
- #define FLASH_SPI_SCK_PIN GPIO_PIN_5
- #define FLASH_SPI_MISO_PIN GPIO_PIN_6
- #define FLASH_SPI_MOSI_PIN GPIO_PIN_7
- #define FLASH_SPI_CS_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
- #define FLASH_SPI_CS_PORT GPIOA
- #define FLASH_SPI_CS_PIN GPIO_PIN_4
- #define FLASH_SPI_CS_ENABLE() HAL_GPIO_WritePin(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN, GPIO_PIN_RESET)
- #define FLASH_SPI_CS_DISABLE() HAL_GPIO_WritePin(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN, GPIO_PIN_SET)
- /* 擴展變量 ------------------------------------------------------------------*/
- extern SPI_HandleTypeDef hspiflash;
- /* 函數聲明 ------------------------------------------------------------------*/
- /* USER CODE BEGIN Private defines */
- /* USER CODE END Private defines */
- #define u8 uint8_t
- #define u16 uint16_t
- #define u32 uint32_t
- /* Private define ------------------------------------------------------------*/
- /* SD卡類型定義 */
- #define SD_TYPE_MMC 0
- #define SD_TYPE_V1 1
- #define SD_TYPE_V2 2
- #define SD_TYPE_V2HC 4
- /* SPI總線速度設置*/
- #define SPI_SPEED_LOW 0
- #define SPI_SPEED_HIGH 1
- /* SD傳輸數據結束後是否釋放總線宏定義 */
- #define NO_RELEASE 0
- #define RELEASE 1
- /* SD卡指令表 */
- #define CMD0 0 //卡復位
- #define CMD9 9 //命令9 ,讀CSD數據
- #define CMD10 10 //命令10,讀CID數據
- #define CMD12 12 //命令12,停止數據傳輸
- #define CMD16 16 //命令16,設置SectorSize 應返回0x00
- #define CMD17 17 //命令17,讀sector
- #define CMD18 18 //命令18,讀Multi sector
- #define ACMD23 23 //命令23,設置多sector寫入前預先擦除N個block
- #define CMD24 24 //命令24,寫sector
- #define CMD25 25 //命令25,寫Multi sector
- #define ACMD41 41 //命令41,應返回0x00
- #define CMD55 55 //命令55,應返回0x01
- #define CMD58 58 //命令58,讀OCR信息
- #define CMD59 59 //命令59,使能/禁止CRC,應返回0x00
- /* Private macro -------------------------------------------------------------*/
- //SD卡CS片選使能端操作:
- #define SD_CS_ENABLE() GPIO_ResetBits(GPIOA,GPIO_PIN_4) //選中SD卡
- #define SD_CS_DISABLE() GPIO_SetBits(GPIOA,GPIO_PIN_4) //不選中SD卡
- //#define SD_PWR_ON() GPIO_ResetBits(GPIOD,GPIO_Pin_10) //SD卡上電
- //#define SD_PWR_OFF() GPIO_SetBits(GPIOD,GPIO_Pin_10) //SD卡斷電
- //#define SD_DET() !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) //檢測有卡
- //1-有 0-無
- /* Private function prototypes -----------------------------------------------*/
- void SPI_Configuration(void);
- void SPI_SetSpeed(u8 SpeedSet);
- u8 SPI_ReadWriteByte(u8 TxData); //SPI總線讀寫一個字節
- u8 SD_WaitReady(void); //等待SD卡就緒
- u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc); //SD卡發送一個命令
- u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc);
- u8 SD_Init(void); //SD卡初始化
- //
- u8 SD_ReceiveData(u8 *data, u16 len, u8 release);//SD卡讀數據
- u8 SD_GetCID(u8 *cid_data); //讀SD卡CID
- u8 SD_GetCSD(u8 *csd_data); //讀SD卡CSD
- u32 SD_GetCapacity(void); //取SD卡容量
- u8 SD_ReadSingleBlock(u32 sector, u8 *buffer); //讀一個sector
- u8 SD_WriteSingleBlock(u32 sector, const u8 *buffer); //寫一個sector
- u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count); //讀多個sector
- u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count); //寫多個sector
- /* USER CODE BEGIN Prototypes */
- extern u8 SD_Init(void);
- /* USER CODE END Prototypes */
- #ifdef __cplusplus
- }
- #endif
- #endif /*__ usart_H */
2、添加FATFS文件系統
3、修改FATFS文件系統SD卡驅動部分sdcard_diskio.c
- /* 包含頭文件 ----------------------------------------------------------------*/
- #include "main.h"
- #include <string.h>
- #include "SDCard.h"
- #include "ff_gen_drv.h"
- /* 私有類型定義 --------------------------------------------------------------*/
- /* 私有宏定義 ----------------------------------------------------------------*/
- #define BLOCK_SIZE 512
- /* 私有變量 ------------------------------------------------------------------*/
- static volatile DSTATUS Stat = STA_NOINIT;
- /* 擴展變量 ------------------------------------------------------------------*/
- /* 私有函數原形 --------------------------------------------------------------*/
- DSTATUS SD_initialize (BYTE);
- DSTATUS SD_status (BYTE);
- DRESULT SD_read (BYTE, BYTE*, DWORD, UINT);
- #if _USE_WRITE == 1 // 如果允許寫操作
- DRESULT SD_write (BYTE, const BYTE*, DWORD, UINT);
- #endif /* _USE_WRITE == 1 */
- #if _USE_IOCTL == 1 // 如果輸入輸出操作控制
- DRESULT SD_ioctl (BYTE, BYTE, void*);
- #endif /* _USE_IOCTL == 1 */
- /* 定義SD卡接口函數 */
- const Diskio_drvTypeDef SD_Driver =
- {
- SD_initialize, // SD卡初始化
- SD_status, // SD卡狀態獲取
- SD_read, // SD卡讀數據
- #if _USE_WRITE == 1
- SD_write, // SD卡寫數據
- #endif /* _USE_WRITE == 1 */
- #if _USE_IOCTL == 1
- SD_ioctl, // 獲取SD卡信息
- #endif /* _USE_IOCTL == 1 */
- };
- /* 函數體 --------------------------------------------------------------------*/
- /**
- * 函數功能: SD卡初始化配置
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 無
- */
- //extern void MX_SPI1_Init(void);
- DSTATUS SD_initialize(BYTE lun)
- {
- Stat = STA_NOINIT;
- /* 初始化SDIO外設 */
- // MX_SPI1_Init();
- /* 獲取SD卡狀態 */
- int result;
- result = SD_Init();
- // if(HAL_SD_GetStatus(&hsdcard)==SD_TRANSFER_OK)
- // {
- // Stat &= ~STA_NOINIT;
- // }
- if (result == 0)
- {
- Stat = RES_OK;
- }
- else
- {
- Stat = RES_ERROR;
- }
- return Stat;
- }
- /**
- * 函數功能: SD卡狀態獲取
- * 輸入參數: lun : 不用
- * 返 回 值: DSTATUS:SD卡狀態返回值
- * 說 明: 無
- */
- DSTATUS SD_status(BYTE lun)
- {
- Stat = STA_NOINIT;
- // if(HAL_SD_GetStatus(&hsdcard) == SD_TRANSFER_OK)
- // {
- // Stat &= ~STA_NOINIT;
- // }
- Stat = RES_OK;
- return Stat;
- }
- /**
- * 函數功能: 從SD卡讀取數據到緩衝區
- * 輸入參數: lun : 不用
- * buff:存放讀取到數據緩衝區指針
- * sector:扇區地址(LBA)
- * count:扇區數目
- * 返 回 值: DSTATUS:操作結果
- * 說 明: SD卡讀操作使用DMA傳輸
- */
- DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
- {
- DRESULT res = RES_OK;
- // if((DWORD)buff&3)
- // {
- // DWORD scratch[BLOCK_SIZE/4];
- // while (count--)
- // {
- // res = SD_read(lun,(void *)scratch, sector++, 1);
- // if (res != RES_OK)
- // {
- // break;
- // }
- // memcpy(buff, scratch, BLOCK_SIZE);
- // buff += BLOCK_SIZE;
- // }
- // return res;
- // }
- //
- // if(HAL_SD_ReadBlocks_DMA(&hsdcard,(uint32_t*)buff,(uint64_t)(sector * BLOCK_SIZE),BLOCK_SIZE,count) != SD_OK)
- // {
- // res = RES_ERROR;
- // }
- // if(res==RES_OK)
- // {
- // if(HAL_SD_CheckReadOperation(&hsdcard, 0xFFFFFFFF) != SD_OK)
- // {
- // res = RES_ERROR;
- // }
- // }
- int result;
- if(count==1)
- {
- result=SD_ReadSingleBlock(sector,buff);
- }
- else
- {
- result = SD_ReadMultiBlock(sector, buff, count);
- }
- if (result == 0)
- {
- res = RES_OK;
- }
- else
- {
- res = RES_ERROR;
- }
- return res;
- }
- /**
- * 函數功能: 將緩衝區數據寫入到SD卡內
- * 輸入參數: lun : 不用
- * buff:存放待寫入數據的緩衝區指針
- * sector:扇區地址(LBA)
- * count:扇區數目
- * 返 回 值: DSTATUS:操作結果
- * 說 明: SD卡寫操作沒有使用DMA傳輸
- */
- #if _USE_WRITE == 1
- DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
- {
- DRESULT res = RES_OK;
- // if((DWORD)buff&3)
- // {
- // DRESULT res = RES_OK;
- // DWORD scratch[BLOCK_SIZE / 4];
- // while (count--)
- // {
- // memcpy( scratch,buff,BLOCK_SIZE);
- // res = SD_write(lun,(void *)scratch, sector++, 1);
- // if (res != RES_OK)
- // {
- // break;
- // }
- // buff += BLOCK_SIZE;
- // }
- // return res;
- // }
- //
- // if(HAL_SD_WriteBlocks(&hsdcard,(uint32_t*)buff,(uint64_t)(sector * BLOCK_SIZE),BLOCK_SIZE, count) != SD_OK)
- // {
- // res = RES_ERROR;
- // }
- int result;
- if(count==1)
- {
- result=SD_WriteSingleBlock(sector, buff);
- }
- else
- {
- result = SD_WriteMultiBlock(sector, buff, count);
- }
- if (result == 0)
- {
- res = RES_OK;
- }
- else
- {
- res = RES_ERROR;
- }
- return res;
- }
- #endif /* _USE_WRITE == 1 */
- /**
- * 函數功能: 輸入輸出控制操作(I/O control operation)
- * 輸入參數: lun : 不用
- * cmd:控制命令
- * buff:存放待寫入或者讀取數據的緩衝區指針
- * 返 回 值: DSTATUS:操作結果
- * 說 明: 無
- */
- #if _USE_IOCTL == 1
- DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff)
- {
- DRESULT res = RES_ERROR;
- // if (Stat & STA_NOINIT) return RES_NOTRDY;
- //
- // switch (cmd)
- // {
- // /* Make sure that no pending write process */
- // case CTRL_SYNC :
- //FLASH_SPI_CS_ENABLE();
- //if(SD_WaitReady()==0)
- //{
- //res = RES_OK;
- //}
- //else
- //{
- //res = RES_ERROR;
- //}
- ////FLASH_SPI_CSDISABLE();
- // break;
- //
- // /* 獲取SD卡總扇區數目(DWORD) */
- // case GET_SECTOR_COUNT :
- //*(WORD*)buff = 512;
- //res = RES_OK;
- // break;
- //
- // /* 獲取讀寫扇區大小(WORD) */
- // case GET_SECTOR_SIZE :
- //*(DWORD*)buff = SD_GetCapacity();
- //res = RES_OK;
- // break;
- //
- // /* 獲取擦除塊大小(DWORD) */
- // case GET_BLOCK_SIZE :
- // *(DWORD*)buff = BLOCK_SIZE;
- // break;
- //
- // default:
- // res = RES_PARERR;
- // }
- uint8_t CSD[16] = {0};
- uint8_t csddata[16] = {0};
- uint32_t csize;
- uint32_t Capacity;
- switch (cmd)
- {
- case CTRL_SYNC:
- res = RES_OK;
- break;
- case GET_SECTOR_COUNT:
- SD_GetCID(CSD);
- SD_GetCSD(csddata);
- //SDGetCIDCSD(CSD, csddata);
- csize = csddata[9] + ((uint32_t)csddata[8] << 8) + ((uint32_t)(csddata[7] & 0x3f) << 16) + 1;
- Capacity = csize << 9;
- *((DWORD *)buff) = Capacity;
- res = RES_OK;
- break;
- case GET_SECTOR_SIZE:
- *(WORD *)buff = 512; //spi flash的扇區大小是 512 Bytes
- return RES_OK;
- case GET_BLOCK_SIZE:
- *((DWORD *)buff) = 4096;
- res = RES_OK;
- break;
- default:
- res = RES_PARERR;
- break;
- }
- return res;
- }
- #endif /* _USE_IOCTL == 1 */
4、在Main.c文件中添加 測試應用程序
- char SPIFLASHPath[4]; /* 串行Flash邏輯設備路徑 */
- char SDPath[4]; /* SD卡邏輯設備路徑 */
- FATFS fs;/* FatFs文件系統對象 */
- FIL file;/* 文件對象 */
- FRESULT f_res; /* 文件操作結果 */
- UINT fnum; /* 文件成功讀寫數量 */
- BYTE ReadBuffer[1024]={0}; /* 讀緩衝區 */
- BYTE WriteBuffer[]= "歡迎使用硬石STM32開發板 今天是個好日子,新建文件系統測試文件\\n";/* 寫緩衝區*/
- extern Diskio_drvTypeDef SD_Driver;
添加文件系統操作結果處理
- /**
- * 函數功能: FatFS文件系統操作結果信息處理.
- * 輸入參數: FatFS文件系統操作結果:FRESULT
- * 返 回 值: 無
- * 說 明: 無
- */
- static void printf_fatfs_error(FRESULT fresult)
- {
- switch(fresult)
- {
- case FR_OK: //(0)
- printf("》操作成功。\\n");
- break;
- case FR_DISK_ERR: //(1)
- printf("!!硬件輸入輸出驅動出錯。\\n");
- break;
- case FR_INT_ERR: //(2)
- printf("!!斷言錯誤。\\n");
- break;
- case FR_NOT_READY: //(3)
- printf("!!物理設備無法工作。\\n");
- break;
- case FR_NO_FILE: //(4)
- printf("!!無法找到文件。\\n");
- break;
- case FR_NO_PATH: //(5)
- printf("!!無法找到路徑。\\n");
- break;
- case FR_INVALID_NAME: //(6)
- printf("!!無效的路徑名。\\n");
- break;
- case FR_DENIED: //(7)
- case FR_EXIST: //(8)
- printf("!!拒絕訪問。\\n");
- break;
- case FR_INVALID_OBJECT: //(9)
- printf("!!無效的文件或路徑。\\n");
- break;
- case FR_WRITE_PROTECTED: //(10)
- printf("!!邏輯設備寫保護。\\n");
- break;
- case FR_INVALID_DRIVE: //(11)
- printf("!!無效的邏輯設備。\\n");
- break;
- case FR_NOT_ENABLED: //(12)
- printf("!!無效的工作區。\\n");
- break;
- case FR_NO_FILESYSTEM: //(13)
- printf("!!無效的文件系統。\\n");
- break;
- case FR_MKFS_ABORTED: //(14)
- printf("!!因函數參數問題導致f_mkfs函數操作失敗。\\n");
- break;
- case FR_TIMEOUT: //(15)
- printf("!!操作超時。\\n");
- break;
- case FR_LOCKED: //(16)
- printf("!!文件被保護。\\n");
- break;
- case FR_NOT_ENOUGH_CORE: //(17)
- printf("!!長文件名支持獲取堆空間失敗。\\n");
- break;
- case FR_TOO_MANY_OPEN_FILES: //(18)
- printf("!!打開太多文件。\\n");
- break;
- case FR_INVALID_PARAMETER: // (19)
- printf("!!參數無效。\\n");
- break;
- }
- }
添加測試程序:
- /* 註冊一個FatFS設備:SD卡 */
- if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
- {
- //在SD卡掛載文件系統,文件系統掛載時會對SD卡初始化
- f_res = f_mount(&fs,(TCHAR const*)SDPath,1);
- printf_fatfs_error(f_res);
- /*----------------------- 格式化測試 ---------------------------*/
- /* 如果沒有文件系統就格式化創建創建文件系統 */
- if(f_res == FR_NO_FILESYSTEM)
- {
- printf("》SD卡還沒有文件系統,即將進行格式化...\\n");
- /* 格式化 */
- f_res=f_mkfs((TCHAR const*)SDPath,0,0);
- if(f_res == FR_OK)
- {
- printf("》SD卡已成功格式化文件系統。\\n");
- /* 格式化後,先取消掛載 */
- f_res = f_mount(NULL,(TCHAR const*)SDPath,1);
- /* 重新掛載*/
- f_res = f_mount(&fs,(TCHAR const*)SDPath,1);
- }
- else
- {
- printf("《《格式化失敗。》》\\n");
- while(1);
- }
- }
- else if(f_res!=FR_OK)
- {
- printf("!!SD卡掛載文件系統失敗。(%d)\\n",f_res);
- printf_fatfs_error(f_res);
- while(1);
- }
- else
- {
- printf("》文件系統掛載成功,可以進行讀寫測試\\n");
- }
- /*----------------------- 文件系統測試:寫測試 -----------------------------*/
- /* 打開文件,如果文件不存在則創建它 */
- printf("****** 即將進行文件寫入測試... ******\\n");
- f_res = f_open(&file, "FatFs讀寫測試文件.txt",FA_CREATE_ALWAYS | FA_WRITE );
- if ( f_res == FR_OK )
- {
- printf("》打開/創建FatFs讀寫測試文件.txt文件成功,向文件寫入數據。\\n");
- /* 將指定存儲區內容寫入到文件內 */
- f_res=f_write(&file,WriteBuffer,sizeof(WriteBuffer),&fnum);
- if(f_res==FR_OK)
- {
- printf("》文件寫入成功,寫入字節數據:%d\\n",fnum);
- printf("》向文件寫入的數據為:\\n%s\\n",WriteBuffer);
- }
- else
- {
- printf("!!文件寫入失敗:(%d)\\n",f_res);
- }
- /* 不再讀寫,關閉文件 */
- f_close(&file);
- }
- else
- {
- printf("!!打開/創建文件失敗。\\n");
- }
- /*------------------- 文件系統測試:讀測試 ------------------------------------*/
- printf("****** 即將進行文件讀取測試... ******\\n");
- f_res = f_open(&file, "FatFs讀寫測試文件.txt", FA_OPEN_EXISTING | FA_READ);
- if(f_res == FR_OK)
- {
- printf("》打開文件成功。\\n");
- f_res = f_read(&file, ReadBuffer, sizeof(ReadBuffer), &fnum);
- if(f_res==FR_OK)
- {
- printf("》文件讀取成功,讀到字節數據:%d\\n",fnum);
- printf("》讀取得的文件數據為:\\n%s \\n", ReadBuffer);
- }
- else
- {
- printf("!!文件讀取失敗:(%d)\\n",f_res);
- }
- }
- else
- {
- printf("!!打開文件失敗。\\n");
- }
- /* 不再讀寫,關閉文件 */
- f_close(&file);
- /* 不再使用,取消掛載 */
- f_res = f_mount(NULL,(TCHAR const*)SDPath,1);
- }
- /* 註銷一個FatFS設備:SD卡 */
- FATFS_UnLinkDriver(SDPath);
3、使用串口查看測試結果
閱讀更多 愛碼廝小妖 的文章