嵌入式实训24.docx
《嵌入式实训24.docx》由会员分享,可在线阅读,更多相关《嵌入式实训24.docx(19页珍藏版)》请在冰豆网上搜索。
嵌入式实训24
嵌入式实训24——维信科技
一、实训目的
学习系统时间相关API函数和使用信号量解决uCOS-II任务之间的互斥问题,把系统时间显示在一个文本框中,并可以通过键盘设置修改。
二、实训内容(维信科技,太原最好的IT培训)
本次实验在用户的Main_Task任务中创建一个新任务,来实现系统时钟的显示和更新。
同时,通过在Main_Task任务中响应键盘消息,可以对系统的时钟进行更改。
使用uCOS-II多任务系统中的信号量保证多个任务对系统的同一个控件访问而不产生冲突。
三、预备知识
1、用ARMSDT2.5或ADS1.2集成开发环境,编写和调试程序的基本过程。
2、基于uCOS-II操作系统应用程序的框架结构。
3、会使用消息循环响应键盘消息。
4、会使用文本框控件。
四、设备及工具(包括软件调试工具)
硬件:
ARM嵌入式开发平台、用于ARM7TDMI的JTAG仿真器、PC机Pentium100以上。
软件:
PC机操作系统win98、Win2000或WinXP、ARMSDT2.51或ADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序、UltraEdit。
五、原理及说明
当系统掉电后RTC(RealTimeClock)电路可以依靠后备电池工作。
RTC电路能够以BCD码的形式向CPU提供时间信息,这些信息包括年、月、日、星期和时、分、秒。
RTC的运行依赖于一个外部32.768KHz晶振,并具有闹钟功能。
该RTC电路还具有闰年发生器、闹钟中断或掉电唤醒、解决Y2K问题、独立电源引脚、秒钟舍入复位功能、用于RTOS核的毫秒级时钟节拍中断等特性。
1、RTC电路单元说明
RTC电路的框图如图4-9所示。
1)闰年发生器
该模块可以根据BCDDAY、BCDMON、BCDYEAR等寄存器的数据决定每个月的最后一天是28、29、30还是31,在决定最后日期时考虑了闰年。
因为8位计数器只能保存两位BCD码,所以无法判断00年是闰年与否。
例如无法区分1900年和2000年。
为此,44B0的RTC单元用硬件来支持闰年2000年,注意这里1900不是闰年而2000年是闰年。
因而00年代表2000年而非1900年。
图4-9RTC电路图框图
需要注意,RTC的合法时间范围是100年,比如1901-2000或2000-2099,也可以是1949-2048等。
否则程序中无法判断某一年是哪个世纪的,由于00年应该认为是2000年,这个范围在实际应用中已经足够了。
2)读写寄存器
RTCCON寄存器的Bit0位必须置1后才能读写RTC单元的寄存器。
为了显示秒、分、时、星期、日期、月和年,CPU应该分别读取BCDSEC、BCDMIN、BCDHOUR、BCDDAY、BCDDATE、BCDMON、BCDYEAR等寄存器的内容。
然而,由于读多个寄存器,一秒的偏差是可能存在的。
例如,用户从BCDYEAR到BCDMIN读取寄存器(维信科技,太原最好的IT培训),结果正好为59年12月31日23时59分;当用户读取BCDSEC寄存器并且结果在1到59秒时,这没有问题,但是当结果为0秒时,由于上述的一秒偏差,年、月、日、时和分可能已经变为60年1月1日0时0分了。
在这种情况下,如果BCDSEC为0的话,用户应该从BCDYEAY到BCDMIN重新读取。
3)闹钟功能
RTC可以在掉电模式或正常工作模式中在指定时刻产生闹钟信号;在正常工作模式下闹钟中断ALMINT被激活,而在掉电模式下,电源管理唤醒PMWKUP信号与ALMINT同时被激活。
RTC闹钟寄存器RTCALM决定闹钟的使能和时刻设置。
4)时钟节拍中断
RTC的时钟节拍用于中断请求,TICNT寄存器包含中断使能位和用于中断的计数值,当计数值减少到0则产生时钟节拍中断。
那么中断周期就是:
Period=(n+1)/128second其中n:
Ticktimecountvalue(1-127)
RTC的时钟节拍可以用于RTOS(实时操作系统)内核的时钟节拍。
如果时钟节拍由RTC产生,RTOS的时间相关功能将一直与实时钟同步。
5)舍入复位功能
舍入复位功能由RTC的舍入复位寄存器RTCRST完成,秒进位发生器的舍入边界(30、40或50秒)是可选的,在舍入复位时秒值被舍入为0。
例如当前时间是23:
37:
47,(维信科技,太原最好的IT培训)并且舍入边界选择为40秒,那么舍入复位将当前时间改为23:
38:
00。
2、RTC相关寄存器
实时时钟控制寄存器(RTCCON)的设置和位描述如下表4-21和表4-22所示:
表4-21实时时钟控制寄存器(RTCCON)的设置
寄存器
地址
R/W
描述
复位值
RTCCON
0x01D70040(L)
0x01D70043(B)
R/W
(bybyte)
RTC控制寄存器
0x0
表4-22实时时钟控制寄存器(RTCCON)的位描述
RTCCON
位
描述
初始化状态
CLKRST
[3]
RTC时钟计数复位
0=无复位,1=复位
0
CNTSEL
[2]
BCD计数选择
0=合并BCD计数器
1=保留(分离BCD计数器)
0
CLKSEL
[1]
BCD时钟选择
0=晶振XTAL1/215分频时钟
1=保留(XTAL时钟只为检测)
0
RTCEN
[0]
RTC读/写使能
0=禁止,1=使能
如果RTC读/写特征使能,静态电流将大量消耗。
为了减少STOP电流,在不访问RTC时该位应该为0。
即使该位为0,RTC时钟仍然运行。
0
RTC闹钟控制寄存器(RTCALM)的设置和位描述如下表4-23和表4-24所示:
表4-23RTC闹钟控制寄存器(RTCALM)的设置
寄存器
地址
R/W
描述
复位值
RTCALM
0x01D70050(L)
0x01D70053(B)
R/W
(bybyte)
RTC闹钟控制寄存器
0x00
表4-24RTC闹钟控制寄存器(RTCALM)的位描述
RTCALM
位
描述
初始化状态
Reserved
[7]
0
ALMEN
[6]
闹钟全局使能
0=禁止,1=使能
0
YEAREN
[5]
年闹钟使能
0=禁止,1=使能
0
MONREN
[4]
月闹钟使能
0=禁止,1=使能
0
DAYEN
[3]
天闹钟使能
0=禁止,1=使能
0
HOUREN
[2]
小时闹钟使能
0=禁止,1=使能
0
MINEN
[1]
分钟闹钟使能
0=禁止,1=使能
0
SECEN
[0]
秒闹钟使能
0=禁止,1=使能
0
闹钟第二数据寄存器(ALMSEC)的设置和位描述如表4-25和表4-26所示:
表4-25闹钟第二数据寄存器(ALMSEC)的设置
寄存器
地址
R/W
描述
复位值
ALMSEC
0x01D70054(L)
0x01D70057(B)
R/W
(bybyte)
闹钟第二数据寄存器
0x00
表4-26闹钟第二数据寄存器(ALMSEC)的位描述
ALMSEC
位
描述
初始化状态
Reserved
[7]
0
SECDATA
[6:
4]
闹钟秒的BCD值,从0-5。
000
[3:
0]
0到9
0000
闹钟分钟数据寄存器(ALMMIN)的设置和位描述如下表4-27和表4-28所示:
表4-27闹钟分钟数据寄存器(ALMMIN)的设置
寄存器
地址
R/W
描述
复位值
ALMMIN
0x01D70058(L)
0x01D7005B(B)
R/W
(bybyte)
闹钟分钟数据寄存器
0x00
表4-28闹钟分钟数据寄存器(ALMMIN)的位描述
ALMMIN
位
描述
初始化状态
Reserved
[7]
0
MINDATA
[6:
4]
闹钟分钟的BCD值,从0到5。
000
[3:
0]
0到9
0000
闹钟小时数据寄存器(ALMHOUR)的设置和位描述如下表4-29和表4-30所示:
表4-29闹钟小时数据寄存器(ALMHOUR)的设置
寄存器
地址
R/W
描述
复位值
ALMHOUR
0x01D7005C(L)
0x01D7005F(B)
R/W
(bybyte)
闹钟时间数据寄存器
0x00
表4-30闹钟小时数据寄存器(ALMHOUR)的位描述
ALMHOUR
位
描述
初始化状态
Reserved
[7:
6]
0
HOURDATA
[5:
4]
闹钟时间的BCD值,从0到2。
00
[3:
0]
0到9
0000
闹钟天数据寄存器(ALMDAY)的设置和位描述如下表4-31和表4-32所示:
表4-31闹钟天数据寄存器(ALMDAY)的设置
寄存器
地址
R/W
描述
复位值
ALMDAY
0x01D70060(L)
0x01D70063(B)
R/W
(bybyte)
闹钟天数据寄存器
0x01
表4-32闹钟天数据寄存器(ALMDAY)的位描述
ALMDAY
位
描述
初始化状态
Reserved
[7:
6]
0
DAYDATA
[5:
4]
闹钟天的BCD值,从0到28,29,30,31
0到3
00
[3:
0]
0到9
0001
闹钟月数据寄存器(ALMMON)的设置和位描述如下表4-33和表4-34所示:
表4-33闹钟月数据寄存器(ALMMON)的设置
寄存器
地址
R/W
描述
复位值
ALMMON
0x01D70064(L)
0x01D70067(B)
R/W
(bybyte)
闹钟月数据寄存器
0x01
表4-34闹钟月数据寄存器(ALMMON)的位设置
ALMMON
位
描述
初始化状态
Reserved
[7:
5]
0
MONDATA
[4]
闹钟月的BCD值,从0到1。
0
[3:
0]
0到9
0001
闹钟年数据寄存器(ALMYEAR)的设置和位描述如下表4-35和表4-36所示:
表4-35闹钟年数据寄存器(ALMYEAR)的设置
寄存器
地址
R/W
描述
复位值
ALMYEAR
0x01D70068(L)
0x01D7006B(B)
R/W
(bybyte)
闹钟年数据寄存器
0x00
表4-36闹钟年数据寄存器(ALMYEAR)的设置的位描述
ALMYEAR
位
描述
初始化状态
YEARDATA
[7:
0]
年的BCD值,从00-99
0x00
RTC复位寄存器(RTCRST)的设置和位描述如下表4-37和表4-38所示:
表4-37RTC复位寄存器(RTCRST)的设置
寄存器
地址
R/W
描述
复位值
RTCRST
0x01D7006C(L)
0x01D7006F(B)
R/W
(bybyte)
RTC舍入复位寄存器
0x0.
表4-38RTC复位寄存器(RTCRST)的位描述
RTCRST
位
描述
初始化状态
SRSTEN
[3]
舍入秒复位使能
0=禁止,1=使能
0
SECCR
[2:
0]
秒进位产生的舍入边界
011=超出30秒
100=超出40秒
101=超出50秒
00
BCD秒寄存器(BCDSEC)的设置和位描述如下表4-39和4-40所示:
表4-39BCD秒寄存器(BCDSEC)的设置
寄存器
地址
R/W
描述
复位值
BCDSEC
0x01D70070(L)0x01D70073(B)
R/W
(bybyte)
BCD秒寄存器
Undef.
表4-40BCD秒寄存器(BCDSEC)的位描述
BCDSEC
位
描述
初始化状态
Reserved
[7]
–
SECDATA
[6:
4]
秒的BCD值从0到5
–
[3:
0]
0到9
–
BCD分钟寄存器(BCDMIN)的设置和位描述如下表4-41和表4-42所示:
表4-41BCD分钟寄存器(BCDMIN)的设置
寄存器
地址
R/W
描述
复位值
BCDMIN
0x01D70074(L)0x01D70077(B)
R/W
(bybyte)
BCD分钟寄存器
Undef.
表4-42BCD分钟寄存器(BCDMIN)的位设置
BCDMIN
位
描述
初始化状态
Reserved
[7]
–
MINDATA
[6:
4]
分钟的BCD值从0到5
–
[3:
0]
0到9
–
BCD小时寄存器(BCDHOUR)的设置和位描述如下表4-43和表4-44所示:
表4-43BCD小时寄存器(BCDHOUR)的设置
寄存器
地址
R/W
描述
复位值
BCDHOUR
0x01D70078(L)
0x01D7007B(B)
R/W
(bybyte)
BCD小时寄存器
Undef.
表4-44BCD小时寄存器(BCDHOUR)的位描述
BCDHOUR
位
描述
初始化状态
Reserved
[7:
6]
–
HOURDATA
[5:
4]
小时的BCD值从0到2
–
[3:
0]
0到9
–
BCD天数寄存器(BCDDAY)的设置和位描述如下表4-45和表4-46所示:
表4-45BCD天数寄存器(BCDDAY)的设置
寄存器
地址
R/W
描述
复位值
BCDDAY
0x01D7007C(L)0x01D7007F(B)
R/W
(bybyte)
BCD天数寄存器
Undef
表4-46BCD天数寄存器(BCDDAY)的位描述
BCDDAY
位
描述
初始化状态
Reserved
[7:
6]
–
DAYDATA
[5:
4]
天数的BCD值从0到3
–
[3:
0]
0到9
–
BCD日期寄存器(BCDDATE)的设置和位描述如下表4-47和表4-48所示:
表4-47BCD日期寄存器(BCDDATE)的设置
寄存器
地址
R/W
描述
复位值
BCDDATE
0x01D70080(L)
0x01D70083(B)
R/W
(bybyte)
BCD日期寄存器
Undef.
表4-48BCD日期寄存器(BCDDATE)的位描述
BCDDATE
位
描述
初始化状态
Reserved
[7:
3]
–
DATEDATA
[2:
0]
日期的BCD值从1到7
–
BCD月寄存器(BCDMON)的设置和位描述如下表4-49和表4-50所示:
表4-49BCD月寄存器(BCDMON)的设置
寄存器
地址
R/W
描述
复位值
BCDMON
0x01D70084(L)0x01D70087(B)
R/W
(bybyte)
BCD月寄存器
Undef.
表4-50BCD月寄存器(BCDMON)的位描述
BCDMON
位
描述
初始化状态
Reserved
[7:
5]
–
MONDATA
[4]
月的BCD值从0到1
–
[3:
0]
0到9
–
BCD年寄存器(BCDYEAR)的设置和位描述如表4-51和4-52所示:
表4-51BCD年寄存器(BCDYEAR)的设置
寄存器
地址
R/W
描述
复位值
BCDYEAR
0x01D70088(L)0x01D7008B(B)
R/W
(bybyte)
BCD年寄存器
Undef.
表4-52BCD年寄存器(BCDYEAR)的位描述
BCDYEAR
位
描述
初始化状态
YEARDATA
[7:
0]
年的BCD值从00到99
–
3)系统时间相关的API函数
和系统时间相关的API函数请参考附录,在RTC.H中定义。
程序中定义了如下结构:
typedefstruct{
U32year;
U32month;
U32day;
U32date;
U32hour;
U32minute;
U32second;
}structTime,*PstructTime
typedefstruct{
U32year;
U32month;
U32day;
}structDate,*PstructDate
typedefstruct{
U32hour;
U32minute;
U32second;
}structClock,*PstructClock
InitRtc()函数用来初始化RTC,Get_Rtc()和Set_Rtc()函数分别用来获取、设置当前完整的时间信息。
还有Set_Rtc_Clock()和Set_Rtc_Date()函数可以分别设置时间、日期(维信科技,太原最好的IT培训)。
在程序中可以用Rtc_IsTimeChange()函数来判断某一个时间单位是否改变,据此决定是否读取时间。
在图形模式下可以用Rtc_Format()函数来获得包含时间信息的指定格式的Unicode编码字符串。
六、实训步骤
1、新建工程,将“Exp19多任务和系统时钟”中的源文件加入到该工程。
2、打开Main.c文件,编辑Main_Task任务中的代码,创建一个时间显示文本框。
在Main_Task任务中再创建一个新任务Rtc_Disp_Task,此任务负责更新显示系统时间。
定义一个信号量Rtc_Updata_Sem,保证系统中多个任务访问或更新时间文本框时不发生冲突。
3、在Main_Task任务中启动消息循环,使用户可以通过键盘在文本框中编辑系统时间。
Main_Task任务具体的程序流程图如图4-10所示:
图4-10Main_Task任务流程图
提示:
1)需要编写CreateText()函数完成时间显示文本框的创建,并在Main_Task中调用该函数。
编辑CreateText()函数内容:
定义键码表TimeKeyTable[],用CreateTextCtrl()函数创建文本框,然后用SetWndCtrlFocus()函数将焦点转移到该文本框,并用DrawTextCtrl()函数重画。
注意,CreateTextCtrl()函数可以根据用户指定的键码表来完成键盘任务发出的键码到要显示字符的转换,由于本实验需要显示“:
”,并指定键盘的“.”键用来输入“:
”,所以需要另行定义键码表,并将TimeKeyTable作为参数传给CreateTextCtrl()(维信科技,太原最好的IT培训)。
如果使用默认键码表,对应参数赋0即可。
2)信号量是uCOS-II任务之间的通信和同步机制之一,由信号量的计数值、等待该信号量的任务构成的等待任务表两部分构成。
首先要调用OSSemCreate()函数建立信号量,对信号量的初始计数值赋值。
因为这里信号量是用于对共享资源的访问,其初值应该设为1。
使用OSSemPend()函数等待信号量,如果信号量当前是可用的(信号量计数值大于0),该函数将信号量的计数值减1,并返回“无错”的错误代码。
如果信号量的计数值为0,则调用OSSemPend()函数的任务要进入休眠状态,等待其他任务释放该信号量。
OSSemPend()函数允许用户定义一个最长等待时间作为它的参数,这样可以避免该任务无休止的等待。
如果该参数非0,则该任务一直等到信号量有效或超时;否则将一直等待下去。
使用OSSemPost()函数发送一个信号量,它会检查是否有任务在等待该信号量。
如果该信号量的等待任务列表非空,就将最高优先级的任务从等待任务列表中删除并使它进入就绪状态;然后调用任务调度函数检查该任务是否是系统中最高优先级的就绪任务,(维信科技,太原最好的IT培训)如果是则进行任务切换,否则调用OSSemPost()的任务继续执行。
如果没有任务在等待该信号量,则其计数值就简单的加1。
3)uCOS-II系统中创建新任务的方法和注意事项请参考前边“uCOS-II移植实验”。
4)uCOS-II系统消息循环的应用请参考前边相关实验,以后的实验中将继续学习。
4、编辑时钟更新任务Rtc_Disp_Task的代码。
此任务具体的程序流程如图4-11所示:
图4-11时钟更新任务流程图
5、编辑键码处理函数onKey(),处理回车键和取消键。
有回车键按下后,如果文本框不是编辑状态则等待信号量并使文本框进入编辑状态;如果正处于编辑状态,则结束编辑并调用SetSysTime()函数设置时间(维信科技,太原最好的IT培训),设置成功则发送信号量,否则显示错误信息。
提示:
1)需要编写SetSysTime()函数,由pTextCtrl->text得到文本框的ASCII字符串,并从该字符串中获得从键盘输入的时间信息,然后赋给structClock类型的结构体,对时间值作有效性判断后调用Set_Rtc_Clock()函数设置RTC。
2)通过SetTextCtrlEdit()函数设置文本框是否处于编辑状态,用SetTextCtrlText()函数设置文本框中的内容。
用Rtc_Format()函数可以获得指定格式的Unicode编码的时间字符串,以方便在图形控件中显示。
比如Rtc_Format("%H:
%I:
%S",strtime)将获得类似于“xx:
xx:
xx”的字符串并保存在strtime中,其中xx表示实际时间值。
3)使用Rtc_IsTimeChange(RTC_SECOND_CHANGE)