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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
移植Tiny-FATFS文件系统到STM8L152C6T6,使用硬件SPI+RTC
- g0 t$ H/ q: {$ S. g- J% Q* H8 p3 S
最近老师需要做一个低功耗的各种环境参数采集仪,要求不多,就是采集各种参数并储存起来,但是要求低功耗。所以我第一时间就想到了stm8L系列单片机,发出去做的板子还没回来,就先使用现有的一块板子先调试文件系统和RTC这些啦。今晚还有点时间就写个移植过程吧,给后来人种一颗小树苗吧。。。+ c5 V/ ]" E1 E* y
0 Z8 X  ?; d. b: P6 p' k
硬件介绍:% P: t! ?( K6 D5 d
    单片机:STM8l152c6t6, 2K RAM,32K FLASH
0 \  |8 K% Z# ?; g! K    sd卡:4G和8G  
) L1 W9 C+ q1 E/ o- R    接口连接://SD_DT3--SD_CS----------------PB4+ T3 W. L3 S& C7 V5 D
                   //SD_CMD--spi1_MOSI--------PB6% B) g" z5 ~. Q3 A' c
                   //SD_SCK--SPI1_SCK-----------PB50 Q. h% Y; Y: ?: o+ e& o* P
                   //SD_DT0--SPI1_MISO--------PB7( s5 ^# u& h8 q7 ~
1 z% P: k( K) ]) M9 o/ `4 f. F
软件介绍:
6 C) u2 k4 Q7 y! ^    编译器:IAR for STM8! V% A% H( T% G. ^1 u+ l
    FATFs版本:R0.11a ,直接到FAT官网上面下载即可,下面附件也有。
9 ]) q* @: |9 a$ }+ n! L, M    通信协议:硬件SPI   (附件也有一份软件SPI的源码)
, F2 }6 k! F( w4 L+ n9 n+ M    RTC:使用STM8L内置的RTC
9 O4 ]7 Z' m# p' Y9 O- M* a' @. J' G! a8 C7 V1 [) n! l) ?
移植意义:可能大家觉得在STM8这种这么low的单片机上面运行FAT文件系统没什么意义,但是我觉得STM8l在用在低功耗采集或者信息节点的场合很多时候都需要存储数据,那么说到存储数据最适合的存储介质我觉得就是SD卡了,低成本大内存。那么自然想到FAT,存储的文件可以直接在电脑打开,每天新建一个文件来存储等。所以我觉得这东西上面使用FAT还是很有意义的。Tiny-FATFS需要单片机的1K的RAM用做工作区,具体需要多大的FLASH看你的要求了,可以适当的裁剪FATFS,我编译出来是20多K。/ `* ]% @5 \( Z
9 ~1 `8 T) V- z3 H
移植步骤:! o; X% X8 h7 @/ W! X7 r' @+ v
   1.下载FATFS源码包,解压之后把src文件夹直接复制到工程目录中,并把带的字库和说明删掉,如下图;
" R, C$ y& j! m) z   ( e6 Q$ y7 I. A2 _6 n
   2.打开STM8工程,把FATFS中的xx.c文件(diskio.c和ff.c)添加至工程目中,并在option中包含路径0 b& q, W! r% _  O# r
  
0 v0 I7 K! b; s, e   3.配置ffconf.h(简要说下,具体可参考原子哥的手册);
% `. \# S2 o' s: F% O$ F) ~6 ]   #define _FS_READONLY        0    //可读可写
% w5 ?2 q. e4 E' r% L4 X/ Y   ##define _FS_MINIMIZE        3    //_FS_MINIMIZE、 _FS_READONLY、 _USE_STRFUNC、 _USE_MKFS、_USE_FORWARD 这些宏是用来对文件系统进行裁剪的,具体见下表
' |0 U# F( c! z9 h0 O   #define _CODE_PAGE        1    //就支持ASCII码,小内存伤不起
, U& I: F4 j6 I7 n: h' ~3 `5 D    。。。。。。。' W! Z2 ]" {) x  p
   #define _VOLUMES        1        //注意:Tiny-FATFS仅支持一个逻辑设备,设为1
) @% l& v& P( m0 D8 l# E; ?   #define        _FS_TINY        1        //就是这个地方,设为1之后就是Tiny-FATFS了,编译之后你会发现比设为0的时候用的RAM少不少,只需1K,当然牺牲就是变慢了$ Q6 q7 ]- B3 f/ _1 @1 Z- D% D
   0 f2 G0 @. o6 G2 X" a6 R8 p
4.编写diskio.c里面的5个接口函数。. `$ O9 H8 F1 E$ \+ O7 x
   前面5个接口函数我是参照原子哥的代码改的,我把除了SD_CARD的其他选项全删了,只留下SD_CARD的部分,因为其他的设备都用不上。(具体代码见附件)5 l+ L) u" j/ e( ?
  get_fattime函数:! Q* i1 k" {8 k& J
DWORD get_fattime (void)0 z6 Q  k  U4 d0 ~2 Y! u
{                                 . {7 E. Y  d( P  @2 d; I
        return (((u32)(RTC_DateStr.RTC_Year-(RTC_DateStr.RTC_Year>>4)*6)+20) << 25) /* Year *// ?" B; ?& ~$ V6 D' K" @
              | ((u32)(RTC_DateStr.RTC_Month-(RTC_DateStr.RTC_Month>>4)*6) << 21)      /* Month*/. E9 `: J: N, [8 M! X1 }  g: w
              | ((u32)(RTC_DateStr.RTC_Date-(RTC_DateStr.RTC_Date>>4)*6) << 16)       /* Day*/
+ e- C, f9 R0 R( r: O              | ((u32)(RTC_TimeStr.RTC_Hours-(RTC_TimeStr.RTC_Hours>>4)*6) << 11)      /* Hour*/$ [# z' r2 q; f# o, P5 e7 K5 E. d
              | ((u32)(RTC_TimeStr.RTC_Minutes-(RTC_TimeStr.RTC_Minutes>>4)*6) << 5)     /* Min*/
  c3 Q/ @, z6 @+ p( ]              | ((u32)(RTC_TimeStr.RTC_Seconds-(RTC_TimeStr.RTC_Seconds>>4)*6) >> 1)     /* Sec*/
, b! v- E- B6 v5 y  G5 `;
' Y9 }( I- N( A2 e" i8 d}9 ^$ a6 N8 h; r8 k; \' n9 N
( @. z- G$ O6 \2 o) M8 n
  这里使用的是内部的RTC,每1S时间产生一个唤醒中断,然后在中断函数中更新日期时间,注意这里的日期时间都是BCD吗,例如0x16表示的是16年,所以上面做了转换。
' @  M% W: P) z. v9 z) l% L, {( ]( O( P% s0 _! O
5.RTC初始化配置见附件源码了。下面是初始化过程中一个需要注意的地方
! A' A5 e+ y# v8 G% i  x  if ((RTC->ISR1 & RTC_ISR1_INITS) == RESET)  //Check calendar has been initialized or not?' \' `9 H5 \/ Z- U
  {6 f, r: W0 ]1 h& p: g2 T# x/ ~3 Q
    RTC_DateStructInit(&RTC_DateStr);9 D# r5 t5 C' d- e* w
    RTC_DateStr.RTC_WeekDay = RTC_Weekday_Friday;6 }) z& Z& I1 V; F
    RTC_DateStr.RTC_Date = 6;
+ i# n* h5 `% n8 L   RTC_DateStr.RTC_Month = RTC_Month_March;) }; p! C4 J4 n1 B1 w: J- }0 y
    RTC_DateStr.RTC_Year = 16;- V* Y. v: @6 X* Y' `
    RTC_SetDate(RTC_Format_BIN, &RTC_DateStr);
4 ]$ E! k+ x& E' C( R2 o% W4 ^# j' q6 _3 F% b, P3 _2 ^
    RTC_TimeStructInit(&RTC_TimeStr);
# {2 I& F$ i$ ]$ H/ p* |3 ?    RTC_TimeStr.RTC_Hours   = 20;
# Z; @1 o9 Y* G  E6 \2 r    RTC_TimeStr.RTC_Minutes = 02;
' ~. _7 t- u' }/ @$ K    RTC_TimeStr.RTC_Seconds = 00;
6 v1 ?  h/ y1 u5 ?0 G1 G    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);    $ M, j3 V2 ?$ C" V) y) @
  }
8 c# D7 K4 B& l9 k! T; y
; g4 }: v* s7 s5 q8 p; s( u就是设置日期时间之前检查是RTC是否已经被设置过了,设置过了就不需要设置了。类似于stm32的备份寄存器,这样子只要不断电RTC的时间就不会复位。顺便提一句,STM8l的RTC还是很稳定、很准的,当时测了两三天跟电脑的时间差不了2秒,美中不足的是没有留出电池供电引脚,单片机断电就完了。: u1 h3 ~* ~3 W+ k4 q9 C
6.硬件SPI配置,这步非常简单,看图
# ^2 ^1 V% ]' x7 ~) z6 u+ C' C6 j+ `& c. d
! e; d3 z5 J( S/ P
简简单单几句就把它给配置了,做好这个借口,直接就跟原子哥的MMC_SD.c和MMC_SD.H对接上了,修改很少。
& ]. ?( b3 {4 u% P; z  q( T  ^6 a8 h( `2 c7 T- o0 f
7.最后主函数:不适用内存分配函数,直接全局变量作为静态工作区。
7 h5 O5 @( c: q$ ~2 {2 J  2 g0 F1 }5 L9 X, l$ A
测试代码:挂载并新建文件( W- O! I8 O, i: o! X7 H; J
  4 [/ q8 t: b- C
8 F$ k: g+ {. P. M) h
编译运行结果(RAM包含了自己测试用的一个长度为514字节的buff数组):
) O2 y: Z7 v+ l+ _/ [& D) n7 K; F4 v/ H- J# i2 G

- o3 i, m& }  g! t" _5 c5 p; W3 s4 K% j) l, n* p
在工程Backup文件夹里面还有一段测试读文件的代码:
# n- `. _" a- E" w. F1 e& |   res = f_open(&fl,"news/news.txt",FA_READ);   
7 z. c) n  n; y3 R$ s, q   if(res == FR_OK): s: P  [* r( R7 L
   {9 ]. m- L6 e3 Q1 ^5 ?4 d4 l0 Y3 D
     Usart1_Str("Open file ok!\r\n");% R. J' q6 \6 H% c  z+ d
     Usart1_Str("The news is:\r\n");
% U1 T/ K  c8 ]  P' ^% V; f     do
. {3 I  F3 M8 }. }$ |+ c+ Q     {7 w% D% O* L+ F5 ]7 G( D
       //for(i=0;i<50;i++) buff = 0;+ K3 M6 X% }! V$ _6 i6 k0 E
       res = f_read(&fl,buff,512,&r);
# R) v+ m! T* p7 s       //Usart1_Str(buff);
6 }! Z- I2 V% V/ S5 @' v% P       if(res || r<512)
- c, R: J1 J4 X* q       {. [. s! G9 b" k8 p/ ?9 S
          Usart1_Str("Read over!\r\n");7 u( Q! s- G1 \2 H' c
         break;   //error or eof   
3 D$ J0 R$ r5 W/ {! e       }
+ M$ O. Z/ X5 K& o; F: E     }
7 `1 S5 S  t4 A2 @' C% v( z     while(1);
" o( f! {' s8 G0 q# f; S! B% V   }
. w6 E+ C5 i& T! U, E# }   else$ g+ t8 R9 J: s5 K9 }! d  b; q" F9 t& w: P
     Usart1_Str("Open file failed!\r\n");" O$ |7 X( t! X
   f_close(&fl);) p+ U7 Q) b. c) v
( d* C/ M5 r% P* {0 g& H
8 L  p* h9 v) X5 Q# X
事先在SD卡里新建一个news/news.txt文件,大小为1026KB,最后测试读出时间是14秒,平均速度是60多Kbyte/s的读出速度,对于一般应用相当够用;/ l9 f4 V+ \/ @% l6 @, d5 N  }9 k
跟另一个用模拟SPI写的工程比较,读取同样的这个文件,耗时一分49秒,平均速度只有10Kbyte/s左右。写入速度没测试,应该会慢一些。。
1 |% f" j% ^9 D4 E2 m7 U
7 r# q1 A8 Q; j/ [7 _+ D& J( H" s% I. P$ x
下载:% W0 R* o. y/ r% i1 I6 Y
游客,如果您要查看本帖隐藏内容请回复

  F6 H. q  A& o0 D# ?: ^% g5 n8 k

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-6 21:24 , Processed in 0.140625 second(s), 26 queries , Gzip On.

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

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

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