1.使用STM32CubeMX配置FatFs
為測試新買的開發(fā)板TF卡讀寫是否正常,使用STM32CubeMX(后簡稱CubeMX)進(jìn)行代碼構(gòu)建。生成代碼后燒錄測試,發(fā)現(xiàn)在掛載TF卡時無法成功,返回值為錯誤3(FR_NOT_READY)。經(jīng)排查后問題已解決,遂記錄配置過程供大家參考,并講解掛載時返回錯誤3的解決方式。
1.1 工程準(zhǔn)備
①為了輸出TF卡(或者SD卡)的讀寫測試結(jié)果,需要你的工程能實現(xiàn)串口打印。因此請準(zhǔn)備好一個使用CubeMX生成的工程(我生成的為Keil工程),要求此工程能夠使用printf函數(shù)打印信息到串口調(diào)試助手上。因為這個過程非常簡單,并且教程極多,請自行搜索并準(zhǔn)備工程。生成的工程根目錄內(nèi)容類似下圖:
②請確認(rèn)你的TF卡槽連接的IO,不同的板卡IO不同,例如我的板卡上熱拔插檢測引腳沒有連接,本教程以我的IO連接為例,原理圖如下所示:
1.2 配置CubeMX
雙擊工程文件夾根目錄中“xxx.ioc”文件,此時會進(jìn)入CubeMX的配置界面。
1.2.1 配置SDIO
①點擊左側(cè)“Connectivity”,Mode選擇“SD 4 bits Wide bus”,將“SDIOCLK clock divide factor”設(shè)置為2(調(diào)試時先不要太快,試驗成功后可以自行改),如下圖所示:
②勾選NVIC中的“SDIO global interruptSDIO”,如下所示:
③配置GPIO,請參照你的板卡原理圖進(jìn)行配置。此處以我的原理圖為例,配置如下圖所示:
④注意,如果你的板卡上有熱拔插檢測引腳,請根據(jù)板卡原理圖,直接在右側(cè)的“PinOut View”窗口點擊對應(yīng)的引腳,設(shè)置為“GPIO_Input”模式。這里假設(shè)我的板卡熱拔插檢測引腳連接到PE2,則設(shè)置如下所示:
1.2.2 配置DMA(如果不想用DMA那么此步驟可省略)
①在SDIO配置下的“DMA Settings”欄目下點擊ADD,添加RX與TX請求,添加后的配置無需修改,使用默認(rèn)的參數(shù)即可:
1.2.3 配置FatFs
①點擊右側(cè)的“Middleware and Software Packs”,選擇“FATFS”,Mode勾選“SDCard”,并修改“Set Defines”中的“CODE_PAGE (Code page ontarget)”為“DBSC”,修改“USE_LFN (Use Long Filename)”為“Enabled with dynamicworking buffer on the STACK”。如下所示:
②(此步驟使用DMA時才需要配置)如果使用了DMA,則需要在“Advanced Settings”欄目將“Use dma template”設(shè)置為“Enable”:
③(當(dāng)你的板卡連接了熱拔插檢測引腳時此步驟才需要配置)如果你的板卡SD卡熱拔插引腳連接到了GPIO上,那么需要在“Platform Settings”中將“Detect_SDIO”項配置為你前面設(shè)置為輸入的那個引腳。比如我在前面假設(shè)我的板子檢測引腳連接到了PE2,則配置如下:
?。?!注意:如果你的板子上熱拔插檢測引腳未連接GPIO,那么這項可以不選,后面有警告直接忽略即可。當(dāng)然你也可以隨便選一個未使用的IO配置成輸入模式,然后在這里選擇該引腳,這樣警告就消失了,但是要將此引腳接地,否則可能識別為卡沒有插入導(dǎo)致TF讀寫測試不通過
1.2.4 配置NVIC
①打開“System Core”中的“NVIC”,修改DMA的兩個通道的“Preemption Priority”值,只要大于“SDIO global interrupt”的值就可以了:
1.2.5 修改時鐘配置
①點擊“Clock Configuration”欄,將“48MHz clocks”的頻率修改為48:
1.2.6 修改工程設(shè)置并輸出工程
①打開“Project Manager”欄目,將“Minimum Stack Size”設(shè)置為0x500(空間足夠的話最好設(shè)置大一點,比如可以設(shè)置為0x1000),設(shè)置后點擊“GENERATE CODE”生成代碼:
2 添加TF讀寫測試代碼
①打開Keil工程,在“main.c”文件中的main()函數(shù)前添加TF卡測試代碼,代碼內(nèi)容如下:
//需要修改MX_SDIO_SD_Init為1B
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
FATFS fs;
FIL fil;
uint32_t total,mfree; // file objects
uint32_t byteswritten; /* File write counts */
uint32_t bytesread; /* File read counts */
uint8_t wtext[] = "SDTest File"; /* File write buffer */
uint8_t rtext[100]; /* File read buffers */
char filename[] = "SDTest.txt";
u8 exf_getfree(u8 *drv,u32 *total,u32 *free)
{
FATFS *fs1;
u8 res;
u32 fre_clust=0, fre_sect=0, tot_sect=0;
res =(u32)f_getfree((const TCHAR*)drv, (DWORD*)&fre_clust, &fs1);
if(res==0)
{
tot_sect=(fs1->n_fatent-2)*fs1->csize;
fre_sect=fre_clust*fs1->csize;
#if _MAX_SS!=512
tot_sect*=fs1->ssize/512;
fre_sect*=fs1->ssize/512;
#endif
*total=tot_sect>>1;
*free=fre_sect>>1;
}
return res;
}
void Fatfs_RW_test(void)
{
printf("\r\n ****** FatFs Example ******\r\n\r\n");
/*##-1- Register the file system object to the FatFs module ##############*/
retSD = f_mount(&fs, "0", 1);
//f_mkdir("0:dxc");
if(retSD)
{
printf(" Mount error!!! Error Num : %d \r\n",retSD);
Error_Handler();
}
else
{
printf(" Mount sucess :) \r\n");
}
/*##-2- Create and Open new text file objects with write access ######*/
retSD=exf_getfree("0",&total,&mfree);
if(retSD==0)
printf(" total : %d MB,free : %d MB \r\n\r\n",total>>10,mfree>>10);
else
printf(" Getfree error!!! \r\n");
retSD = f_open(&fil, filename, FA_CREATE_ALWAYS | FA_WRITE);
if(retSD)
printf(" Open file error!!! Error Num : %d\r\n",retSD);
else
printf(" Open file sucess :) \r\n");
/*##-3- Write data to the text files ###############################*/
retSD = f_write(&fil, wtext, sizeof(wtext), (void *)&byteswritten);
if(retSD)
printf(" Write file error!!! Error Num : %d\r\n",retSD);
else
{
printf(" Write file sucess :) \r\n");
printf(" Write Data : %s\r\n\r\n",wtext);
}
/*##-4- Close the open text files ################################*/
retSD = f_close(&fil);
if(retSD)
printf(" Close error!!! Error Num : %d\r\n",retSD);
else
printf(" Close sucess :) \r\n");
/*##-5- Open the text files object with read access ##############*/
retSD = f_open(&fil, filename, FA_READ);
if(retSD)
printf(" Open file error!!! Error Num : %d\r\n",retSD);
else
printf(" Open file sucess :) \r\n");
/*##-6- Read data from the text files ##########################*/
retSD = f_read(&fil, rtext, sizeof(rtext), (UINT*)&bytesread);
if(retSD)
printf(" Read error!!! Error Num : %d\r\n",retSD);
else
{
printf(" Read sucess :) \r\n");
printf(" Read Data : %s\r\n\r\n",rtext);
}
/*##-7- Close the open text files ############################*/
retSD = f_close(&fil);
if(retSD)
printf(" Close error!!! Error Num : %d\r\n",retSD);
else
printf(" Close sucess :) \r\n\r\n");
/*##-8- Compare read data with the expected data ############*/
if(bytesread == byteswritten)
{
printf(" FatFs is working well!!!\r\n");
}
}
②在main()函數(shù)中,MX_SDIO_SD_Init和MX_FATFS_Init執(zhí)行完以后的地方調(diào)用TF測試代碼:
3 使用f_mount()函數(shù)掛載時返回錯誤3(FR_NOT_READY)問題的解決
經(jīng)過上面的配置,如果你用的是舊版CubeMX軟件,那么編譯并燒錄后便可以通過TF測試了(具體多舊的版本未知)。
如果此時你燒錄運行發(fā)現(xiàn)輸出了Mount Error的信息,Num值為3,如下圖所示:
則說明你需要進(jìn)行以下修改:
3.1 修改代碼以解決掛載時返回錯誤3
找到“void MX_SDIO_SD_Init(void)”函數(shù),將“hsd.Init.BusWide”的值由“SDIO_BUS_WIDE_4B”修改為“SDIO_BUS_WIDE_1B”,修改后如下所示:
此時重新編譯并運行,問題便得以解決,以下是測試通過時的輸出信息:
文章來源:http://www.zghlxwxcb.cn/news/detail-836893.html
3.2 掛載時返回錯誤3的原因
在SDIO進(jìn)行初始化時,使用的是1位寬模式進(jìn)行配置的,在初始化完成后才會使用4位寬進(jìn)行數(shù)據(jù)傳輸。新版的CubeMX軟件生成代碼時不知道為何會在初始化時直接配置成4位寬模式,從而導(dǎo)致初始化不過,返回錯誤3。因此只要將初始化代碼中位寬進(jìn)行修改即可。文章來源地址http://www.zghlxwxcb.cn/news/detail-836893.html
到了這里,關(guān)于[STM32] - STM32F407VET6使用STM32CubeMX配置FatFs,以及掛載時返回03錯誤碼問題的解決的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!