原创 智林STM32开发板上的FatFS移植过程分析(十二)

2010-3-23 14:55 3206 6 6 分类: MCU/ 嵌入式

 


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


十二、开发板RTC时钟的调整程序设计


1、现在时钟运行情况


现在开发板上运行的时钟系统情况是这样:(1)能够持续不断地计时,即使断电也能够维持正确的时间格式。2不能显示日期


其实现理论是这样:(1)每次运行时读取备份域寄存器的内容,若为指定的值0xAA,说明曾经初始化过,则继续运行就可以了。若不是,初始化RTC,并设置初始时间。(2)由于一天过去后,235959后会溢出,所有每次运行都检查是否超过0x00015180(对应24小时),若超过0x00015180,则循环减去0x00015180,直到小于0x00015180为止。(3)同时在开发板运行过程中,在秒中断时也检查该数值,若超过0x00015180,则减去0x00015180,保持数值小于24小时。


 


2、新设计时钟系统的目标


1)能够显示日期,以XXXXXXXX的格式显示。


2)能够显示时间,以XXXXXX的格式显示。


3能够设置日期和时间


3、设计实现的思路


1)采用两个命令:date time。如果不带参数,则显示当前时间。如果带参数,则调整当前日期和时间。


2)设置时,要对参数字符串的格式进行简单的验证。


4、程序实现的步骤


       1)在开发板复位时,首先检查备份域标志,若没有设置,则为RTC时钟设置时钟源、设置初始计数值,并设置备份域标志


       2)如果标志已设置,则将APB1时钟与RTC时钟同步就行了。(根据RTC要求,这样可读寄存器里的数值才是正确的)。


       3)现在不需要秒中断了,可以取消。


3在命令终端输入time时,将调用下面的函数:


void UartCmdTime(u8 argc,void **argv){


  u8 s[10];              //输出时间字符串


  u32 RTCCount;         //用于获取RTC的当前计数


  TimeStruct CurrentTime; //时间结构定义


typedef struct {


u16 Year;u8 Month;u8 Date;u8 Week;u8 Hour;u8 Minute;u8 Second;}TimeStruct;


  u8* ParaPtr= ( u8* ) ( argv[1] );      //类型强制转换。


  if ( ParaPtr !='\0' ){      //如果有输入参数


      if ( ParaPtr[2]==':' && ParaPtr[5] == ':'){ //简单检查参数格式


             RTCCount=    RTC_GetCounter(); //获取RTC的当前计数


               Time_CountToTime(RTCCount,&CurrentTime);//首先获取系统的时间


                Time_GetTimeFromStr( ParaPtr&CurrentTime ); //改变时间结构中年月日


                Time_Adjust( &CurrentTime );//调用设置时间函数。实际调用Time_TimeToCount将日期时间转换为计数值并写入RTC计数寄存器。


                Uart_PutString ( "Time set finished !\r\n" );       }


         return;  }


  RTCCount= RTC_GetCounter(); //获取RTC的当前计数


  Time_ CountToTime (RTCCount,&CurrentTime); //转换为具体时间


  //利用库函数将时间转换为格式化字符串


sprintf((char*)s,"%02d:%02d:%02d",CurrentTime.Hour,CurrentTime.Minute,CurrentTime.Second);


  Uart_PutString(s); /*在屏幕上显示*/


  Uart_PutString("\r\n");  //换行,回到命令提示符}


这里先准备好函数Time_TimeToCount()Time_CountToTime()的框架,编译通过,然后再进行程序的设计,整个程序的重点和难点就在这两个函数。


 


5、从计数值取得时间,Time_CountToTime()函数的设计


 


计数规律:每秒加132位的计数器是137年溢出一次,所以要设定一个参照时间。从该时间开始往后计数。我这里采用<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1980-01-01000000为开始计数时间,我记得linux好像是从1970年开始的。


每天的秒数为24*60*60=86400=0x16580;每四年的天数为366+3*365=1461=0x5B5(因为能被4整除的年份2月有29);


如我得到一个计数值 Xcount,拿它除以0x16580便得到从198011以来经过的天数Xday,其余数便是这一天已经走过的秒数Xsec


Xsec秒数除以3600便得到小时数,其余数为Xsec,再除以60便得到分钟数再得到的余数就是秒数


关键是如何从天数得到年月日和星期的值,星期值应该这样求取,假定1980-1-1日是星期X,则天数除以7的余数就是相对X往后移的天数这个数值+X再对7取模,就是真正的星期数。


如何取得年数呢?拿天数Xyear除以每四年的天数1461,就得到经过4年的个数X4,,其余数为4年内的天数,若小于366,则为第一年。实际年数为1980+4*X4。若大于等于366,则减去366后再除以365就是后三年中经过的年数X3实际年数为1980+4*X4+1+X3。(由于2000年正好能被400整除,所有这一年2月有29日,所以就不同考虑逢百年不闰的问题了,2100年还早着呢。)。


月份用造表的方法解决:


闰年表{0316091121152182213244274305335366}


非闰年表{0315990120151181212243273304334365}


根据一年内剩余的天数查表,返回月份。


总天数减去该月对应的天数再加上1,就是对应的日期。


 


6、从时间计算出计数值,Time_TimeToCount ()函数的设计


年数减去1980得到经过的年数Xyear年数除以4得到4年的个数X4y,如果余数YU<1则该年为闰年。用闰年表取出该月的天数Xyue,总天数Xday=1461*X4y+Xyue+日期-1


如果余数YU大于1,则使用非闰年表取出月天数,总天数=1461*X4y+366+YU-1*365+Xyue+日期-1


总天数*96400+小时*3600+分钟*60+实际秒数=总的计数值。


 


 


 


 

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条