校园作息时间控制系统(基于单片机)_第1页
校园作息时间控制系统(基于单片机)_第2页
校园作息时间控制系统(基于单片机)_第3页
校园作息时间控制系统(基于单片机)_第4页
校园作息时间控制系统(基于单片机)_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.PAGE.目录1.系统设计方案与论证……………………32.1设计要求…………………32.2系统设计总体方案…………………..….32系统的硬件设计与实现………………..…………………42.1.1时钟芯片DS12887性能简介……….42.1.2时钟芯片读写时序……………….…62.1.3时间寄存器地址……………………62.1.4特殊控制寄存器功能………………72.2.1液晶SYB12864介绍………………82.2.2液晶与单片机的接口………………82.2.3液晶写操作时序……………………92.3.1红外发送与接收……………………102.3.2遥控码数据分析……………………102.3.3接收电路……………112.4.1电源部分电路图……………………113.程序设计…………………123.主程序流程图……………123.2按键识别……………..……………..…133.3课表计算………………133.4遥控解码………………144.系统测试与总结…………16附录1主要元器件清单………………….…17附录2程序清单………….…18附录3原理图与印制板图………………….35附录4系统使用说明……………………….36附录5系统实物图片……………………….371.系统设计方案与比较1.1设计要求一、时钟功能:能显示年、月、日、星期、时、分、秒二、调整功能:能校正年份、日期、时间等三、打铃功能:按指定时间表播放音乐、现场修改作息时间表四、设置的作息时间表数据在单片机掉电后不会丢失1.2系统设计总体方案根据设计要求实现的功能,可以采用不同的设计系统方案如下:方案一:采用单片机自带定时器进行计时,外加存储器保存课表数据,普通键盘输入。由于单片机进行软件计时,硬件成本比较低,但是误差比较大,需要校准,日后的维护工作量比较大。可用廉价的AT24C04等存储器保存数据,读写比较容易。对于普通的独键盘,设置量比较大,改用矩阵键盘又会占用较大的电路板空间。方案二:采用实时时钟芯片计时,红外数据输入。时钟芯片常见的有美信公司的DS1302、DS12887等.前者与后者的最大区别在于有没有自带的备份电池。前者需要增加额外的电池以及相关的充电电路,后者DS12887本身已经集成了锂电池,而且掉电后相当长一段时间还可以正常走时,最重要的是它还剩下114字节的非易失RAM,由于有备份电池供电,相当于一个存储器,可以充分利用,而不需要增加另外的存储器,减少了外围电路。电视红外遥控比较常见,只要解码出来,可以充分利用面板上的多个数字键,接收电路也相当简单,另外由于是非接触式按键,避免了普通机械按键的磨损弊端。故本设计选用第二种方案.总体方框图如下:单片机单片机89S52时钟芯片DS12887红外接收头遥控液晶显示蜂鸣器2.系统的硬件设计与实现2.1时钟芯片DS12887性能简介2.1.1时钟芯片特点功能简介及引脚分布如图:2.1.2读写时序2.1.3时间寄存器地址值得注意的是上表中最后的寄存器地址0EH--7FH,这里就是剩余的144字节RAM,在本设计中实际使用的是10H—13H四个字节,用于保存课表上午和下午的起始数据。2.1.4特殊控制寄存器功能2.2液晶显示块部分电路2.2.1液晶SYB12864功能与技术参数简介SYB12864是一种图形点阵液晶显示器,它主要由行驱动器/列驱动器及128×64全点阵液晶显示器组成.可完成图形显示,内置汉字库,可以显示8×4个<16×16点阵>汉字.主要技术参数和性能:1.电源:VDD:+5V;LCD外接驱动电压为3.0∽8.0V2.显示内容:128<列>×64<行>点3.全屏幕点阵4.七种指令5.与CPU接口采用8位数据总线并行输入输出和8条控制线.2.2.2液晶与单片机接口外部接口信号如下表所示:管脚号管脚名称LEVER管脚功能描述1VSS0V电源地2VDD5.0V电源电压3V0-液晶显示器驱动电压4RSH/LRS="H",表示DB7~DB0为显示数据RS="L",表示DB7~DB0为显示指令数据5R/WH/LR/W="H",E="H",数据被读到DB7~DB0R/W="L",E="H→L",DB7~DB0的数据被写到IR或DR6EH/L使能信号:R/W="L",E信号下降沿锁存DB7~DB0R/W="H",E="H"DRAM数据读到DB7~DB07DB0H/L数据线8DB1H/L数据线9DB2H/L数据线10DB3H/L数据线11DB4H/L数据线12DB5H/L数据线13DB6H/L数据线14DB7H/L数据线15PSBH/LH:8或4位并口,L串口〔本设计中硬件置高电平16NC17RETH/L复位信号,低电平复位<如不需要经常复位可以悬空>18VOUT10VLCD驱动电压19LED+-LED背光板电源20LED--LED背光板电源数据线D0~D7与单片机P0口相连,完成数据传送。单片机P1.0与液晶RS相连,控制显示数据和显示指令数据.单片机P1.1与液晶RW相连,控制数据读写.单片机P1.2与液晶E相连,液晶REST与电源相连,控制液晶复位信号。18脚是液晶背光驱动端,通过限流可变电阻调节对比度,由于经过试验测量可变电阻大概是16K,为了方便电路布局,用15K的固定电阻。液晶与单片机接口图2.2.3液晶写操作时序写操作时序R/W为低电平,CS为低电平写入指令,R/W为低电平,CS为高电平写入数据2.3红外遥控2.3.1发送与接收通用红外遥控系统由发射和接收两大部分组成。应用编/解码专用集成电路芯片来进行控制操作,如图所示。发射部分包括键盘矩阵、编码调制、LED红外发送器;接收部分包括光、电转换放大器、解调、解码电路。2.3.2遥控码数据分析遥控发射器专用芯片很多,这里我们以运用比较广泛,解码比较容易的一类来加以说明,以东芝公司的TC9012组成发射电路为例说明编码原理。当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的"0";以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的"1",其波形如图所示。遥控码的"0"和"1"上述"0"和"1"组成的32位二进制码经38kHz的载频进行二次调制,然后再通过红外发射二极管产生红外线向空间发射。一般电视遥控器的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。后16位为8位的操作码和8位的操作反码,用于核对数据是否接收准确。

根据红外编码的格式,发送数据前需要先发送4.5ms的起始码和4.5ms的结果码作为引导码。

遥控串行数据编码波形如下图所示:2.3.3接收电路接收电路较为简单,采用一体化接收头HS0038,滤波电容在这里可以减少电源带来的干扰。如图:2.4电源2.3.3接收电路2.4.1电源部分电路图为达到提供稳定5V供电电压,变压器采用了玩具车电池充电适配器,由于此电源只包含了全波整流电路,在此加上滤波电路和稳压电路,如图。3.系统的软件设计3.1主程序流程图主程序流程图:读取课表数据并计算读取时间欢迎界面时钟与液晶复位读取课表数据并计算读取时间欢迎界面时钟与液晶复位上电上电显示时间显示时间比较课表T比较课表True显示课次,播放音乐显示课次,播放音乐FalseTrueFalseTrue键扫键扫退出菜单选择修改课表选择查看课表选择调整时间退出菜单选择修改课表选择查看课表选择调整时间调整时间上午课表修改课表调整时间上午课表修改课表保存设置下午课表保存设置保存设置下午课表保存设置3.2按键识别为了输入简单,用数字键直接输入要设置的数字,而且没有另外设置专门的光标移位键,即输入一个数字后自动换到一个位置,如果有现成的不需要修改的数字,可以直接按任意非数字键跳过。由于进行年月日等数据的保存时是以两个键为一个单位〔比如23,由此将产生一个问题,怎样保存无效的键值,即如果第一个键是无效键或者第二个键是无效键,这个数据怎么保存。具体解决办法如下:从遥控按键解码结果可知,键值和数字键的数字对应关系为:如果键值小于9〔0x09,按键数字就是键值加上1,而键值9对应按键"0"。所以两个按键的要分九种情况,第一个按键有三种情况,无效键,1~9键,0键,第二个键也有三种情况,考虑到第二个键有可能是无效键,所以按第一个键〔十位时候要保存个位数字,具体赋值如下:〔以年为例,year0,year1,year2分别是原值、第一次按键后赋值、第二次按键后赋值第一个按键后赋值如下表:key>9〔无效键year1=year0key<9〔1~9键year1=10*<key+1>+year0%10key=9〔0键year1=year0%10第二个按键后赋值如下表:第一个键第二个键赋值无效键0键year2=year1/10*101~9键0键year2=year1/10*100键0键year2=year1/10*10为方便编程没有用year2=0无效键1~9键year2=year1/10*10+key+11~9键1~9键year2=year1/10*10+key+10键1~9键year2=key+1无效键无效键year2=year11~9键无效键year2=year10键无效键year2=year1事实上第二个键是无效键的情况在刚开始已经考虑,所以键值不变,可以不做处理。3.3课表计算以上午为例,当设定好第一节课上课时间,以后的时间在此基础上往上加。第一节课下课第二节课上课第二节课下课第三节课上课第三节课下课第四节课上课第四节课下课小时增量0012223分钟增量4555400455540实际编写程序计算时,为了对齐,插入了无效的0值,当然如果schedule1[]表同样采用二维数组可避免此弊端,这也是当时编程时候总体设计考虑不周造成的,以至于要修改就要改动其很多的数据。3.4遥控解码具体解码过程如下:通过定时器读出相应的高低电平,先读出低电平,再读出高电平,如果中间有非正常的值则重新接收。每八个位为一个字节数据,总共四个有效数据,最后在数码管上显示。#include<AT89X51.H>

#definec<x><x*110592/120000>//便于数据分析

sbitIr_Pin=P3^6;//接收管脚

unsignedcharcodeLed_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,

0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};//共阳极数码显示码0-F.

unsignedcharcodeLed_Sel[]={0xfe,0xfd,0xfb,0xf7};//显示位控

unsignedcharLed_Buf[4];//显示缓冲区

unsignedcharLed;//位选

unsignedcharIr_Buf[4];//用于保存解码结果

//===================================================

timer0<>interrupt1using1

//防止按键时LED显示闪烁

{

TL0=<65536-1000>%256;

TH0=<65536-1000>/256;//定时器0设定约1000us中断一次,用于数码管扫描

P0=0xff;

P2=Led_Sel[Led];//位选

P0=Led_Tab[Led_Buf[Led]];//段选

if<++Led>3>Led=0;

//四个扫描完了,到第一个数码管

}

//===================================================

unsignedintIr_Get_Low<>

//获取低电平时间

{

TL1=0;

TH1=0;

TR1=1;

while<!Ir_Pin>;//当P3.6为低等待

TR1=0;

returnTH1*256+TL1;

}

//===================================================

unsignedintIr_Get_High<>//获取高电平时间

{

TL1=0;

TH1=0;

TR1=1;

while<Ir_Pin>;//当P3.6为高等待

TR1=0;

returnTH1*256+TL1;

}//===================================================main<>

{

unsignedinttemp;

chari,j;

TMOD=0x11;

TL0=<65536-1000>%256;

TH0=<65536-1000>/256;//定时器0设定约1000us中断一次,用于数码管扫描

EA=1;

ET0=1;

TR0=1;

while<1>

{

restart:

while<Ir_Pin>;

temp=Ir_Get_Low<>;//允许有一定的误差if<temp<c<4000>||temp>c<5000>>continue;//引导脉冲低电平4500

temp=Ir_Get_High<>;

if<temp<c<4000>||temp>c<5000>>continue;//引导脉冲高电平4500

for<i=0;i<4;i++>//4个字节

for<j=0;j<8;j++>//每个字节8位

{

temp=Ir_Get_Low<>;//560us低电平if<temp<c<200>||temp>c<800>>gotorestart;

temp=Ir_Get_High<>;

//560us或1680us高电平if<temp<c<200>||temp>c<2000>>gotorestart;

Ir_Buf[i]>>=1;//先写"0"

if<temp>c<1120>>

Ir_Buf[i]|=0x80;//再写"1"

}

Led_Buf[0]=Ir_Buf[2]&0x0f;

//低四位数据码

Led_Buf[1]=Ir_Buf[2]>>4;

//高四位数据码

Led_Buf[2]=Ir_Buf[0]&0x0f;

//低四位系统码

Led_Buf[3]=Ir_Buf[0]>>4;

//高四位系统码

}

}解码结果如下,系统码为0x0E〔由于设置键和屏显键的键值相同,故有同样的功能4.总结经过各方面的测试,达到设计的要求。一、在系统硬件的设计方面,充分考虑了电路元器件的布局,整个系统板小巧精致。刚开始用万能板做实验时,红外接收头由于没有使用滤波电路,抗干扰能力比较弱,单片机容易进入死机状态,经过改进后,恢复正常,只有极少数情况下会出现死机,可能是电源干扰所致,如果加入看门狗电路可以避免死机。在设计的过程中,曾遇到了许多的问题,比如内存溢出、液晶的判忙、按键识别、菜单设置等,经过了大量的调试修改工作,得以解决,在这过程中积累了宝贵的经验。二、本设计还可以进一步改进和添加新的功能1、加入温度测量。采用DS18B20,只占用一根单片机口线,精度也比较高。2、闹钟功能。DS12887 上自带闹钟功能。如果只是用来做普通的闹钟,实用性不强,其实在本设计中可以用来打铃,只要把课表计算好,每次上课或者下课后由单片机自动把下一个打铃点设置为闹钟,这样就不用单片机来比较打铃点。3、加入液晶屏保功能。在没有操作时把液晶电源关掉,当有按键出现时点亮液晶,可以延长液晶使用寿命,还可以节省电能。不过具体操作时候必须把液晶的电源和地线全部断开。4、添加任意打铃点,并可以删除。其实还有一百多字节的非易失RAM剩余,可以保存数据。附录1:主要元器件清单序号名称型号,规格数量备注1单片机AT89S521AT89S522电阻色环电阻10kΩ1kΩ200Ω15kΩ1211误差10%3电容0.1uF,470uF10uF33p,uF1000uF221211104470uF/25V10uF/10v1031000uF/10V4三极管90121PNP5蜂鸣器16时钟芯片DS12CR8871DS12CR8877电视遥控器1TC90128液晶128641128649单片机插座40座1DIP4010插座单排插座1SIP2011排阻10K1103J12发光二极管红色发光二极管13直流插座1三脚直流座14晶振112MHZ16稳压管LM78051LM7805附录2:程序清单#include<reg52.h>#defineucharunsignedchar #defineuintunsignedintucharweek,key,high;//12864液晶操作口sbitrs=P1^0; sbitrw=P1^1;sbiten=P1^2;//ds12cr887操作口sbitds=P3^3; sbitRw=P3^2;sbitas=P3^1;sbitcs=P3^0;sbitIr_Pin=P3^5;//红外接收ucharIr_Buf[4];//保存解码数据bitenable=1; //允许进入设置菜单bitflag; //音乐开关sbitbuzzer=P3^6; //蜂鸣器ucharcodeschedule0[2][13]= {{0,0,0,0,1,0,2,0,2,0,2,0,3},//课表小时增量 {45,0,55,0,40,0,0,0,45,0,55,0,40}};//课表分钟增量uchartable[6]; //依次为年 月日时分秒uchartable1[4]; //依次为设置课表上午*时*分,下午*时*分ucharidataschedule1[16]; //上午课表ucharidataschedule2[16];//下午课表ucharidatadisplayschedule1[4][13];//上午课表显示缓冲区ucharidatadisplayschedule2[4][13];//下午课表显示缓冲区ucharcodeytable[]={2,4};//显示第二行第四行 坐标ucharcodextable[]={1,2,4,5,7,8};//显示列 设置时间显示位置ucharcodextable1[]={2,3,5,6};//显示列设置课表显示位置//=================延时=========================================voiddelay<uintm>{ while<m-->; }//==============================================================/*液晶*///=========================判忙=================================voidcheckbusy<>{rs=0;rw=1;P0=0xff;while<1>{ en=1; if<P0<0x80>break;//P0的最高位为忙标志为,H:忙,L:空闲 en=0; }en=0;} //===========液晶写指令=========================================voidwritecommand<ucharcommand>{ checkbusy<>; rs=0; rw=0; en=1; P0=command;//液晶数据线P0 en=0;}//============液晶写数据=========================================voidwritedata<uchardate>{ checkbusy<>; rs=1; rw=0; en=1; P0=date; en=0;}//==============液晶设置=========================================voidlcdset<void>{ writecommand<0x30>;//基本指令集 writecommand<0x01>;//清屏,DDRAM的地址归零 writecommand<0x02>;//地址归位 writecommand<0x0c>;//显示开,光标关,反白关 writecommand<0x06>;//DDRAM地址加1}//===========设置光标=============================================voidcursor<uchary,ucharx>{ucharcommand=0x80;writecommand<0x0f>; //开光标闪烁if<y==2>y=3;elseif<y==3>y=2;command|=<y-1><<3;command+=<x-1>;writecommand<command>;}//===========设置反白=============================================voidconvert<ucharyy> //反白一行{ucharx,y,i,j;y=0x80;x=0x80;writecommand<0x36>;//绘图开for<i=0;i<32;i++>{writecommand<y++>; writecommand<x>;for<j=0;j<16;j++>writedata<0x00>;}y=0x80;x=0x88;for<i=0;i<32;i++>{writecommand<y++>;writecommand<x>;for<j=0;j<16;j++>writedata<0x00>;}writecommand<0x30>;if<yy>2>{x=0x88;y=<<yy-3><<4>+0x80;}else{x=0x80;y=<<yy-1><<4>+0x80;}writecommand<0x36>;for<i=0;i<16;i++>{writecommand<y++>;writecommand<x>;for<j=0;j<16;j++> //一行宽度是16的点writedata<0xff>;}writecommand<0x30>;}//===========字符显示============================================voiddisplay<uchary,ucharx,uchar*p>{switch<y>{case1:writecommand<0x7f+x>;break;//液晶第一行case2:writecommand<0x8f+x>;break;//0x90+<x-1>case3:writecommand<0x87+x>;break;case4:writecommand<0x97+x>;break;default:break;}while<*p> writedata<*p++>;}//=========显示数字===============================================voiddisplayNumber<uchary,ucharx,ucharnumber>{ switch<number> { //引号内数字为中文全角输入占据一个汉字位置 case0:display<y,x,"0">;break; case1:display<y,x,"1">;break; case2:display<y,x,"2">;break; case3:display<y,x,"3">;break; case4:display<y,x,"4">;break; case5:display<y,x,"5">;break; case6:display<y,x,"6">;break; case7:display<y,x,"7">;break; case8:display<y,x,"8">;break; case9:display<y,x,"9">;break; default:break; }}//==========显示星期===============================================voiddisplayweek<ucharweek>{ switch<week> { case1:display<3,3,"一">;break; case2: display<3,3,"二">;break; case3: display<3,3,"三">;break; case4: display<3,3,"四">;break; case5: display<3,3,"五">;break; case6: display<3,3,"六">;break; case7: display<3,3,"日">;break; default:break; } }//==========显示课次===============================================voiddisplaylesson<ucharlesson>{ switch<lesson> { case1:display<3,5,"第一节课">;break; case2: display<3,5,"第二节课">;break; case3: display<3,5,"第三节课">;break; case4: display<3,5,"第四节课">;break; case5: display<3,5,"第五节课">;break; case6: display<3,5,"第六节课">;break; case7: display<3,5,"第七节课">;break; case8: display<3,5,"第八节课">;break; default:break; } }//==========显示菜单===============================================voidmenu<void>{ writecommand<0x01>; //清屏 display<1,3,"设置时间">; display<2,3,"查看课表">; display<3,3,"修改课表">; display<4,3,"退出菜单">;}//===========显示时间==============================================voiddisplaytime0<void> //静态数据{ display<1,2,"校园作息系统">; display<2,3,"年">; display<2,6,"月">; display<3,1,"星期">; display<4,3,"-">; //全角输入 display<4,6,"-">;} voiddisplaytime1<void>{ //动态数据 displayNumber<2,1,table[0]/10>; displayNumber<2,2,table[0]%10>; displayNumber<2,4,table[1]/10>; displayNumber<2,5,table[1]%10>; displayNumber<2,7,table[2]/10>; displayNumber<2,8,table[2]%10>; displayweek<week>; displayNumber<4,1,table[3]/10>; displayNumber<4,2,table[3]%10>; displayNumber<4,4,table[4]/10>; displayNumber<4,5,table[4]%10>; displayNumber<4,7,table[5]/10>; displayNumber<4,8,table[5]%10>; }//==============================================================/*红外*///==========取回低电平==========================================uintIr_Get_Low<>{ TL1=0; TH1=0; TR1=1; while<!Ir_Pin>;//等待高电平到来 TR1=0; returnTH1*256+TL1;}//===========取回高电平==========================================uintIr_Get_High<>{ TL1=0; TH1=0; TR1=1; while<Ir_Pin>;//等待低电平到来 TR1=0; returnTH1*256+TL1;}//============红外解码===========================================ucharIR_decode<void>{uinttemp; //12M晶振uchari,j; restart: temp=Ir_Get_Low<>; if<temp<4000||temp>5000>gotorestart;//引导码低电平4500us temp=Ir_Get_High<>; if<temp<4000||temp>5000>gotorestart;//引导码高电平4500us for<i=0;i<4;i++>//4个字节 for<j=0;j<8;j++>//每个字节8位 { temp=Ir_Get_Low<>;//560us低电平 if<temp<200||temp>800>gotorestart; temp=Ir_Get_High<>;//560us或1680us高电平 if<temp<200||temp>2000>gotorestart; Ir_Buf[i]>>=1;//右移一位准备写数据,相当于填0 if<temp>1120>Ir_Buf[i]|=0x80;//若为1再填1 } return<Ir_Buf[2]>;}//==============================================================/*ds12cr887*///==========12887写数据=========================================voidwrite_ds<ucharaddress,uchardate>{ cs=0; as=1; ds=1; Rw=1; P2=address; as=0; Rw=0; P2=date;//ds12cr887数据线 Rw=1; as=1; cs=1; }//============12887读数据========================================ucharread_ds<ucharaddress>{ uchardate; as=1; ds=1; Rw=1; cs=0; P2=address; as=0; ds=0; date=P2; ds=1; as=1; cs=1; returndate; }//==============================================================/*课表处理*///===========课表计算============================================voidschedulecount<void>{uchari;schedule1[0]=read_ds<0x10>; //读取课表数据schedule1[1]=read_ds<0x11>;for<i=0;i<=12;i=i+2> //上午课表数据{ schedule1[i+2]=schedule1[0]+schedule0[0][i]; schedule1[i+3]=schedule1[1]+schedule0[1][i]; if<schedule1[i+3]>=60> //小时进位 { schedule1[i+2]++;schedule1[i+3]=schedule1[i+3]-60; }}schedule2[0]=read_ds<0x12>;schedule2[1]=read_ds<0x13>;for<i=0;i<=12;i=i+2> //下午课表数据{ schedule2[i+2]=schedule2[0]+schedule0[0][i]; schedule2[i+3]=schedule2[1]+schedule0[1][i]; if<schedule2[i+3]>=60> { schedule2[i+2]++;schedule2[i+3]=schedule2[i+3]-60; }}}//===========课表数据转换成显示字符===============================voidscheduletostring<void>{uchari,j;for<i=0,j=0;i<4;i++,j=j+4> //上午课表每次转换一行 { displayschedule1[i][0]=schedule1[j]/10+'0'; displayschedule1[i][1]=schedule1[j]%10+'0'; displayschedule1[i][2]=':'; displayschedule1[i][3]=schedule1[j+1]/10+'0'; displayschedule1[i][4]=schedule1[j+1]%10+'0'; displayschedule1[i][5]='-'; displayschedule1[i][6]='-'; displayschedule1[i][7]=schedule1[j+2]/10+'0'; displayschedule1[i][8]=schedule1[j+2]%10+'0'; displayschedule1[i][9]=':'; displayschedule1[i][10]=schedule1[j+3]/10+'0'; displayschedule1[i][11]=schedule1[j+3]%10+'0'; displayschedule1[i][12]='\0'; }for<i=0,j=0;i<4;i++,j=j+4> //下午课表 { displayschedule2[i][0]=schedule2[j]/10+'0'; displayschedule2[i][1]=schedule2[j]%10+'0'; displayschedule2[i][2]=':'; displayschedule2[i][3]=schedule2[j+1]/10+'0'; displayschedule2[i][4]=schedule2[j+1]%10+'0'; displayschedule2[i][5]='-'; displayschedule2[i][6]='-'; displayschedule2[i][7]=schedule2[j+2]/10+'0'; displayschedule2[i][8]=schedule2[j+2]%10+'0'; displayschedule2[i][9]=':'; displayschedule2[i][10]=schedule2[j+3]/10+'0'; displayschedule2[i][11]=schedule2[j+3]%10+'0'; displayschedule2[i][12]='\0'; }}//===========课表显示============================================voiddisplayschedule<void>{ schedulecount<>; //课表计算 scheduletostring<>; //课表数据转换成显示字符 display<2,4,"上午">; //第二行 delay<65500>;delay<65500>; while<1> { display<1,1,"一">; //上午课表 display<1,3,displayschedule1[0]>; display<2,1,"二">; display<2,3,displayschedule1[1]>; display<3,1,"三">; display<3,3,displayschedule1[2]>; display<4,1,"四">; display<4,3,displayschedule1[3]>; if<!Ir_Pin>break; //任意键退出 } writecommand<0x01>; //清屏 display<2,4,"下午">; //第二行 delay<65500>;delay<65500>; while<1> { display<1,1,"五">; //下午课表 display<1,3,displayschedule2[0]>; display<2,1,"六">; display<2,3,displayschedule2[1]>; display<3,1,"七">; display<3,3,displayschedule2[2]>; display<4,1,"八">; display<4,3,displayschedule2[3]>; if<!Ir_Pin>break; }}//=========修改课表================================================voidsetschedule<void>{ucharm=0,i=0,j=0,k=0;voidsetNumber<uchary,ucharx>;//函数声明table1[0]=read_ds<0x10>; //上午课表起始时间table1[1]=read_ds<0x11>;table1[2]=read_ds<0x12>; //下午课表起始时间table1[3]=read_ds<0x13>;display<1,4,"上午">; //第一行displayNumber<2,2,table1[0]/10>;//第二行displayNumber<2,3,table1[0]%10>;display<2,4,"-">;displayNumber<2,5,table1[1]/10>;displayNumber<2,6,table1[1]%10>;display<3,4,"下午">; //第三行displayNumber<4,2,table1[2]/10>; //第四行displayNumber<4,3,table1[2]%10>; display<4,4,"-">;displayNumber<4,5,table1[3]/10>;displayNumber<4,6,table1[3]%10>;while<1> //依次是上午起始时间*时*分下午起始时间*时*分 { //i0~3循环两次,j0~3循环一次,k0~1循环一次 while<1> { //一直闪烁 有键按下时,Ir_Pin变低切换到下一个位置 cursor<ytable[k],xtable1[i]>;if<!Ir_Pin>break;//十位闪烁 } setNumber<ytable[k],xtable1[i]>;//显示设置数字 if<key==0x09>table1[j]=0*10+table1[j]%10;//考虑到可能下次是无关键 elseif<key<0x09>table1[j]=10*<key+1>+table1[j]%10;//本次为1~9键 m=key; //暂时保存键值,便于下次键分析 i++; //十位完成 while<1> { cursor<ytable[k],xtable1[i]>;if<!Ir_Pin>break;//个位闪烁 } setNumber<ytable[k],xtable1[i]>; if<key==0x09> //本次为0键 { table1[j]=table1[j]/10*10; } elseif<key<0x09> //本次为1~9键 { if<m==0x09>table1[j]=key+1;//上次为0键 table1[j]=table1[j]/10*10+key+1;//上次为无关键或1~9键 } //个位完成 i++;j++; if<i==4> { i=0;k++; if<k==2>{k=0;j=0;break;}//两行设置完跳出循环 }//换到下两位}write_ds<0x10,table1[0]>; //保存课表起始数据write_ds<0x11,table1[1]>;write_ds<0x12,table1[2]>;write_ds<0x13,table1[3]>;}//===========打铃==================================================voidring<void>{ //时 分 if<schedule1[0]==table[3]&&schedule1[1]==table[4]> {displaylesson<1>;flag=1;} //第一节课上课if<schedule1[2]==table[3]&&schedule1[3]==table[4]> {display<3,5,"">;flag=1;}//清除"第*节课"字样if<schedule1[4]==table[3]&&schedule1[5]==table[4]> {displaylesson<2>;flag=1;}if<schedule1[6]==table[3]&&schedule1[7]==table[4]> {display<3,5,"">;flag=1;}if<schedule1[8]==table[3]&&schedule1[9]==table[4]> {displaylesson<3>;flag=1;}if<schedule1[10]==table[3]&&schedule1[11]==table[4]> {display<3,5,"">;flag=1;}//清除"第*节课"字样if<schedule1[12]==table[3]&&schedule1[13]==table[4]> {displaylesson<4>;flag=1;}if<schedule1[14]==table[3]&&schedule1[15]==table[4]> {display<3,5,"">;flag=1;}//第四节课下课if<schedule2[0]==table[3]&&schedule2[1]==table[4]> {displaylesson<5>;flag=1;} //第五节课上课if<schedule2[2]==table[3]&&schedule2[3]==table[4]> {display<3,5,"">;flag=1;}if<schedule2[4]==table[3]&&schedule2[5]==table[4]> {displaylesson<6>;flag=1;}if<schedule2[6]==table[3]&&schedule2[7]==table[4]> {display<3,5,"">;flag=1;}if<schedule2[8]==table[3]&&schedule2[9]==table[4]> {displaylesson<7>;flag=1;}if<schedule2[10]==table[3]&&schedule2[11]==table[4]> {display<3,5,"">;flag=1;}if<schedule2[12]==table[3]&&schedule2[13]==table[4]> {displaylesson<8>;flag=1;}if<schedule2[14]==table[3]&&schedule2[15]==table[4]> {display<3,5,"">;flag=1;}//第八节课下课 }//==============================================================/*键处理*///==========显示设置的数字=======================================voidsetNumber<uchary,ucharx> //占据一个汉字位置{ key=IR_decode<>;//红外键值加上一刚好是要显示的数字 if<key<0x09>{displayNumber<y,x,key+1>;} if<key==0x09>{displayNumber<y,x,0>;}//键值0x09对应按键0}//==========设置时间=============================================voidsettime<void>{ucharm=0,i=0,j=0,k=0;while<1> //设置年月日时分秒 { //i0~5循环两次,j0~5循环一次,k0~1循环一次 while<1> { //一直闪烁 有键按下时,Ir_Pin变低切换到下一个位置 cursor<ytable[k],xtable[i]>;if<!Ir_Pin>break; //十位闪烁 } setNumber<ytable[k],xtable[i]>; //显示设置数字 if<key==0x09>table[j]=0*10+table[j]%10;//考虑到可能下次是无关键 elseif<key<0x09>table[j]=10*<key+1>+table[j]%10;//本次为1~9键 m=key; //暂时保存键值,便于下次键分析 i++; //十位完成 while<1> { cursor<ytable[k],xtable[i]>;if<!Ir_Pin>break;//个位闪烁 } setNumber<ytable[k],xtable[i]>; if<key==0x09> //本次为0键 { table[j]=table[j]/10*10; } elseif<key<0x09> //本次为1~9键 { if<m==0x09>table[j]=key+1;//上次为0键 table[j]=table[j]/10*10+key+1;//上次为无关键或1~9键 } i++;j++; //个位完成 if<i==6> { i=0;k++; if<k==2>{k=0;j=0;break;}//六个两位显示完跳出整个循环 } //换到下两位}}//==========设置星期=============================================voidsetweek<void>{while<1> { cursor<3,3>;if<!Ir_Pin>break; //星期闪烁 } key=IR_decode<>; if<key<0x07>week=<key+1>; displayweek<week>;}//===========保存时间设置=========================================voidsave<void>{ write_ds<9,table[0]>; //年 write_ds<8,table[1]>; //月 write_ds<7,table[2]>;//日 write_ds<6,week>; //星期 write_ds<4,table[3]>; //时 write_ds<2,table[4]>; //分 write_ds<0,table[5]>; //秒}//============键盘扫描===========================================voidkeyscan<void>{ ucharline=1;if<!Ir_Pin> { key=IR_decode<>; if<key==0x19> //进入菜单 { menu<>; //显示菜单 convert<1>; //默认第一行反白 while<enable> { key=IR_decode<>; switch<key> { case0x13: //电视遥控音量减反白行下移 line++; if<line==5> line=1; //允许循环向下移动 convert<line>; break; case0x12: //电视遥控音量加反白行上移 line--; if<line==0> line=4; convert<line>;//第line行反白 break; case0x19: //确定键 switch<line> { case1: //调整时间 writecommand<0x01>; //清屏 displaytime0<>; displaytime1<>; settime<>; setweek<>; writecommand<0x0c>; //关光标 save<>; //保存设置 menu<>; //返回菜单显示 convert<line>;//恢复当前行反白 break; case2: //查看课表 writecommand<0x01>; //清屏 displayschedule<>; menu<>; //返回菜单显示 convert<line>;//恢复当前行反白 break; case3: //修改课表 writecommand<0x01>; //清屏 setschedule<>; writecommand<0x0c>; //关光标 menu<>; //返回菜单显示 convert<line>;//恢复当前行反白 break; case4: //退出整个菜单 enable=0;//防止再次进入菜单 writecommand<0x01>; //清屏 break; default:break; } default:break; } }//结束while<enable> displaytime0<>;//返回显示时间界面静态数据 }}enable=1; //重新允许下次键扫进入菜单delay<1000>;}//==============================================================/*音乐*///======================长延时=================================voiddelay1<uinta>{uinti;ucharj;for<i=0;i<a;i++>{for<j=0;j<125;j++>;}}//======================音乐代码=================================uintcodef[]={0x00,64260

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论