STM32
直播中

张莹

7年用户 968经验值
私信 关注
[问答]

怎样去移植基于SPI模式的SD卡驱动和FatFS文件呢

怎样去移植基于SPI模式的SD卡驱动和FatFS文件呢?

如何利用minini库对ini配置信息文件进行读取呢?

回帖(1)

高博

2021-11-3 11:49:26
  本文实现了基于STM32F107VC的金牛开发板的基于SPI模式的SD卡驱动和FatFS的移植,以及利用minini库对ini配置信息文件进行读取。
  因为后面连接网络需要相关配置参数,而且可能随时发生变化,这些参数不可能固定在程序中,所以,我们现在把它放在sd卡中,以便随时更改。
  IDE环境为: MDK v5.23
  硬件环境:基于STM32F107VC的金牛开发板
  一、添加SD卡驱动代码、移植FatFS
  为了节省时间,就不造轮子了,直接使用网上共享的spi和sd驱动代码、FatFS源代码。
  这部分源代码摘自:
  STM32_SD_FATFS_LCD_TOUCH
  备用地址:STM32_SD_FATFS_LCD_TOUCH
  把这个源代码下来,解压。
  把STM32_SD_FATFS_LCD_TOUCH.rarUserSD_CARDsrc 目录下的spi.c、sdcard.c文件和
  STM32_SD_FATFS_LCD_TOUCH.rarUserSD_CARDinc 目录下的spi.h、sdcard.h文件都复制到我们工程的BSP目录下,并把spi.c、sdcard.c加入工程的BSP组。
  在spi.h中加入:
  #include “stm32f10x_spi.h” 然后下载FatFS官方源码:
  http://elm-chan.org/fsw/ff/arc/ff13.zip
  解压后重命名整个文件夹为FatFS,并把它复制到我们工程的third_party目录下。
  在IDE上添加一个组,名字为:third_party/FatFS,添加third_party/FatFS/source目录下的diskio.c、ff.c这两个文件。
  其中ff.c是具体fat文件系统的实现,diskio.c是文件系统硬件驱动接口实现。
  接下来,把STM32_SD_FATFS_LCD_TOUCH.rarUserfatfs 目录下的diskio.h和diskio.c文件复制到third_party/FatFS/Source下面来,覆盖原同名文件。
  这样就直接使用来源于网上的SD卡驱动接口实现了。
  然后,把third_party/FatFS/source这个路径添加到IDE的包含路径中。
  编译一下可以通过。
  移植完了。写个demo测试一下。
  首先参考网上的例程,写一个fatfs测试代码,主体放在common.h和common.c中
  到此,文件系统已经基本OK,需要说明的是,此次移植没有加上对unicode的支持,因此,也就不支持中文,需要支持中文的读者请参考其他移植文章。
  下面写一个ini文件,保存为ipcfg.ini,里面内容:
  [server]ip=10.0.0.105port=1883name=password= 关于server是域名(feild),ip是关键字(key),“=”后面是该关键字参数的值(value)。
  关于这部分请自行搜索参考有关文章。
  把ipcgf.ini放到SD卡上,进行读取操作。
  以下是一些展示:
  
  
  
  
  以上完整源代码:
  STM32F107_FreeRTOS_v9.0.0_SDCard-FatFS.rar
  二、移植minIni库
  本项目使用了minIni库来读取ini文件解析配置参数,版本为minini_12b。
  minIni官方网站:
  https://www.compuphase.com/minini.htm
  minini_12b官方源码地址:
  https://www.compuphase.com/software/minini_12b.zip
  下载下来,解压到minini_12b文件夹,把minini_12b整个文件夹复制到third_party目录下。
  然后,在IED上添加一个组,命名为third_party/minIni,把third_party/minini_12b下的minIni.c文件加入到工程里面。
  并把third_party/minini_12b加入到包含路径中。
  此时编译会出现两个错误:
  。.OutputFreeRTOS_v9.0.0.: Error: L6218E: Undefined symbol __aeabi_assert (referred from minini.o)。..OutputFreeRTOS_v9.0.0.: Error: L6218E: Undefined symbol strnicmp (referred from minini.o)。 这是链接找不到这两个函数。
  所以,minIni.c需要修改。
  对于__aeabi_assert,我们需要自定义实现,我们编写一个头文件bsp_assert.h,实现它:
  bsp_assert.h:
  #undef assert#ifdef __cplusplusextern “C” {#endif#ifdef NDEBUG/* * If not debugging, assert does nothing. */#define assert(x) ((void)0)#else /* debugging enabled *//* * CRTDLL nicely supplies a function which does the actual output and * call to abort. */extern void _assert(const char *mesg, const char *file, int line);/* * Definition of the assert macro. */#define assert(e) ((e) ? (void)0 : _assert(#e, __FILE__, __LINE__))#endif /* NDEBUG */#ifdef __cplusplus}#endif 并把它放在BSP目录下。
  然后把minIni.c中的
  #include 《assert.h》 换成我们的
  #include “bsp_assert.h” 对于strnicmp,我们只需要在#include “bsp_assert.h”下面加一行宏:
  #define PORTABLE_STRNICMP 这一部分代码改后如下:
  #if defined NDEBUG #define assert(e)#else //#include 《assert.h》 #include “bsp_assert.h” //added @2017.09.25 #define PORTABLE_STRNICMP //added @2017.09.25#endif 接下来,要配置一下FatFS函数接口配置:
  把minIni.h中的
  #include “minGlue.h” #include “minGlue-FatFs.h” 此时编译会出错:
  。.third_partyminini_12bminGlue-FatFs.h(34): error: #144: a value of type “int” cannot be used to initialize an entity of type “char *”。.third_partyminini_12bminGlue-FatFs.h(35): error: #20: identifier “NULL” is undefinedD:Program Files (x86)Keil_v5ARMARMCCBin。.includestring.h(209): error: #159: declaration is incompatible with previous “strchr” (declared at line 34 of “。.third_partyminini_12bminGlue-FatFs.h”) 打开minGlue-FatFs.h文件,在文件顶端加入:
  #include 《string.h》 修改ini_rename函数,在char *drive定义前面加const:
  static int ini_rename(TCHAR *source, const TCHAR *dest){ /* Function f_rename() does not allow drive letters in the destination file */ const char *drive = strchr(dest, ‘:’); drive = (drive == NULL) ? dest : drive + 1; return (f_rename(source, drive) == FR_OK);} F7编译通过了。
  下面写一个程序来读取上面ipcfg.ini中的参数。
  其中,InitMQTTServerInfo(void)函数读取了ipcfg.ini文件,并把参数解析出来放在缓存中。
  剩下的几个函数是从缓存中读取参数出来。
  ini_gets(“server”, “ip”, “192.168.1.1”, str, sizearray(str), inifile); 是读取server域中的ip关键字,如果没有该关键字,则设置成默认值(此处为”192.168.1.1”)。
  在程序中如果ipcfg.ini文件读取出错则会设置成以下默认值:
  ip=192.168.1.1port=1883name=“”password=“” 在mian函数中的SD_Init(); 下面添加一行:
  InitMQTTServerInfo();
  然后,编译链接,烧到板子上运行,可以看到:
  
  参数已经读取出来了。
  修改一下参数,把sd卡的ipcfg.ini内容改成如下:
  [server]ip=10.0.0.108port=10000name=adminpassword=123456 上电再试:
  
举报

更多回帖

发帖
×
20
完善资料,
赚取积分