查看: 5315|回复: 4

[经验] 移植Tiny-FATFS文件系统到STM8L152C6T6,使用硬件SPI+RT

[复制链接]
  • TA的每日心情
    开心
    2019-11-4 13:48
  • 签到天数: 14 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2020-6-25 12:19:26 | 显示全部楼层 |阅读模式
    分享到:
    最近老师需要做一个低功耗的各种环境参数采集仪,要求不多,就是采集各种参数并储存起来,但是要求低功耗。所以我第一时间就想到了STM8L系列单片机,发出去做的板子还没回来,就先使用现有的一块板子先调试文件系统和RTC这些啦。今晚还有点时间就写个移植过程吧,给后来人种一颗小树苗吧。。。

    硬件介绍:
        单片机:STM8l152c6t6, 2K RAM,32K FLASH
        SD卡:4G和8G  
        接口连接://SD_DT3--SD_CS----------------PB4
                       //SD_CMD--SPI1_MOSI--------PB6
                       //SD_SCK--SPI1_SCK-----------PB5
                       //SD_DT0--SPI1_MISO--------PB7

    软件介绍:
        编译器:IAR for STM8
        FATFs版本:R0.11a ,直接到FAT官网上面下载即可,下面附件也有。
        通信协议:硬件SPI   (附件也有一份软件SPI的源码)
        RTC:使用STM8L内置的RTC

    移植意义:可能大家觉得在STM8这种这么low的单片机上面运行FAT文件系统没什么意义,但是我觉得STM8l在用在低功耗采集或者信息节点的场合很多时候都需要存储数据,那么说到存储数据最适合的存储介质我觉得就是SD卡了,低成本大内存。那么自然想到FAT,存储的文件可以直接在电脑打开,每天新建一个文件来存储等。所以我觉得这东西上面使用FAT还是很有意义的。Tiny-FATFS需要单片机的1K的RAM用做工作区,具体需要多大的FLASH看你的要求了,可以适当的裁剪FATFS,我编译出来是20多K。

    移植步骤:
       1.下载FATFS源码包,解压之后把src文件夹直接复制到工程目录中,并把带的字库和说明删掉,如下图;
       
       2.打开STM8工程,把FATFS中的xx.c文件(diskio.c和ff.c)添加至工程目中,并在option中包含路径
      
       3.配置ffconf.h(简要说下,具体可参考原子哥的手册);
       #define _FS_READONLY        0    //可读可写
       ##define _FS_MINIMIZE        3    //_FS_MINIMIZE、 _FS_READONLY、 _USE_STRFUNC、 _USE_MKFS、_USE_FORWARD 这些宏是用来对文件系统进行裁剪的,具体见下表
       #define _CODE_PAGE        1    //就支持ASCII码,小内存伤不起
        。。。。。。。
       #define _VOLUMES        1        //注意:Tiny-FATFS仅支持一个逻辑设备,设为1
       #define        _FS_TINY        1        //就是这个地方,设为1之后就是Tiny-FATFS了,编译之后你会发现比设为0的时候用的RAM少不少,只需1K,当然牺牲就是变慢了
       
    4.编写diskio.c里面的5个接口函数。
       前面5个接口函数我是参照原子哥的代码改的,我把除了SD_CARD的其他选项全删了,只留下SD_CARD的部分,因为其他的设备都用不上。(具体代码见附件)
      get_fattime函数:
    DWORD get_fattime (void)
    {                                 
            return (((u32)(RTC_DateStr.RTC_Year-(RTC_DateStr.RTC_Year>>4)*6)+20) << 25) /* Year */
                  | ((u32)(RTC_DateStr.RTC_Month-(RTC_DateStr.RTC_Month>>4)*6) << 21)      /* Month*/
                  | ((u32)(RTC_DateStr.RTC_Date-(RTC_DateStr.RTC_Date>>4)*6) << 16)       /* Day*/
                  | ((u32)(RTC_TimeStr.RTC_Hours-(RTC_TimeStr.RTC_Hours>>4)*6) << 11)      /* Hour*/
                  | ((u32)(RTC_TimeStr.RTC_Minutes-(RTC_TimeStr.RTC_Minutes>>4)*6) << 5)     /* Min*/
                  | ((u32)(RTC_TimeStr.RTC_Seconds-(RTC_TimeStr.RTC_Seconds>>4)*6) >> 1)     /* Sec*/
    ;
    }

      这里使用的是内部的RTC,每1S时间产生一个唤醒中断,然后在中断函数中更新日期时间,注意这里的日期时间都是BCD吗,例如0x16表示的是16年,所以上面做了转换。

    5.RTC初始化配置见附件源码了。下面是初始化过程中一个需要注意的地方
      if ((RTC->ISR1 & RTC_ISR1_INITS) == RESET)  //Check calendar has been initialized or not?
      {
        RTC_DateStructInit(&RTC_DateStr);
        RTC_DateStr.RTC_WeekDay = RTC_Weekday_Friday;
        RTC_DateStr.RTC_Date = 6;
        RTC_DateStr.RTC_Month = RTC_Month_March;
        RTC_DateStr.RTC_Year = 16;
        RTC_SetDate(RTC_Format_BIN, &RTC_DateStr);

        RTC_TimeStructInit(&RTC_TimeStr);
        RTC_TimeStr.RTC_Hours   = 20;
        RTC_TimeStr.RTC_Minutes = 02;
        RTC_TimeStr.RTC_Seconds = 00;
        RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);   
      }

    就是设置日期时间之前检查是RTC是否已经被设置过了,设置过了就不需要设置了。类似于STM32的备份寄存器,这样子只要不断电RTC的时间就不会复位。顺便提一句,STM8l的RTC还是很稳定、很准的,当时测了两三天跟电脑的时间差不了2秒,美中不足的是没有留出电池供电引脚,单片机断电就完了。
    6.硬件SPI配置,这步非常简单,看图


    简简单单几句就把它给配置了,做好这个借口,直接就跟原子哥的MMC_SD.c和MMC_SD.H对接上了,修改很少。

    7.最后主函数:不适用内存分配函数,直接全局变量作为静态工作区。
      
    测试代码:挂载并新建文件
      

    编译运行结果(RAM包含了自己测试用的一个长度为514字节的buff数组):



    在工程Backup文件夹里面还有一段测试读文件的代码:
       res = f_open(&fl,"news/news.txt",FA_READ);   
       if(res == FR_OK)
       {
         Usart1_Str("Open file ok!\r\n");
         Usart1_Str("The news is:\r\n");
         do
         {
           //for(i=0;i<50;i++) buff = 0;
           res = f_read(&fl,buff,512,&r);
           //Usart1_Str(buff);
           if(res || r<512)
           {
              Usart1_Str("Read over!\r\n");
             break;   //error or eof   
           }
         }
         while(1);
       }
       else
         Usart1_Str("Open file failed!\r\n");
       f_close(&fl);


    事先在SD卡里新建一个news/news.txt文件,大小为1026KB,最后测试读出时间是14秒,平均速度是60多Kbyte/s的读出速度,对于一般应用相当够用;
    跟另一个用模拟SPI写的工程比较,读取同样的这个文件,耗时一分49秒,平均速度只有10Kbyte/s左右。写入速度没测试,应该会慢一些。。。

    建议:使用FATFS时选用内存稍大的点STM单片机,本实验使用的是Medium容量的,上面还有Medium density plus,跟High density的,内存和存储空间都大很多,建议选用后面两种。
    STM8L的低功耗貌似很感人,等板子来了在测试了。。。


    游客,如果您要查看本帖隐藏内容请回复


    回复

    使用道具 举报

    该用户从未签到

    发表于 2021-9-29 08:54:58 | 显示全部楼层
    好东西,回来试试。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2021-11-23 16:46:06 | 显示全部楼层
    看看  正需要
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2023-1-4 09:49:20 | 显示全部楼层
    这个帖子是转载的吧
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-24 08:57 , Processed in 0.156433 second(s), 25 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.