打印
[菜农群课笔记]

7月22日晚群课笔记

[复制链接]
3051|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 51小刚 于 2011-7-23 08:58 编辑

首先先了解三个概念:rtc, gps,电波表

前两个就不用我解释了,电波表是机身由原子时钟和无线电接收系统组成,由
国家授时中心发出准确时间,通过无线电接收系统接收、经CPU处理后显示时间,电波表30万年误差不会超过一秒。简单的说就是一种接受标准时间信息的电波后,可以自动校对时间的手表

两个相关的链接http://www.hotpower.org/HotAjax/HotPower_HotAjax.htmlhttps://bbs.21ic.com/icview-248981-1-1.html
涉及六个算法
0.世纪内星期算法
3480

1.菜农星期表格
3492

2.菜农星期公式
3500

3.菜农星期第二公式
3500

4.基姆拉尔森星期公式
3516

5.蔡勒完整星期公式
3516

6.蔡勒星期公式(无越界校验)
3508 (此公式不能在计算机实战)

具体大家可看菜农大叔的帖子。以下为群课总结,希望对大家有帮助。
菜农大叔说:
俺以前的感觉,ST的RTC应该是“假的”,ST的RTC我们需要自己处理时间,年月日时分秒,甚至星期,而一般真的RTC,不需要你处理的,甚至闹铃都可以,nxp,nuvoton都是真的,当然还有很多外围模块。


这是例程通过串口输出的字符串,[6]内是星期,(1)是24小时显示模式。
俺为何又要讲星期算法呢???
在任何rtc模块中,一般都是0点翻转,你在其它时间强行写入即改写的,一般不做校验,例如,今天是星期五,你可以输入星期X,新唐的RTC也是这样的不校验,即使0点翻转,故新唐的RTC的星期,为week%7的内部算法,这是其一。有个问题,没有外接电池引脚,这是不好,ds1302,它也是0点翻转校验的,gps的出现,使rtc淡化了,几乎无用了,手机里有的也用gps校准rtc,所以,这种应用rtc就不怕掉电了,所以,这些都需要星期的算法。
难民人:上传电波表图,方便大家理解







中国的长波授时编码标准为BPC。目前该长波授时的时间编码还未正式公开,其专利由西安高华实业有限公司持有。同时该公司也是中国第一台长波授时电波钟的开发者
菜农大叔抽烟后:
我们是东8区,那么,就有2个“断点”,上午8点和下午四点,我们的8点,是伦敦的0点,此后我们是同一天,我们的0点,就是伦敦的下午4点,但是我们进入了新的一天,新的一周,新的一年,新的世纪,新的。。。。gps此时还是伦敦时间,不会翻转,
所以,我们必须把伦敦时间+8小时,对否????
故,我们必须知道星期算法,才能进行换算,故我们的0点,gps不翻转,但是我们必须软翻转,但是在上午8点,gps翻转,故我们的时间也要修正,假若8点我们再翻转就错了,再说电波表,由于陕西天文台不是24小时授时,故需要rtc的支持,但是gps也需要,应该可能在屋内或大树下,信号不好时,BPC是通过长波发送出去的。
为何要星期算法?我们就需要年月日,时分秒呀?星期无用呀?这些人都要被

下面菜农老师讲了例程:
最著名的星期公式有蔡勒和基姆拉尔森两个(俺目前知道的),俺的公式是在没参考任何公式的情况下推导出来的,https://bbs.21ic.com/icview-248985-1-1.html 这个帖子了有俺对他们的推导过程,并且对蔡勒公式进行了修正,因为那是在125年前推导出来的,没有考虑计算机的溢出问题。
void rtc_t::SetWeek(uint32_t Year, uint32_t Month, uint32_t Day)
{
uint32_t DayOfWeek;
#if WEEK_M == 1
//月表=(13*Month+8)/5
static const char WeekTable[]="\x2\x5\x0\x3\x5\x1\x4\x6\x2\x0";
#endif
if (WriteEnable())
{
if (Month < 2)
{
//去年
if (Year > 0) Year --;//2000.3~2099.12
else Year = 9999;
//今年的1月2月是去年的13月14月
// Month += 12;
//今年的1月2月是去年的5月6月
Month += 4;
}
#if WEEK_M == 0
//世纪内星期算法
//工程编译长度合计3480个字节

DayOfWeek = ((Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;

#else

#if
WEEK_M == 1

//菜农星期表格=((百年%4)*5+年+年/4+月表+日)%7
//月表=(13*Month+8)/5
//工程编译长度合计3492个字节

DayOfWeek = (((Year/100)&3)*5+(Year%100)+((Year%100)>>2)+WeekTable[Month-3]+Day)%7;


#else


#if WEEK_M == 2

//菜农星期公式=((百年&3)*5+年+(年>>2)+(13*月+8)/5+日)%7
//工程编译长度合计3500个字节

DayOfWeek = (((Year/100)&3)*5+(Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;

#else

#if WEEK_M == 3

//菜农星期公式2=((百年*5)%20+年+(年>>2)+(13*月+8)/5+日)%7
//工程编译长度合计3492个字节

DayOfWeek = (((Year/100)*5)%20+(Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;


#else


#if WEEK_M == 4

//基姆拉尔森星期公式=(百年/4+百年*5+年+年/4+(13*月+8)/5+日)%7
//工程编译长度合计3516个字节

DayOfWeek = (Year/400+(Year/100)*5+(Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;


#else


#if WEEK_M == 5

//蔡勒完整星期公式=(203+百年/4-2*百年+年+年/4+(13*月+3)/5+日+1)%7
//工程编译长度合计3516个字节

DayOfWeek = (203+Year/400-(Year/100)*2+(Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;

#else //WEEK_M == 6
//蔡勒星期公式=(百年/4-2*百年+年+年/4+(13*月+3)/5+日+1)%7 (此公式不能在计算机实战)
//工程编译长度合计3508个字节

DayOfWeek = (Year/400-(Year/100)*2+(Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;


#endif


#endif


#endif


#endif


#endif

#endif

#if LOOK_H == 0
RTCs.DWR.Bits.DWR = DayOfWeek;
#else
RTC.DWR().DWR = DayOfWeek;
#endif
rtc_t::DayOfWeek = DayOfWeek;
}
}
例程可以通过WEEK_M选择一个,字节最短速度最快的当然是查表法,新唐的 RTC只支持本世纪,严格说一个为2000.3.1~2099.12.31,为什么,大家自己看俺的推导过程就明白了,菜农星期公式=((百年&3)*5+年+(年>>2)+(13*月+8)/5+日)%7,既然是本世纪,百年=20,那么(百年&3)*5=0,故:
//世纪内星期算法
//工程编译长度合计3480个字节

DayOfWeek = ((Year%100)+((Year%100)>>2)+(13*Month+8)/5+Day)%7;

用过外围RTC的人,还有NXP,新唐的 RTC,时间日期都是计算好,我们用时取出即可,不需要我们再去计算了,有人说无外接电池不好,这个是的,但大量的应用是某些的辅助,如辅助gps,电波表等高精度时钟源,这节课,实际是讲RTC的应用,主要是设置问题,
void rtc_t::SetCalender()
{
if (WriteEnable())
{
SetHourMode(1);//DRVRTC_CLOCK_24
SetDate(2011, 7, 15);
SetTime(23, 59, 0);
SetWeek(2011, 7, 15);
SetTickMode(0);
}
}
注意,星期不是外部输入的,而是星期公式算不来的,这样就不容易出错,俺主张,在设置时,只输入日期和时间即可,星期还是算吧,还有,星期是“密码”,可以检验gps协议里日期的真伪,这个例程没有加闹铃中断,新唐BSP里的RTC例程有的
rtc_t中断服务例程
bool rtc_t::isr(int vector)
{
#if LOOK_H == 0
RTCs.RIIR.Bits.TI = 1;
#else
RTC.RIIR().TI = 1;
#endif
return true;
}

void rtc_t::dsr(int vector, uintptr_t count)
{
GetCalender();
sem.do_post();
}

例程采用RTC每秒中断一次,即秒脉冲发生器,void rtc_t::dsr(int vector, uintptr_t count)
{
GetCalender();
sem.do_post();
}
在dsr()读日期,时间等信息,并为任务发送信号量。


难民人<lwslws201@qq.com> 21:59:54
有秒脉冲
还不是跟STm 的RTC一样?

菜农答曰:不一样的,此中断是当前所有实时的信息,不需要你计算的,取出来就是你想要得到的,不过新唐的 RTC里的数据是BCD码,有些晕,估计是受ds1302等影响吧,感觉有些“抄板”的嫌疑~~~,只是猜测。
John Lee:
bcd码对显示比较方便。

雁塔菜农:
是的

雁塔菜农:
LED数码管最好了

雁塔菜农:
应该是这个想法,后头问问国军

雁塔菜农:
void rtc_t::GetCalender()
{
#if LOOK_H == 0
Year = 2000 + RTCs.CLR.Bits.YEAR10 * 10 + RTCs.CLR.Bits.YEAR1;
Month = RTCs.CLR.Bits.MON10 * 10 + RTCs.CLR.Bits.MON1;
Day = RTCs.CLR.Bits.DAY10 * 10 + RTCs.CLR.Bits.DAY1;
Hour = RTCs.TLR.Bits.HR10 * 10 + RTCs.TLR.Bits.HR1;
Minute = RTCs.TLR.Bits.MIN10 * 10 + RTCs.TLR.Bits.MIN1;
Second = RTCs.TLR.Bits.SEC10 * 10 + RTCs.TLR.Bits.SEC1;
DayOfWeek = RTCs.DWR.Bits.DWR;
  ClockDisplay = RTCs.TSSR.Bits.HR24;
#else
  #if LOOK_H == 1
auto clr = RTC.CLR();
Year = 2000 + clr.YEAR10 * 10 + clr.YEAR1;
Month = clr.MON10 * 10 + clr.MON1;
Day = clr.DAY10 * 10 + clr.DAY1;
DayOfWeek = RTC.DWR().DWR;
auto tlr = RTC.TLR();
Hour = tlr.HR10 * 10 + tlr.HR1;
Minute = tlr.MIN10 * 10 + tlr.MIN1;
Second = tlr.SEC10 * 10 + tlr.SEC1;
  ClockDisplay = RTC.TSSR().HR24;
  #else
RTC.CLR()
.YEAR10.lambda([&Year](uint32_t y){Year = 2000 + y * 10; return y; })
.YEAR1.lambda([&Year](uint32_t y){ Year += y; return y; })
.MON10.lambda([&Month](uint32_t m){Month = m * 10; return m; })
.MON1.lambda([&Month](uint32_t m){ Month += m; return m; })
.DAY10.lambda([&Day](uint32_t d){Day = d * 10; return d; })
.DAY1.lambda([&Day](uint32_t d){ Day += d; return d; });
DayOfWeek = RTC.DWR().DWR;
RTC.TLR()
.HR10.lambda([&Hour](uint32_t h){Hour = h * 10; return h; })
.HR1.lambda([&Hour](uint32_t h){ Hour += h; return h; })
.MIN10.lambda([&Minute](uint32_t m){Minute = m * 10; return m; })
.MIN1.lambda([&Minute](uint32_t m){ Minute += m; return m; })
.SEC10.lambda([&Second](uint32_t s){Second = s * 10; return s; })
.SEC1.lambda([&Second](uint32_t s){ Second += s; return s; });
  ClockDisplay = RTC.TSSR().HR24;
  #endif
#endif
}

相关帖子

沙发
51小刚|  楼主 | 2011-7-23 08:51 | 只看该作者
下面的我不知道该怎么写了,晕了,故将聊天记录贴出来:
雁塔菜农<hotwc3@qq.com> 22:06:28
Lee老师很辛苦,也很暴力~~~
雁塔菜农<hotwc3@qq.com> 22:06:36
其头太残酷
John Lee<j.y.lee@yeah.net> 22:06:51
这个就不要讲了,整晕一大片
雁塔菜农<hotwc3@qq.com> 22:07:00
哈哈
日期:2011-7-22
难民人<lwslws201@qq.com> 22:07:41

雁塔菜农<hotwc3@qq.com> 22:07:55
红杏和老师头文件合写
John Lee<j.y.lee@yeah.net> 22:08:09
有个比较
雁塔菜农<hotwc3@qq.com> 22:08:16
红杏可以同时用于C/C++
雁塔菜农<hotwc3@qq.com> 22:08:32
老师的暂时只能用于C++
雁塔菜农<hotwc3@qq.com> 22:08:48
所以都不能放弃
雁塔菜农<hotwc3@qq.com> 22:09:35
老师不暴力的头文件和红杏有“一对一”的转换方法,很简单
雁塔菜农<hotwc3@qq.com> 22:09:54
#if LOOK_H == 0
RTCs.DWR.Bits.DWR = DayOfWeek;
#else
RTC.DWR().DWR = DayOfWeek;
#endif

雁塔菜农<hotwc3@qq.com> 22:10:16
把.Bits用()代换
雁塔菜农<hotwc3@qq.com> 22:10:32
s.换成 .
雁塔菜农<hotwc3@qq.com> 22:10:44
就相同了~~~
雁塔菜农<hotwc3@qq.com> 22:11:16
但是老师和暴力之处在于可以对位域连续操作
雁塔菜农<hotwc3@qq.com> 22:12:00
例如:
RTCs.CLR.Bits.YEAR10 = (Year % 100) / 10;
RTCs.CLR.Bits.YEAR1 = (Year % 100) % 10;
RTCs.CLR.Bits.MON10 = Month / 10;
RTCs.CLR.Bits.MON1 = Month % 10;
RTCs.CLR.Bits.DAY10 = Day / 10;
RTCs.CLR.Bits.DAY1 = Day % 10;

雁塔菜农<hotwc3@qq.com> 22:12:31
红杏只能一个位域一个位域的操作,但都是对一个寄存器的
雁塔菜农<hotwc3@qq.com> 22:12:46
故他们之间就有了“延时”
雁塔菜农<hotwc3@qq.com> 22:13:07
老师的:
RTC.CLR(0)
   .YEAR10((Year % 100) / 10, false)
   .YEAR1((Year % 100) % 10, false)
   .MON10(Month / 10, false)
   .MON1(Month % 10, false)
   .DAY10(Day / 10, false)
   .DAY1(Day % 10, false);

雁塔菜农<hotwc3@qq.com> 22:13:35
对一个寄存器下的所以位域一次操作
雁塔菜农<hotwc3@qq.com> 22:13:48
对一个寄存器下的所有位域一次操作

雁塔菜农<hotwc3@qq.com> 22:14:21
#if LOOK_H == 0
GPIOAs.DMASK.Regs = ~0b111100;
GPIOAs.DOUT.Regs =  (~Second) << 2;
#else
GPIOA.DMASK(-1)
.DMASK5(0)
.DMASK4(0)
.DMASK3(0)
.DMASK2(0);
GPIOA.DOUT = (~Second) << 2;
#endif

雁塔菜农<hotwc3@qq.com> 22:14:50
今天的课基本讲完了
batsong@21IC(6335473) 22:14:53
我晕,这个写法看不懂啊
雁塔菜农<hotwc3@qq.com> 22:14:58
有什么问题吗????
batsong@21IC(6335473) 22:15:20
GPIOA.DMASK(-1).DMASK5(0).DMASK4(0).DMASK3(0).DMASK2(0);

雁塔菜农<hotwc3@qq.com> 22:15:24
这是老师最最温柔的写法
难民人<lwslws201@qq.com> 22:15:29
不会 C++ 所以看不懂啊
batsong@21IC(6335473) 22:15:43
我学过c++,也没看懂
batsong@21IC(6335473) 22:15:45
。。。
雁塔菜农<hotwc3@qq.com> 22:15:52
-1=0xffffffff
雁塔菜农<hotwc3@qq.com> 22:16:04
GPIOA.DMASK(-1).DMASK5(0).DMASK4(0).DMASK3(0).DMASK2(0);

batsong@21IC(6335473) 22:16:36
怎么给每位赋值的
雁塔菜农<hotwc3@qq.com> 22:16:51
GPIOA.DMASK(-1)
先在缓冲内将DMASK全部置‘1’
雁塔菜农<hotwc3@qq.com> 22:17:30
DMASK5(0)
在缓冲内将DMASK.5清0
雁塔菜农<hotwc3@qq.com> 22:17:46
DMASK4(0)
在缓冲内将DMASK.4清0

雁塔菜农<hotwc3@qq.com> 22:17:55
DMASK3(0)
在缓冲内将DMASK.3清0

雁塔菜农<hotwc3@qq.com> 22:18:05
DMASK2(0)
在缓冲内将DMASK.2清0

batsong@21IC(6335473) 22:18:09
不是直接操作寄存器,是计算好再一次写入寄存器?
雁塔菜农<hotwc3@qq.com> 22:18:36
结果DMASK=0b11111111...111000011
雁塔菜农<hotwc3@qq.com> 22:18:45

雁塔菜农<hotwc3@qq.com> 22:19:06
故C++比C要好些
batsong@21IC(6335473) 22:19:40
中间用.连接? c++的哪个机制?
雁塔菜农<hotwc3@qq.com> 22:19:41
假若位域,就要写4条语句了
batsong@21IC(6335473) 22:19:59
我学过,没用过c++
雁塔菜农<hotwc3@qq.com> 22:20:01
这个要深入后就明白了
batsong@21IC(6335473) 22:20:19

雁塔菜农<hotwc3@qq.com> 22:20:21
开始俺也晕沉的
难民人<lwslws201@qq.com> 22:20:29

Jason(836795556) 22:20:37
m0516的ad参考电压在那里加上的?
(本消息由该成员通过手机QQ发送,体验手机QQ请登录: http://mobile.qq.com/c )  
雁塔菜农<hotwc3@qq.com> 22:20:40
后来琢磨了红杏和它的对比
雁塔菜农<hotwc3@qq.com> 22:20:57
用红杏来理解它,就不晕了
batsong@21IC(6335473) 22:21:21
红杏理解啊
雁塔菜农<hotwc3@qq.com> 22:21:36
课就讲到这里,谁做群课笔记???
雁塔菜农<hotwc3@qq.com> 22:21:48

雁塔菜农<hotwc3@qq.com> 22:22:00
红杏就是用C做的
雁塔菜农<hotwc3@qq.com> 22:22:18
结构,联合,位域和枚举
难民人<lwslws201@qq.com> 22:22:27
51小刚 我明天给他发
雁塔菜农<hotwc3@qq.com> 22:22:52
今天课不晕吧
John Lee<j.y.lee@yeah.net> 22:22:54
寄存器缓冲方式,用起来很easy,但要想弄清楚它的实现,就不很easy了。
batsong@21IC(6335473) 22:23:04
GPIOA.DMASK(-1).DMASK5(0).DMASK4(0).DMASK3(0).DMASK2(0);
雁塔菜农<hotwc3@qq.com> 22:23:07
哈哈

使用特权

评论回复
板凳
51小刚|  楼主 | 2011-7-23 09:00 | 只看该作者
第一次做笔记,做的不好,大家见谅哈!:P

使用特权

评论回复
地板
hotpower| | 2011-7-23 10:13 | 只看该作者
好,昨晚贴图少,主要是网速太慢了。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
51小刚 + 1
5
Swallow_0322| | 2011-7-23 10:52 | 只看该作者
:P来顶!

使用特权

评论回复
6
plc_avr| | 2011-7-23 13:11 | 只看该作者
哈哈,这下有人做笔记了,顶!

使用特权

评论回复
7
ttlasong| | 2011-7-23 16:05 | 只看该作者
:victory:

使用特权

评论回复
8
nayaix| | 2011-7-23 19:02 | 只看该作者
:)

使用特权

评论回复
9
lwslws201| | 2011-7-24 02:20 | 只看该作者
几日没得空,现在来顶下。:lol

使用特权

评论回复
10
batsong| | 2011-7-24 10:53 | 只看该作者
:lol:lol:lol

还得重新去翻翻c++的书,不然跟不上节奏

使用特权

评论回复
11
hotpower| | 2011-7-25 08:08 | 只看该作者
学过就好。复习很快的。

使用特权

评论回复
12
ichuangj| | 2011-7-28 16:22 | 只看该作者
啥时我也上上群课

使用特权

评论回复
13
缥缈九哥| | 2013-7-28 02:39 | 只看该作者
顶起。lambda的使用。关于m0的RTC操作

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

943

帖子

1

粉丝