电子钟实验报告 班 级 学号 实验名称 一、设计目标和要求:
1、理解rtc模块的结构,并掌握rtc的配置和读写操作。 2、学习使用UC GUI。
3、对无操作系统的应用,设计任务的切换和协调运行。 4、完成考核要求:
①驱动RTC模块,设置和读取RTC时间(在液晶上用文字显示当前时间,年月日、星期几、时分秒)。
②添加液晶绘图函数,在液晶上绘制电子表表盘。
③设计任务,添加ucos2操作系统。添加任务1(时间设置、报警闹钟设置和绘图参数)和任务2(绘制表盘),并协调2个任务。
④通过UC GUI丰富图形界面(添加GUI任务,添加对应任务的图像窗口)。 二、实验环境:
硬件:嵌入式开发平台、JTAG仿真器、PC机、嵌入式系统实验箱,串口线。 软件: WinXP、RVDS集成开发环境、仿真器驱动程序、超级终端通讯程序。 三、设计思路和实现步骤、内容: 1、设计思路:
(1)用函数画出一个时钟表盘,写出实时的时间。
首先,定义边角点坐标,确定屏幕范围;接着,用清屏函数清屏;然后,用ILI93××程序画图,定义一点作为中心坐标,画一个确定半径的为R的圆;最后画三条直线,分别为秒针、分针、时针(都是使用坐标来确定的)。
(2)实现对时间的更改功能,并可以将更改过的时间赋值给现实的时间。
STM32中RTC模块计数器,秒针每次+1,每次+1后,秒针指向下一个刻度的时候,上一个刻度的位置用清屏函数清掉,然后重新画好指针;
(3)用时钟来控制一个闹钟时间,中断后让液晶做出相应的反应。
电子班 ******* 姓名 电子钟 ** 在源程序中加入UCOS2操作系统,在系统中进行时间设置,报警和闹钟等等功能。 2、程序流程图:
3、具体实现程序: 1、主程序 int main(void) {
KEY_Init();
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72);
//延时初始化
uart_init(72,9600); //串口1初始化 LED_Init(); LCD_Init(); RTC_Init();
EXTIX_Init();
DrawClock();
while(1) {
if(alarmflag==1)//闹钟标志
Alarm(); //闹钟显示
else
Timeshow(); //时间显示 if(set==1) //设置时间标志 {
LCD_Clear(WHITE);
Set_timeshow(); //设置时间 }
} }
时钟、led、lcd、rtc初始化后,进入一个死循环,如果没有进入闹钟中断,就开始时钟显示,按下第一个使能按键后,进入第二个界面,开始时间更改,然后再返回更改值。如果进入中断了,开始做出闹钟的动作。
2、表盘的制作 void DrawClock() {
POINT_COLOR=MAGENTA;//设置表盘为紫色 Draw_Circle(120,130,100); Draw_Circle(120,130,78);
POINT_COLOR=BLACK;//设置文字为黑色 LCD_ShowString(90,5,\"CLOCK\");
POINT_COLOR=BROWN;//设置表盘文字为棕色 LCD_ShowNum(115,32,12,2,16); LCD_ShowNum(163,47,1,1,16); LCD_ShowNum(193,80,2,1,16); LCD_ShowNum(204,123,3,1,16);
LCD_ShowNum(193,166,4,1,16); LCD_ShowNum(163,199,5,1,16); LCD_ShowNum(119,214,6,1,16); LCD_ShowNum(69,199,7,1,16); LCD_ShowNum(39,166,8,1,16); LCD_ShowNum(28,123,9,1,16); LCD_ShowNum(35,80,10,2,16); LCD_ShowNum(69,45,11,2,16);
POINT_COLOR=BLACK;//设置表盘刻度为黑色 LCD_DrawLine(122,52,122,60); //12 LCD_DrawLine(155,69.4,159,62.5); //1 LCD_DrawLine(180.6,95,187.6,91); //2 LCD_DrawLine(190,131,198,131);//3 LCD_DrawLine(180.6,165,187.6,169);//4 LCD_DrawLine(155,190.6,159,197.6);//5 LCD_DrawLine(122,200,122,208);//6 LCD_DrawLine(85,190.6,81,197.6);//7 LCD_DrawLine(59.4,165,52.5,169);//8 LCD_DrawLine(42,131,50,131); //9 LCD_DrawLine(59.4,95,52.5,91);//10 LCD_DrawLine(85,69.4,81,62.5);//11 //显示时间
POINT_COLOR=BLUE;//设置字体为蓝色
#include 先画出表盘、刻度、刻度上的文字(用函数画出,其坐标用软件算出来)。再写出用数字表示的时间
LCD_DrawRectangle(71,238,163,300); LCD_ShowString(80,240,\" - - \"); LCD_ShowString(80,280,\" : : \");
3、时钟的显示程序 void Timeshow() {
u8 pd;
LCD_ShowNum(120,240,timer.w_month,2,16);
LCD_ShowNum(144,240,timer.w_date,2,16); switch(timer.week) {
case 0:
LCD_ShowString(85,260,\"Sunday \"); break;
POINT_COLOR=BLUE;
LCD_ShowNum(80,240,timer.w_year,4,16);
case 1:
LCD_ShowString(85,260,\"Monday \"); break;
case 2:
LCD_ShowString(85,260,\"Tuesday \"); break;
case 3:
LCD_ShowString(85,260,\"Wednesday\"); break;
case 4:
LCD_ShowString(85,260,\"Thursday \"); break;
case 5:
LCD_ShowString(85,260,\"Friday \"); break;
}
case 6:
LCD_ShowString(85,260,\"Saturday \"); break;
LCD_ShowNum(80,282,timer.hour,2,16);
LCD_ShowNum(104,282,timer.min,2,16);
LCD_ShowNum(128,282,timer.sec,2,16); Sx=120-c1[59-timer.sec]; Sy=130+s1[59-timer.sec]; Mx=120-c2[59-timer.min]; My=130+s2[59-timer.min]; if(timer.hour>=12) { } else { }
if(Sxp!=Sx) POINT_COLOR=WHITE,
LCD_DrawLine(120,130,Sxp,Syp),//秒针
Hx=120-c3[11-timer.hour]; Hy=130+s3[11-timer.hour]; pd=timer.hour-12; Hx=120-c3[11-pd]; Hy=130+s3[11-pd];
LCD_DrawLine(120,130,Mxp,Myp),//分针
LCD_DrawLine(120,130,Hxp,Hyp);//时针 POINT_COLOR=GRAY;//分针为灰色
}
LCD_DrawLine(120,130,Sx,Sy);//秒针 POINT_COLOR=RED;//分针为红色 LCD_DrawLine(120,130,Mx,My);//分针 POINT_COLOR=GREEN; //时针为绿色 LCD_DrawLine(120,130,Hx,Hy); //时针 Sxp=Sx,Syp=Sy,Mxp=Mx,Myp=My,Hxp=Hx,Hyp=Hy;
算出此时的星期,下一秒时应该做出什么动作(秒针向前动一个单位,分针时针是否移动)
4、闹钟显示模块 void Alarm() { }
一旦时间到了,中断开始,开始进行闹钟动作,即白屏,然后出现\"TIME OUT!\"的字样,延迟一段时间,返回时钟界面。
5、时间设置界面 void Set_timeshow() { u16 ye=timer.w_year; u8 mo=timer.w_month,
da=timer.w_date, ho=timer.hour, mi=timer.min; LCD_Clear(WHITE); POINT_COLOR=RED;
LCD_ShowString(85,160,\"TIME OUT! \");
delay_ms(9000); alarmflag=0; LCD_Clear(WHITE); DrawClock();
mode=0; //设置哪一个位
while(set==1) {
POINT_COLOR=BLUE;
LCD_ShowString(100,140,\" - - \");
LCD_ShowString(100,180,\" : : \");
LCD_ShowNum(100,140,ye,4,16); LCD_ShowNum(140,140,mo,2,16); LCD_ShowNum(1,140,da,2,16); LCD_ShowNum(100,180,ho,2,16); LCD_ShowNum(124,180,mi,2,16); LCD_ShowNum(148,180,0,2,16); delay_ms(300);
if(mode==0)
{
if(data==1) ye=ye+1; if(data==2) ye=ye-1;
data=0;
POINT_COLOR=WHITE;
LCD_ShowNum(100,140,ye,4,16); }
else if(mode==1) {
if(data==1) mo=mo+1; if(data==2) mo=mo-1; data=0;
POINT_COLOR=WHITE;
delay_ms(300);
LCD_ShowNum(140,140,mo,2,16);
delay_ms(300);
}
else if(mode==2) {
if(data==1) da=da+1; if(data==2) da=da-1;
data=0;
POINT_COLOR=WHITE;
LCD_ShowNum(1,140,da,2,16);
delay_ms(300);
}
else if(mode==3) {
if(data==1) ho=ho+1; if(data==2) ho=ho-1;
data=0;
POINT_COLOR=WHITE;
LCD_ShowNum(100,180,ho,2,16);
delay_ms(300);
}
else if(mode==4) {
if(data==1) mi=mi+1; if(data==2) mi=mi-1; data=0;
POINT_COLOR=WHITE;
LCD_ShowNum(124,180,mi,2,16); }
delay_ms(300);
else
set=0,mode=0;
}
RTC_Set(ye,mo,da,ho,mi,0);
LCD_Clear(WHITE); DrawClock(); }
第一个键按一下,开始进入时间设置界面,继续按设置的位置向前移动,第二三个键负责对数值加减,设置完成会返回到数值更新的时钟界面
6一些中断的函数 1)闹钟的中断
void RTC_IRQHandler(void) {
if(RTC->CRL&0x0001)//秒钟中断 {
RTC_Get();//更新时间 //printf(\"CRL:%d\\n\
}
if(RTC->CRL&0x0002)//闹钟中断 {
alarmflag=1;
RTC->CRL&=~(0x0002);//清闹钟中断
//闹钟处理
}
RTC->CRL&=0X0FFA; //清除溢出,秒钟中断标志 }
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
用时钟的定时来实现闹钟功能,可以自己规定什么时候开始时钟中断
2)第一个按键的中断
void EXTI0_IRQHandler(void) {
delay_ms(50); if(set==0) set=1; }
第一次按第一个键,进入时钟设置,再次按设置的位置移动
3)第二三个按键
void EXTI15_10_IRQHandler(void) { }
对需要设置的数值进行加减1
else
mode=mode+1;
EXTI->PR=1<<0; //清除LINE0上的中断标志位
delay_ms(50); //消抖 if(KEY0==0) //按键0 {
data=data+1;
}else if(KEY1==0)//按键1 { }
EXTI->PR=1<<13; //清除LINE13上的中断标志位 EXTI->PR=1<<15; //清除LINE15上的中断标志位
data=data+2;
四、实验总结
学习嵌入式系统的时间并不长,而且又是第一次接触,因此有很多东西还是不太了解, 虽然说时间不长,但是还是很有收获的,这次毕竟使自己有机会去学习一些贴近硬件的知识。 在这次实验中,让我对课堂上的理论知识有了更深一层的理解,在实践中发现问题,从而解决问题的过程,让我最是获益匪浅。说真的,刚开始拿到实验要求时,一头雾水,但是在多次和同学的交流学习以及反复摸索实验的过程中,自己有了点思路,不懂就问。此刻不得不感谢老师同学的帮助,没有你们的耐心地解决我心中困惑,就不会有此时实验的成功。