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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
移植Tiny-FATFS文件系统到STM8L152C6T6,使用硬件SPI+RTC
" C* K  w0 v! ]/ z6 I7 x0 U4 h7 [
最近老师需要做一个低功耗的各种环境参数采集仪,要求不多,就是采集各种参数并储存起来,但是要求低功耗。所以我第一时间就想到了stm8L系列单片机,发出去做的板子还没回来,就先使用现有的一块板子先调试文件系统和RTC这些啦。今晚还有点时间就写个移植过程吧,给后来人种一颗小树苗吧。。。
/ \& j' F- l# c2 f- ~* G" C- ^6 U) g1 W: h8 H% b+ q
硬件介绍:
4 _, l( m1 r8 X7 n3 }    单片机:STM8l152c6t6, 2K RAM,32K FLASH
. A! R0 e$ u4 N. y5 R: J    sd卡:4G和8G  7 J. \5 N* h7 N6 m6 ?# X
    接口连接://SD_DT3--SD_CS----------------PB40 r9 M) u9 E0 K. [: B$ M( t2 h/ P
                   //SD_CMD--spi1_MOSI--------PB61 E2 k4 {1 w8 Q- E+ c# C7 e& k
                   //SD_SCK--SPI1_SCK-----------PB5
1 C) F$ x% C/ ]! e/ h3 E. v                   //SD_DT0--SPI1_MISO--------PB7
4 L2 h1 R3 k0 S; S. a4 q" Y% S& E; L5 N( A
软件介绍:
0 B8 w2 ~9 q( x( L# f) @    编译器:IAR for STM8
) y3 I* F( c$ v6 a( ]& r( W    FATFs版本:R0.11a ,直接到FAT官网上面下载即可,下面附件也有。2 y/ V% k1 _- ]" d
    通信协议:硬件SPI   (附件也有一份软件SPI的源码)
6 m: j8 q7 P9 C5 L    RTC:使用STM8L内置的RTC; E; Z* m6 f. C
2 w8 U3 O  Y/ |7 m9 r  y
移植意义:可能大家觉得在STM8这种这么low的单片机上面运行FAT文件系统没什么意义,但是我觉得STM8l在用在低功耗采集或者信息节点的场合很多时候都需要存储数据,那么说到存储数据最适合的存储介质我觉得就是SD卡了,低成本大内存。那么自然想到FAT,存储的文件可以直接在电脑打开,每天新建一个文件来存储等。所以我觉得这东西上面使用FAT还是很有意义的。Tiny-FATFS需要单片机的1K的RAM用做工作区,具体需要多大的FLASH看你的要求了,可以适当的裁剪FATFS,我编译出来是20多K。
) r; `: N% i7 F" X. c) F% a$ H+ [8 s6 l3 D
移植步骤:
7 d# d! l* X, k   1.下载FATFS源码包,解压之后把src文件夹直接复制到工程目录中,并把带的字库和说明删掉,如下图;! v6 x# C, p7 e" c, d7 ?- t
   
4 s% [! I5 W' C2 E" d. ~! q   2.打开STM8工程,把FATFS中的xx.c文件(diskio.c和ff.c)添加至工程目中,并在option中包含路径
! j$ |' ~# @+ c' O, H  
3 Z/ o) l' d7 ~& `8 {   3.配置ffconf.h(简要说下,具体可参考原子哥的手册);/ n/ ?8 J% o4 N3 m  Q+ T
   #define _FS_READONLY        0    //可读可写5 j1 Y3 r7 \6 b4 A  W- S/ Z( {/ t
   ##define _FS_MINIMIZE        3    //_FS_MINIMIZE、 _FS_READONLY、 _USE_STRFUNC、 _USE_MKFS、_USE_FORWARD 这些宏是用来对文件系统进行裁剪的,具体见下表8 F: Z* J" v0 U* V9 R  ~8 W' a
   #define _CODE_PAGE        1    //就支持ASCII码,小内存伤不起) o4 P; w) k  q: W4 Z- d' N
    。。。。。。。
  m# [$ D- {9 T! L   #define _VOLUMES        1        //注意:Tiny-FATFS仅支持一个逻辑设备,设为1
. H, B% Y2 ^6 Y* {: B+ M   #define        _FS_TINY        1        //就是这个地方,设为1之后就是Tiny-FATFS了,编译之后你会发现比设为0的时候用的RAM少不少,只需1K,当然牺牲就是变慢了6 j6 G+ o; n  d4 o2 p  d- e5 S7 }
   ! ^' _# G# W: ~3 b/ s/ ~( E2 H
4.编写diskio.c里面的5个接口函数。; E- l4 J7 o% q, X; T
   前面5个接口函数我是参照原子哥的代码改的,我把除了SD_CARD的其他选项全删了,只留下SD_CARD的部分,因为其他的设备都用不上。(具体代码见附件)
: z& Y! a. ^9 Z" c5 [" v  W5 K2 H4 V  get_fattime函数:
0 W) M# \) L+ B. p8 z8 B' zDWORD get_fattime (void)
, G# C' f, x+ `' d- B{                                 ( S7 {5 D9 J0 L$ k9 s
        return (((u32)(RTC_DateStr.RTC_Year-(RTC_DateStr.RTC_Year>>4)*6)+20) << 25) /* Year */
. j+ k/ q' P) @/ ^& B7 E              | ((u32)(RTC_DateStr.RTC_Month-(RTC_DateStr.RTC_Month>>4)*6) << 21)      /* Month*/
4 v# |9 o+ I9 n7 G( a9 n4 o              | ((u32)(RTC_DateStr.RTC_Date-(RTC_DateStr.RTC_Date>>4)*6) << 16)       /* Day*/3 b0 w6 a, `2 T% \4 e: }4 ^
              | ((u32)(RTC_TimeStr.RTC_Hours-(RTC_TimeStr.RTC_Hours>>4)*6) << 11)      /* Hour*// d8 Z2 A3 g% b0 m: z
              | ((u32)(RTC_TimeStr.RTC_Minutes-(RTC_TimeStr.RTC_Minutes>>4)*6) << 5)     /* Min*/
* I7 X5 i6 r0 o: [              | ((u32)(RTC_TimeStr.RTC_Seconds-(RTC_TimeStr.RTC_Seconds>>4)*6) >> 1)     /* Sec*/
6 P6 b8 M, \- k, S0 a4 z: ^;3 N/ ]) z: T7 M
}
5 ~  |+ N7 `: |0 a& B
( t& z% u9 O6 I, X  这里使用的是内部的RTC,每1S时间产生一个唤醒中断,然后在中断函数中更新日期时间,注意这里的日期时间都是BCD吗,例如0x16表示的是16年,所以上面做了转换。
' [" n& _$ B' Z  O) g) k9 U  q& U
5.RTC初始化配置见附件源码了。下面是初始化过程中一个需要注意的地方: m/ ]9 P/ M6 P5 s9 s
  if ((RTC->ISR1 & RTC_ISR1_INITS) == RESET)  //Check calendar has been initialized or not?$ ^2 x2 C  s$ f- N/ y& P
  {& I8 g' B8 B4 U+ E6 K7 h
    RTC_DateStructInit(&RTC_DateStr);7 Y+ A" G+ A' |: v/ F
    RTC_DateStr.RTC_WeekDay = RTC_Weekday_Friday;
" w! c* M  y! K) W    RTC_DateStr.RTC_Date = 6;9 S9 ], A" Q+ v) {4 k3 l
   RTC_DateStr.RTC_Month = RTC_Month_March;# v9 Y: G8 W, p. h! o6 y
    RTC_DateStr.RTC_Year = 16;
& a3 d1 O. T# s6 O1 C    RTC_SetDate(RTC_Format_BIN, &RTC_DateStr);
, y& w8 D: c- g1 g0 \) a0 I! q! B; R0 n
    RTC_TimeStructInit(&RTC_TimeStr);& i. X9 N, Y# u$ F1 `
    RTC_TimeStr.RTC_Hours   = 20;; F1 H' h- J7 H
    RTC_TimeStr.RTC_Minutes = 02;
! ?. A2 L! L# |* b) b! K    RTC_TimeStr.RTC_Seconds = 00;' j0 y7 [5 y; b; @+ K: `
    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);    ( b5 K: P, f2 a1 W9 m2 ]
  }
0 s; e5 f. F; ^
1 P; y/ u, j! w就是设置日期时间之前检查是RTC是否已经被设置过了,设置过了就不需要设置了。类似于stm32的备份寄存器,这样子只要不断电RTC的时间就不会复位。顺便提一句,STM8l的RTC还是很稳定、很准的,当时测了两三天跟电脑的时间差不了2秒,美中不足的是没有留出电池供电引脚,单片机断电就完了。
7 l+ S3 x- k7 z: p3 D6.硬件SPI配置,这步非常简单,看图
4 V$ w; B* t4 S. l: i; {2 U, v$ F

/ ]1 G/ G0 A: |. I7 s+ g" O% Q* Q, ^! x简简单单几句就把它给配置了,做好这个借口,直接就跟原子哥的MMC_SD.c和MMC_SD.H对接上了,修改很少。
( O* ^5 G) O6 Q7 U8 ~3 z6 h0 ~" y5 a* \* n
7.最后主函数:不适用内存分配函数,直接全局变量作为静态工作区。
4 M; R: @% ^3 y3 T/ H! n    W! [' h$ Q2 c, H7 ?
测试代码:挂载并新建文件' r8 c, [1 s$ F& x/ j
  
( D0 y6 Z" z& i" [5 Q( y5 F* I8 m: h$ r6 P3 b/ ?
编译运行结果(RAM包含了自己测试用的一个长度为514字节的buff数组):
: a( w, S/ D6 }% b; Z5 f/ z3 d
! m) z+ s9 h6 x
* q! Z$ H' H7 E/ T4 Q" V$ G( T$ _6 L1 T/ g# X8 P: C! S) }
在工程Backup文件夹里面还有一段测试读文件的代码:
. p+ z2 d) }6 ]4 F   res = f_open(&fl,"news/news.txt",FA_READ);   
% F8 Z& N) P6 b- |7 y  {   if(res == FR_OK)
6 x# Q! {- O) K. i4 T- E   {  `! s: n6 ^6 Y" i! J
     Usart1_Str("Open file ok!\r\n");- E6 u( K9 N! F* _( ^% J
     Usart1_Str("The news is:\r\n");
! M+ [/ \5 y1 t( t" c, a- Z& h     do
% Y! A( p0 g6 V     {
% O& D, Z# o! U8 }* ^: V+ r2 X       //for(i=0;i<50;i++) buff = 0;
" ~  p9 s) n  P- g5 j/ L       res = f_read(&fl,buff,512,&r);
# p) n' ?% _6 m  k       //Usart1_Str(buff);
& _/ J% _$ }) ~% r5 Q) w       if(res || r<512)
. k8 H- G" B+ C) f       {
% ^: k0 W" @" m          Usart1_Str("Read over!\r\n");
, o8 U6 A+ m  G, S5 Q- @         break;   //error or eof    ; w6 g# G7 h8 w
       }
& r# J/ }, b  c# l     }
- L2 g% w% H4 O: O     while(1);
7 Y5 a* R9 ?, I! \% o. m! s   }
; S1 b& M9 P) P$ Y0 A   else7 d, Q$ Y1 T' |& b( f+ @; j
     Usart1_Str("Open file failed!\r\n");: V7 ]+ s# @+ U% ~) I0 s1 P
   f_close(&fl);
  g0 D0 A3 |7 G2 z' \& @- a1 E$ y3 A/ ^# x, P9 W% k
' U  ?& M  J( Q6 @3 [% c' _. b
事先在SD卡里新建一个news/news.txt文件,大小为1026KB,最后测试读出时间是14秒,平均速度是60多Kbyte/s的读出速度,对于一般应用相当够用;
: M$ D, ^: e; I* q跟另一个用模拟SPI写的工程比较,读取同样的这个文件,耗时一分49秒,平均速度只有10Kbyte/s左右。写入速度没测试,应该会慢一些。。( R6 W5 G& [: v5 }* z' T

! t5 V' R* f) Y# v! g, C' @
7 ^( ~' Q0 R+ V" W* h6 i' w6 s下载:" ]) Y1 I! Y1 r' w4 [, z
游客,如果您要查看本帖隐藏内容请回复

& A1 f! i/ ~* a3 [& r

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-23 13:50 , Processed in 0.125000 second(s), 26 queries , Gzip On.

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

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

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