嵌入式课程设计 编程闹钟 广西大学.docx
《嵌入式课程设计 编程闹钟 广西大学.docx》由会员分享,可在线阅读,更多相关《嵌入式课程设计 编程闹钟 广西大学.docx(14页珍藏版)》请在冰豆网上搜索。
嵌入式课程设计编程闹钟广西大学
可编程电子闹钟
一、设计总原理
系统结构框图如下:
本设计采用ILI9341触摸屏作为基础,将程序写入STM32中,通过电阻触摸屏上不同的坐标来使用不同的功能。
再将辅助用的美化图片通过Image2Lcd根据不同的分辨率生成代码放入Fonts.c中;Rcc.c作为系统时间控制三种功能的时间;EXTI.c实现外部中断即当闹钟时间到时中断RTC;用LCD.c记录一些文字,指针位置和颜色的变化及必要的设置。
总体来说就是STM32中的程序和触摸屏完成设计。
二、系统各单元模块设计
一、时钟和时钟设置
时钟采用RTC和RCC两部分组成,其中RCC是系统时钟,系统所有功能的时间都是RCC系统时钟。
STM32的实时时钟(RTC)是一个独立的定时器。
RTC模块拥有一组连续计数的计数器,可提供时钟日历的功能。
修改计数器的值可以重新设置系统当前的时间和日期。
根据不同触摸点的位置(坐标)确定修改的年月日时分秒。
二、闹钟部分
闹钟程序分为逻辑部分和显示部分。
逻辑部分是通过对RCC时间的读取来进行不断的更新闹钟时间进而判断该闹钟的发生与否,当有时分的闹钟设定后会去先更新数组进行记录,接着是对有效闹钟的查询来确定最近的报警时间作为闹钟值。
再将星期几和是否重复更新到闹钟数组,再一次进行查询和确定报警时间的操作。
设置多组闹钟就是循环上述总体过程。
显示部分就是一些清屏和汉字位置的程序。
三、LCD及触摸屏
此次设计采用的是电阻屏ILI9341液晶触摸屏。
整个程序是基于触摸屏上不同的坐标来写的,触摸屏的分辨率是240*320。
LCD主要用来设定一些固定的参数比如范围,还有字符和字符背景颜色等常规设置。
加入了对时钟部分指针显示的指针部分的角度消除等一些问题。
四、程序图片处理
首先确认实用的该图片的分辨率应该是多少,这一点非常重要,否则在LCD上就是图片乱码。
确认之后将图片先修改成规定的分辨率,再根据Image2Lcd软件得到相应的程序代码,添加到Fonts.c中。
三、软件设计流程图
五、结论与感想
这次课设我选择的题目是可编程电子闹钟,一开始觉得这个题目挺容易的,认为它类似于VB这种可视化编程,但是可随着设计的深入,越发的感到力不从心。
还好最终经过大量的查阅资料完成了题目的要求。
既是对自己专业知识的实践补充,也是一次对ARM开发板的全新认识。
首先是对课设的前期准备不充分,首先针对课设要求进行逐条分析。
此题目要求显示实时时间,这个要求可以用RTC和RCC(系统时间)来完成。
它所有的操作都要基于面板,也就是触摸屏操作。
所以对触摸屏必须有一个清醒的认识,触摸屏的型号是ILI9341,分辨率是240*320(这个尤为重要),它设置开始点必须设置结束点和其他型号在这点上有重大区分。
这些是必须在写程序之前都要得到的准确参数,但是由于第一次接触这种开发板,刚开始一头雾水,什么图片放进去都是乱码,文字也是横的。
下一次再设计时这些就成为了宝贵的经验。
其次是对于程序的书写和理解还有很多的问题。
此次题目的重点是写一个闹钟程序,个人认为首先要搞懂程序的逻辑,闹钟是以7天为一个循环,程序什么时候确认它停是一个很关键的问题。
开发板提供的光盘上有一个综合程序,里面有包含闹钟的一部分程序,有一定的参考价值。
但是由于对程序认识的浅薄,看了几天都没有得出它的完整逻辑。
随后去图书馆查看STM32和ARM的有关书籍才逐渐懂得一些,并且了解到一些程序的书写格式。
这些知识相信在我以后的设计中会非常受用的。
最后我想对此次课设做一个总结,ARM开发板是一款非常实用的学习STM32的开发板。
运用液晶屏上的坐标加上不同的程序可以设计许多的应用,不单单是闹钟一种。
通过这次课程设计也让我体会到51单片机和STM32的许多不同之处,相比于51,STM32确实有一些实用的改进。
当我再一次拿到题目时可以考虑的做法也不仅仅局限于51一种,对我明年的毕业设计也是一种很大帮助。
附件:
闹钟程序(逻辑部分)
//显示主界面
voidDisplay_Allarm_Main(void)
{
u8i=0;
LCD_Clear_Display(Vertical_LCD,BLACK);//清屏
LCD_Display_Window(Vertical_LCD,0,0,240,29,DARKGREEN);
LCD_Display_Num_Chinese_Char_Number_16_16(Vertical_LCD,10,6,"创建闹钟",4,":
",NO_Number,WHITE,RED,Fill_OFF);
LCD_Display_Window(Vertical_LCD,195,14,18,2,WHITE);
LCD_Display_Window(Vertical_LCD,203,6,2,18,WHITE);
LCD_Display_Window(Vertical_LCD,0,29,240,2,BLUE);
for(i=1;i<=Display_Allarm_Num;i++)
{
Display_Allarm_Interface(i);
}
}
voidAdd_Allarm(void)
{
u8i=0;
Interface_Type=Add_Allarm_Type;
Display_Set_Allarm_Interface();//添加闹钟界面
if(Success_Set==1)//表示成功添加
{
Set_Allarm_Hour=Set_Allarm_Hour_Temp;
Set_Allarm_Min=Set_Allarm_Min_Temp;
//把当前设置的一周中星期几闹铃的值更新到数组中去
for(i=0;i<7;i++)
{
Set_Allarm_Week[i]=Set_Allarm_Week_Temp[i];
}
Set_Allarm_Loop=Set_Allarm_Loop_Temp;
Display_Allarm_Num++;//显示的闹钟数量增加一个
All_Allarm_Hour[Display_Allarm_Num-1]=Set_Allarm_Hour;//把当前设置的闹钟的小时值更新到所有闹钟时间的数组中对应位置
All_Allarm_Min[Display_Allarm_Num-1]=Set_Allarm_Min;//把当前设置的闹钟的分值更新到所有闹钟时间分钟的数组中对应位置
//把当前设置的一周中星期几闹铃的值更新到数组中去
for(i=0;i<7;i++)
{
All_Allarm_Week[Display_Allarm_Num-1][i]=Set_Allarm_Week[i];
}
//更新当前设置的闹钟的重复与否参数写入数组中
All_Allarm_Loop[Display_Allarm_Num-1]=Set_Allarm_Loop;
//由于成功添加了闹钟之后默认这个闹钟是打开的,因此需要更新所有闹钟状态的数组值,针对那种不重复的数组如果全部都闹过了以后自动将这个闹钟关闭了,再次开启这个闹钟又会开始闹铃
//当然在打开设置里面打开了的话就会将每天的已经闹过闹铃数组清0
All_Allarm_STA[Display_Allarm_Num-1]=1;
//针对有效的闹钟进行查询,当天最接近报警时间的值,作为准备闹铃的时间
Find_Nearest_Time_Allarm();
////更新主界面
//Display_Allarm_Main();
Success_Set=0;
}
//else//表示没有成功添加闹钟
//{
////更新主界面
//Display_Allarm_Main();
//}
}
//编辑闹钟
voidSet_Allarm(void)
{
u8i=0;
Interface_Type=Set_Allarm_Type;
Display_Set_Allarm_Interface();//设置闹钟界面
if(Success_Set==1)//表示成功设置闹钟
{
Set_Allarm_Hour=Set_Allarm_Hour_Temp;
Set_Allarm_Min=Set_Allarm_Min_Temp;
//把当前设置的一周中星期几闹铃的值更新到数组中去
for(i=0;i<7;i++)
{
Set_Allarm_Week[i]=Set_Allarm_Week_Temp[i];
}
Set_Allarm_Loop=Set_Allarm_Loop_Temp;
All_Allarm_Hour[Set_Allarm_Number-1]=Set_Allarm_Hour;//把当前设置的闹钟的小时值更新到所有闹钟时间的数组中对应位置
All_Allarm_Min[Set_Allarm_Number-1]=Set_Allarm_Min;//把当前设置的闹钟的分值更新到所有闹钟时间分钟的数组中对应位置
//把当前设置的一周中星期几闹铃的值更新到数组中去
for(i=0;i<7;i++)
{
All_Allarm_Week[Set_Allarm_Number-1][i]=Set_Allarm_Week[i];
}
if(All_Allarm_STA[Set_Allarm_Number-1]==1)
{
if(All_Allarm_Week[Set_Allarm_Number-1][calendar.week]==1)//编辑闹钟的话如果当天有闹钟已经闹了编辑过后又要让他重新可以闹
Already_Allarm[Set_Allarm_Number-1][calendar.week]=0;
}
//更新当前设置的闹钟的重复与否参数写入数组中
All_Allarm_Loop[Set_Allarm_Number-1]=Set_Allarm_Loop;
//针对有效的闹钟进行查询,当天最接近报警时间的值,作为准备闹铃的时间
Find_Nearest_Time_Allarm();
////更新主界面
//Display_Allarm_Main();
Success_Set=0;
}
//else//表示没有成功添加闹钟
//{
////更新主界面
//Display_Allarm_Main();
//}
}
voidDelete_Allarm_Funtion(void)
{
u8i=0;
u8j=0;
u8Temp=0;
//当前删除的闹钟编号之后的闹钟全部清0
for(j=0;j{
for(i=0;i<7;i++)
{
Already_Allarm[j][i]=0;
}
}
Display_Allarm_Num--;
Temp=Delete_Allarm_Number;
for(Delete_Allarm_Number=Temp;Delete_Allarm_Number<=Display_Allarm_Num;Delete_Allarm_Number++)
{
All_Allarm_Hour[Delete_Allarm_Number-1]=All_Allarm_Hour[Delete_Allarm_Number];
All_Allarm_Min[Delete_Allarm_Number-1]=All_Allarm_Min[Delete_Allarm_Number];
All_Allarm_STA[Delete_Allarm_Number-1]=All_Allarm_STA[Delete_Allarm_Number];
for(i=0;i<7;i++)
{
All_Allarm_Week[Delete_Allarm_Number-1][i]=All_Allarm_Week[Delete_Allarm_Number][i];
}
All_Allarm_Loop[Delete_Allarm_Number-1]=All_Allarm_Loop[Delete_Allarm_Number];
if(All_Allarm_STA[Delete_Allarm_Number-1]==1)//如果移位后的闹钟是打开状态才进行以下更新
{
RTC_Get();//更新时间
//将在当前时间之前的天数的闹钟都设置为已经闹铃过了
for(i=0;i<7;i++)
{
if(calendar.week==0)
{
if(i!
=0)//不等于星期天的其他全部设置为无效
Already_Allarm[Delete_Allarm_Number-1][i]=1;
else//星期天的查询
{
if((calendar.hour*60+calendar.min)>(Set_Allarm_Hour*60+Set_Allarm_Min))
Already_Allarm[Delete_Allarm_Number-1][i]=1;
}
}
else
{
if(iAlready_Allarm[Delete_Allarm_Number-1][i]=1;
elseif(i==calendar.week)
{
if((calendar.hour*60+calendar.min)>(Set_Allarm_Hour*60+Set_Allarm_Min))
Already_Allarm[Delete_Allarm_Number-1][i]=1;
}
}
}
}
}
//首先将以前的最后一个闹钟参数全部清了
All_Allarm_Hour[Display_Allarm_Num]=0;//把当前设置的闹钟的小时值更新到所有闹钟时间的数组中对应位置
All_Allarm_Min[Display_Allarm_Num]=0;//把当前设置的闹钟的分值更新到所有闹钟时间分钟的数组中对应位置
All_Allarm_STA[Display_Allarm_Num]=0;
for(i=0;i<7;i++)
{
All_Allarm_Week[Display_Allarm_Num][i]=0;
}
for(i=0;i<7;i++)
{
Already_Allarm[Display_Allarm_Num][i]=0;
}
All_Allarm_Loop[Display_Allarm_Num]=0;
Delete_Allarm_Number=Temp;//回复编号值
//针对有效的闹钟进行查询,当天最接近报警时间的值,作为准备闹铃的时间
Find_Nearest_Time_Allarm();
LCD_Display_Window(Vertical_LCD,0,29*Delete_Allarm_Number+2,240,320-29*Delete_Allarm_Number-2,BLACK);
for(i=Delete_Allarm_Number;i<=Display_Allarm_Num;i++)
{
Display_Allarm_Interface(i);
}
}
voidOpen_Or_Close_Allarm(void)
{
u8i=0;
//打开或者关闭对应编号的闹钟
if(All_Allarm_STA[Open_Or_Close_Number-1]==1)
All_Allarm_STA[Open_Or_Close_Number-1]=0;
else
All_Allarm_STA[Open_Or_Close_Number-1]=1;
if(All_Allarm_STA[Open_Or_Close_Number-1]==1)
LCD_Display_Window(Vertical_LCD,10,29*Open_Or_Close_Number+2+22,22,2,GREEN);
else
LCD_Display_Window(Vertical_LCD,10,29*Open_Or_Close_Number+2+22,22,2,WHITE);
if(All_Allarm_STA[Open_Or_Close_Number-1]==0)//关闭了当前闹钟就需要把当前闹钟的已经闹铃数组全部清0
{
for(i=0;i<7;i++)
{
Already_Allarm[Open_Or_Close_Number-1][i]=0;
}
}
if((All_Allarm_Loop[Open_Or_Close_Number-1]!
=1)&&(All_Allarm_STA[Open_Or_Close_Number-1]==1))//如果查询到当前闹钟不是每周循环的话并且当前为打开了闹钟,清0全部已经闹铃数组
{
for(i=0;i<7;i++)
{
Already_Allarm[Display_Allarm_Num-1][i]=0;
}
RTC_Get();//更新时间
//将在当前时间之前的天数的闹钟都设置为已经闹铃过了
for(i=0;i<7;i++)
{
if(calendar.week==0)
{
if(i!
=0)//不等于星期天的其他全部设置为无效
Already_Allarm[Display_Allarm_Num-1][i]=1;
else//星期天的查询
{
if((calendar.hour*60+calendar.min)>(Set_Allarm_Hour*60+Set_Allarm_Min))
Already_Allarm[Display_Allarm_Num-1][i]=1;
}
}
else
{
if(iAlready_Allarm[Display_Allarm_Num-1][i]=1;
elseif(i==calendar.week)
{
if((calendar.hour*60+calendar.min)>(Set_Allarm_Hour*60+Set_Allarm_Min))
Already_Allarm[Display_Allarm_Num-1][i]=1;
}
}
}
}
Find_Nearest_Time_Allarm();//由于打开和关闭了闹钟要重新搜索出距离当前时间最近的闹钟
}
//针对有效的闹钟进行查询,当天最接近报警时间的值,作为准备闹铃的时间
voidFind_Nearest_Time_Allarm(void)
{
u8i=0;
u8j=0;
RTC_Get();//更新时间
Prepare_Allarm_Time=2000;//将准备闹铃的时间设置为最大值
for(i=0;i{
if(All_Allarm_STA[i]==1)//查询到当前闹钟是打开
{
//将在当前时间之前的天数的闹钟都设置为已经闹铃过了
for(j=0;j<7;j++)
{
if(calendar.week==0)
{
if(j!
=0)//不等于星期天的其他全部设置为无效
Already_Allarm[i][j]=1;
else//星期天的查询
{
if((calendar.hour*60+calendar.min)>(All_Allarm_Hour[i]*60+All_Allarm_Min[i]))
Already_Allarm[i][j]=1;
}
}
else
{
if(jAlready_Allarm[i][j]=1;
elseif(j==calendar.week)
{
if((calendar.hour*60+calendar.min)>(All_Allarm_Hour[i]*60+All_Allarm_Min[i]))
Already_Allarm[i][j]=1;
}
}
}
if(All_Allarm_Week[i][calendar.week]==1)//查询当前星期是否对应有闹钟
{
if(Already_Allarm[i][calendar.week]!
=1)//表示查询到这个闹钟今天还没闹过,并且今天是有闹钟的
{
if(All_Allarm_Hour[i]*60+All_Allarm_Hour[i]{
Prepare_Allarm_Time=All_Allarm_Hour[i]*60+All_Allarm_Min[i];
Allarm_Number=i;
}
}
}
}
}
}