找回密码
 注册
关于网站域名变更的通知
查看: 437|回复: 1
打印 上一主题 下一主题

移植Tiny-FATFS文件系统到STM8L152C6T6,使用硬件SPI+RTC

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-1-31 14:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
移植Tiny-FATFS文件系统到STM8L152C6T6,使用硬件SPI+RTC& L5 l- h/ p) x; f* V) h" T  o
, D+ ^2 W4 u  D. w' t4 D
最近老师需要做一个低功耗的各种环境参数采集仪,要求不多,就是采集各种参数并储存起来,但是要求低功耗。所以我第一时间就想到了stm8L系列单片机,发出去做的板子还没回来,就先使用现有的一块板子先调试文件系统和RTC这些啦。今晚还有点时间就写个移植过程吧,给后来人种一颗小树苗吧。。。5 Y$ m; t/ G" q9 a0 X% D9 V  Y: s

. h' N4 |, F- W" A  o# n硬件介绍:0 M$ {& r% v. d2 W/ P2 ?4 M; z
    单片机:STM8l152c6t6, 2K RAM,32K FLASH
7 U3 H4 F+ q/ }* c4 ^& S6 x4 A% z    sd卡:4G和8G  # n. i5 K( |! c/ h+ Y  g
    接口连接://SD_DT3--SD_CS----------------PB44 E6 n. a+ N* o
                   //SD_CMD--spi1_MOSI--------PB6
- R. \0 j# O4 Z( w6 M                   //SD_SCK--SPI1_SCK-----------PB5
1 ~4 [* c* e) [& q0 O: k* y6 L                   //SD_DT0--SPI1_MISO--------PB7! f3 A# o+ o5 v$ t  q% k( O: M* R: l

- J7 V: c9 _$ U& X3 r+ y2 J软件介绍:
3 Q- U7 s- z9 H, d+ b    编译器:IAR for STM8
" i! k+ u5 i+ K2 s  G9 ?/ f    FATFs版本:R0.11a ,直接到FAT官网上面下载即可,下面附件也有。+ B# G; ]7 G) v" T# }
    通信协议:硬件SPI   (附件也有一份软件SPI的源码)8 c8 y  L& n) d6 B
    RTC:使用STM8L内置的RTC% t& i6 W; x* p0 e

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

# Y8 F0 Y" G3 T0 \/ _% K' }/ Q' u4 O移植步骤:
: K3 K+ c( v: P0 Y& [. Z   1.下载FATFS源码包,解压之后把src文件夹直接复制到工程目录中,并把带的字库和说明删掉,如下图;7 H- n! l9 x' p. n% \( ?: p7 y
   8 u7 d+ }  }% U
   2.打开STM8工程,把FATFS中的xx.c文件(diskio.c和ff.c)添加至工程目中,并在option中包含路径
4 P+ |  K% b0 l. L6 H  
2 c  a( k! N0 J* ~% {   3.配置ffconf.h(简要说下,具体可参考原子哥的手册);
3 |& \. ^: I/ W$ O  f5 A1 Y  j   #define _FS_READONLY        0    //可读可写
. C- E" K- z  p9 y1 b: x   ##define _FS_MINIMIZE        3    //_FS_MINIMIZE、 _FS_READONLY、 _USE_STRFUNC、 _USE_MKFS、_USE_FORWARD 这些宏是用来对文件系统进行裁剪的,具体见下表
6 r" z. |9 \# e+ d9 u) @3 _   #define _CODE_PAGE        1    //就支持ASCII码,小内存伤不起
4 f( e' X* y3 k% s$ B+ b    。。。。。。。
) A0 L" I) w& Z  j1 p. D  V5 Z9 h   #define _VOLUMES        1        //注意:Tiny-FATFS仅支持一个逻辑设备,设为1) \# V7 r5 g' g$ @+ g8 U$ X
   #define        _FS_TINY        1        //就是这个地方,设为1之后就是Tiny-FATFS了,编译之后你会发现比设为0的时候用的RAM少不少,只需1K,当然牺牲就是变慢了8 u  {6 L2 n' n
   ; q* C& y  b& n9 C
4.编写diskio.c里面的5个接口函数。: ~! l8 g; t# ]- k! W/ ^1 b! f) k+ }
   前面5个接口函数我是参照原子哥的代码改的,我把除了SD_CARD的其他选项全删了,只留下SD_CARD的部分,因为其他的设备都用不上。(具体代码见附件)$ }: `7 I4 n. r  |
  get_fattime函数:8 C% `! i  ]3 u. @- `; i
DWORD get_fattime (void)
( ~1 S) n( u  |; @" Y4 h5 K* `9 A# m{                                 
: F# ?( \+ F, U' J4 k; p4 N        return (((u32)(RTC_DateStr.RTC_Year-(RTC_DateStr.RTC_Year>>4)*6)+20) << 25) /* Year */6 L% {7 s  K, W9 Y5 i  d3 y
              | ((u32)(RTC_DateStr.RTC_Month-(RTC_DateStr.RTC_Month>>4)*6) << 21)      /* Month*/1 e. C/ \) ~& ~9 J" Y5 R1 r' N
              | ((u32)(RTC_DateStr.RTC_Date-(RTC_DateStr.RTC_Date>>4)*6) << 16)       /* Day*/
& H: [% \1 n: W+ S$ c: t. d1 V5 F              | ((u32)(RTC_TimeStr.RTC_Hours-(RTC_TimeStr.RTC_Hours>>4)*6) << 11)      /* Hour*/9 h$ _; w1 P2 B2 S
              | ((u32)(RTC_TimeStr.RTC_Minutes-(RTC_TimeStr.RTC_Minutes>>4)*6) << 5)     /* Min*/
4 L9 E+ k# u. k              | ((u32)(RTC_TimeStr.RTC_Seconds-(RTC_TimeStr.RTC_Seconds>>4)*6) >> 1)     /* Sec*/, Z4 C1 M5 e7 A& F# ~
;
5 W& h. ~1 @5 _8 ^}' E1 D# T8 k6 t8 d+ i  Y* A

9 a" U# U, {3 h2 y6 J6 O  这里使用的是内部的RTC,每1S时间产生一个唤醒中断,然后在中断函数中更新日期时间,注意这里的日期时间都是BCD吗,例如0x16表示的是16年,所以上面做了转换。
0 q7 o3 s$ }3 q; z: \, n! f) j3 Y8 P7 W5 Y# A1 N
5.RTC初始化配置见附件源码了。下面是初始化过程中一个需要注意的地方4 v- P, I4 J! D" c' p: S, G9 [
  if ((RTC->ISR1 & RTC_ISR1_INITS) == RESET)  //Check calendar has been initialized or not?
5 G; l" k5 T* y  {5 W% r9 t2 j* ]0 D
    RTC_DateStructInit(&RTC_DateStr);
8 M  w8 P! \. @# Z, D    RTC_DateStr.RTC_WeekDay = RTC_Weekday_Friday;# I/ T7 p1 g. z& C& A
    RTC_DateStr.RTC_Date = 6;
& i7 i) d) W0 J* B   RTC_DateStr.RTC_Month = RTC_Month_March;
6 m0 Q* R/ \. o! k. ]1 O  e' h5 f    RTC_DateStr.RTC_Year = 16;. r& T0 ~, O. _/ E- l' D8 z
    RTC_SetDate(RTC_Format_BIN, &RTC_DateStr);4 n9 S9 `2 x8 J( a1 p: J- x
6 S# I) X8 z3 P) }  T2 G
    RTC_TimeStructInit(&RTC_TimeStr);2 C$ K  _/ h/ \2 J- \4 ~; z$ m
    RTC_TimeStr.RTC_Hours   = 20;
5 F) i* p# I1 G. C    RTC_TimeStr.RTC_Minutes = 02;
/ f0 T  [) e* R    RTC_TimeStr.RTC_Seconds = 00;
6 ~. G+ H" U8 q& M. _6 X" S3 {, }* H    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);   
1 q/ y/ z) L1 O' O1 ~  }( C/ w; ?7 d6 L

! H9 M: s" U* j0 n就是设置日期时间之前检查是RTC是否已经被设置过了,设置过了就不需要设置了。类似于stm32的备份寄存器,这样子只要不断电RTC的时间就不会复位。顺便提一句,STM8l的RTC还是很稳定、很准的,当时测了两三天跟电脑的时间差不了2秒,美中不足的是没有留出电池供电引脚,单片机断电就完了。  Z% y! x9 n5 T3 U+ y
6.硬件SPI配置,这步非常简单,看图6 X. k8 j% U7 z  S1 |! `

! U$ b/ D# t  b5 Y4 a: }* I
, k4 m3 P# G( @5 m简简单单几句就把它给配置了,做好这个借口,直接就跟原子哥的MMC_SD.c和MMC_SD.H对接上了,修改很少。3 X; _% k# N& z8 h0 N1 e

) r7 m' L) @7 o! ]8 H7.最后主函数:不适用内存分配函数,直接全局变量作为静态工作区。
1 _8 l$ Z# J& ~0 w  ! c3 m& O+ m# c2 j( X: ?
测试代码:挂载并新建文件/ `+ v# r' k! k( h) t% F
  
0 I, O1 B" Q( t: m0 H$ g/ b! [$ {" y7 A
编译运行结果(RAM包含了自己测试用的一个长度为514字节的buff数组):
2 D) \. l$ ]0 r, N* L
# F6 N5 P0 N4 W" t2 U: t9 N' e  J1 |/ P6 q  T' r

9 N( `+ i6 L8 h! a2 F在工程Backup文件夹里面还有一段测试读文件的代码:+ x* K$ o/ ~- m- ~1 \* V* e
   res = f_open(&fl,"news/news.txt",FA_READ);   % E6 L1 [' G, A2 s2 i. P' n) L. v
   if(res == FR_OK)4 x$ K6 d) L$ K# h! Z0 j. q
   {0 k" s  E1 U( l) l0 P5 Q
     Usart1_Str("Open file ok!\r\n");
! s& x4 b, g# C( E6 Y: r, K- X: n     Usart1_Str("The news is:\r\n");
3 R: s  A- Z: o2 B     do8 z. V2 _4 M' f( v6 @
     {
1 Q/ D  _- o( P) c7 O/ w6 r       //for(i=0;i<50;i++) buff = 0;6 @* \% m2 @: Q
       res = f_read(&fl,buff,512,&r);
* j# [6 K; F. g       //Usart1_Str(buff);
" b+ P9 W( b2 P       if(res || r<512): ]6 W+ h2 o) o( r9 H2 d, W
       {7 K+ H- J8 s% C4 t- @% F
          Usart1_Str("Read over!\r\n");6 `* o" q* y6 c9 `% s8 x" q
         break;   //error or eof    9 }& p: L; ~. J0 L( h) V7 x$ r* }
       }) k: p! f# M% R% _7 w( ]! n: U
     }& ]. R+ |3 O2 q& d
     while(1);
1 D/ J3 Q: l  r: ^- q6 T% j: z   }4 {* I9 f7 @: W0 w& }
   else0 \$ Y1 k. S9 v
     Usart1_Str("Open file failed!\r\n");
0 W- C; y. @1 J" F   f_close(&fl);0 ]5 r8 h$ w: I& C! `" ~9 u

! U' S7 D9 E1 L8 U! `
/ z8 ~$ Q" K7 \6 H! f6 @4 A事先在SD卡里新建一个news/news.txt文件,大小为1026KB,最后测试读出时间是14秒,平均速度是60多Kbyte/s的读出速度,对于一般应用相当够用;# ~/ y) [% Y1 S" K, `
跟另一个用模拟SPI写的工程比较,读取同样的这个文件,耗时一分49秒,平均速度只有10Kbyte/s左右。写入速度没测试,应该会慢一些。。
* F) c: v$ p9 V' R1 F) X2 F5 f& `' C! a8 y4 u

9 j0 r5 i9 s2 q6 Z' R- C0 k* O下载:
+ @# b" S/ j5 N! ?8 t- j% l% s' F
游客,如果您要查看本帖隐藏内容请回复

* @2 H( L+ C6 b8 }6 j

该用户从未签到

2#
发表于 2019-1-31 15:59 | 只看该作者
学习一下,谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-19 14:04 , Processed in 0.093750 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表