192第19章实践项目开发指导_第1页
192第19章实践项目开发指导_第2页
192第19章实践项目开发指导_第3页
192第19章实践项目开发指导_第4页
192第19章实践项目开发指导_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

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

文档简介

19践项目开发指导--多功能电子钟章节的PDF版地址可以从主站找到:,#ifndef_KEY_BOARD_H#define#ifndefvoidKeyScan();voidvoidKeyAction(uint8#define_KEY_BOARD_C#include"config.h"#include"keyboard.h"#include"Time.h"#include"main.h"constuint8codeKeyCodeMap[4][4]={//矩阵按键到PC标准键码的1','2','3',0x26},//1234','5','6',0x25},//4567','8','9',0x28},//78900x1B,0x0D,0x27}//0、ESC键、回车键、向右键uint8pdataKeySta[4][4]={//{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,/**/voidKeyAction(uint8keycode){if((keycode>='0&&(keycode<='9'))//{}elseif(keycode0x25)//{}elseif(keycode0x27)//{}elseif(keycode0x0D)//回车键,切换运行状态/{}elseif(keycode0x1B)//Esc键,静音/{if(staSystemE_NORMAL){staMute=} //处于设置状态时退出设{}}}/**/voidKeyDriver(){uint8i,staticuint8pdatabackup[4][4]={//{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,for(i=0;i<4;i++)//4*4{for(j=0;j<4;{if(backup[i][j] //检测按键动{ifbackup[i][j] //按键按下时执行动{KeyAction(KeyCodeMap[i][j]);//调用按键动作函}backup[i][j] //刷新前一次的备份}}}}/*按键扫描函数,需在定时中断中调用,调用间隔1ms*/voidKeyScan(){uint8staticuint8keyout=0;//矩阵按键扫描输出索引staticuint8keybuf[4][4]={//矩阵按键扫描缓冲区{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,//4keybuf[keyout][0]=(keybuf[keyout][0]<<1)|KEY_IN_1;keybuf[keyout][1]=(keybuf[keyout][1]<<1)|KEY_IN_2;keybuf[keyout][2]=(keybuf[keyout][2]<<1)|KEY_IN_3;keybuf[keyout][3]=(keybuf[keyout][3]<<1)|//消抖后更新按键状for(i=0;i<4;i++)//44{if((keybuf[keyout][i]&0x0F)=={//404*4msKeySta[keyout][i]=}elseif((keybuf[keyout][i]&0x0F)=={//414*4msKeySta[keyout][i]=}} keyout&=0x03;//4switch(keyout)//根据索引值,当前输出引脚,拉低下次的输出引{case0:KEY_OUT_4=1;KEY_OUT_1=0;case1:KEY_OUT_1=1;KEY_OUT_2=0;case2:KEY_OUT_2=1;KEY_OUT_3=0;case3:KEY_OUT_3=1;KEY_OUT_4=0;break;default:break;}} 把红外按键的代码解析出来后,再去做相应的操作显得有点多余了。的处理方式是,把红外的按键代码解析出来,和板载按键进 对应关系,不同的红外按 为板子上的不同的板载按键值就可以了,这样只需要写一套按键驱动序,红外的代码只做解析和功能即可/***********************Infrared.h文件程序源代码#ifndef_INFRARED_H#define#ifndefvoidInitInfrared();voidInfraredDriver();#define_INFRARED_C#include"config.h"#include"Infrared.h"#includeconstuint8codeIrCodeMap[][2]={//红外键码到标准PC键码的{0x450x00},{0x46,0x00{0x470x1B},开关->无Mode->无静音-{0x44,0x00},{0x40,0x25},{0x43,0x27},//->无后退->向左前进->向{0x070x00},{0x15,0x28{0x090x26},EQ->无减号->->{0x160x30},{0x19,0x1B},0x0D,0x0D},//'0'->'0'箭头->ESCU/SD->{0x0C,0x31},{0x18,0x32},{0x5E,0x33},//'1'->'1''2'->'2''3'-{0x08,0x34},{0x1C,0x35},{0x5A,0x36},//'4'->'4''5'->'5''6'-{0x42,0x37},{0x52,0x38},{0x4A,0x39},//'7'->'7''6'->'8''9'-bitirflag0;//1uint8ircode[4];//红外代码接收缓冲区/**/voidInfraredDriver(){uint8if{irflag=for(i=0;i<sizeof(IrCodeMap)/sizeof(IrCodeMap[0]);i++)//遍历{if(ircode[2]IrCodeMap[i][0])// //用对应的码执行函数调度 //直接调用按键动作函数即可}}}}/**/voidInitInfrared(){IR_INPUT1;//确保红外接收引脚被TMOD&=0x0F;//清零T1的控制位TMOD|=0x10;//配置T11TR1 //停止T1ET1= //T1中IT1 //设置INT1为负边沿触EX1 //使能INT1中}/**/uint16GetHighTime(){TH10;//清零T1TL1=TR11;//启动T1while(IR_INPUT)//10{if(TH1>= //当T10x400018msbreak;//}}TR10;//停止T1return(TH1*256+TL1);//T1计数值为16bit整型数,并返回该}/**/uint16GetLowTime(){TH10;//清零T1TL1=TR11;//启动T1whileIR_INPUT)//01{if(TH1>= //当T10x400018msbreak;//}}TR10;//停止T1return(TH1*256+TL1);//T1计数值为16bit整型数,并返回该}/*INT1中断服务函数,执行红外接收及*/voidEXINT1_ISR()interrupt2{uint8i,j;uint8byt;uint16time;//接收并判定引导码的9ms低电time=if((time<7833)||(time>8755))// IE1=0;//退出前清零INT1中断标志}//接收并判定引导码的4.5ms高电time=if((time<3686)||(time>4608))// IE1=0;}//4for(i=0;i<4;i++)//4{for(j=0;j<8;j++)//8个{//接收判定每bit560ustime=if((time<313||(time>718)) IE1=0;}//接收每bitbittime=if((time>313&&(time<718 //在此范围内说明该bit0byt>>=1;//因低位在先,所以数据右移,为}elseiftime>1345)&&(time<1751)) //在此范围内说明该bit值为byt1;//因低位在先,所以数据右移,byt|=0x80;//置1}else//{IE1=}}ircode[i]byt;//}irflag1;//IE1 //退出前清零INT1中断标}这一切底层的驱动完成之后,就可以整理调试main.c和Time.c内的功能代码了。一边添加功能一边调试,最终的功能代码调试出来,在KST-51开发板上做验证。这一切都完事之后,可以添加一项新功能,就是DS18B20温度传#ifndef_DS18B20_H#define#ifndefbitbitGet18B20Temp(int16#define_DS18B20_C#include"config.h"#include"DS18B20.h"/*延时函数,延时时间(t*10)us*/voidDelayX10us(uint8t){do}while(--}/**/bitGet18B20Ack(){bitEA=0;//总中IO_18B20 //产生500us复位脉IO_18B20=1; //延时ack=IO_18B20;//存在脉冲while(!IO_18B20等待存在脉冲结束EA=1;//重新使能总中断return}/*向DS18B20写入一个字节,dat-*/voidWrite18B20(uint8dat){uint8EA=0;//总中for(mask=0x01mask!=0;mask<<=1)//8个{IO_18B20 //2us低电平脉if((mask&dat)0)//bitIO_18B20=IO_18B20= //延时IO_18B20 //拉高通信引}EA1;//}/*从DS18B20一个字节,返回值-读到的字节*/uint8Read18B20(){uint8dat;uint8mask;EA=0;//总中for(mask=0x01;mask!=0;mask<<=1)//低位在先,依次8个{

IO_18B20 //2us低电平脉IO_18B20 //结束低电平脉冲,等待18B20输出 //延时if //通信引脚上的dat&=dat|= //再延时}EA1;//return}/*18B20温度转换,返回值-*/bitStart18B20(){bitackGet18B20Ack();//18B20if(ack //如18B20正确应答,则启动一次转{Write18B20(0xCC);//跳过ROMWrite18B20(0x44);//}return~ack;//ack==0表示操作成功,所以返回值对其取}/*DS18B20转换的温度值,返回值-表示是否成功*/bitGet18B20Temp(int16*temp){bituint8LSBMSB16bitack //执行总线复位,并获取18B20应if(ack== //如18B20正确应答,则温度{Write18B20(0xCC);//跳过ROMWrite18B20(0xBE);//发送读命令LSBRead18B20();//读温度值的低字节MSBRead18B20();//*temp=((int16)MSB<<8)+LSB;//为16bit整型}return~ack;//ack==0表示操作应答,所以返回值为其取反}#ifndef_TIME_H#define#ifndef_TIME_CexternbitstaMute;voidvoidRefreshDate(uint8ops);voidRefreshAlarm();voidAlarmMonitor();voidSwitchSystemSta();voidCancelCurSet();voidSetRightShift();voidSetLeftShift();voidInputSetNumber(uint8#define_TIME_C#include"config.h"#include"DS1302.h"#include"LedBuzzer.h"#include"Lcd1602.h"#include"Time.h"#include"main.h"uint8codeWeekMod[]={//星期X字符0xFF,0x990x000x00,0x00,0x810xC30xE7,//星期日(红心0xEF,0xE7,0xE30xE70xE70xE7,0xE7,0xC3,//0xC3,0x810x9D,0x87,0xC3,0xF90xC10x81,//0xC3,0x810x9D,0xC7,0xC70x9D,0x810xC3,//0xCF0xC70xC3,0xC9,0xC9,0x81,0xCF,0xCF,//0x81,0xC1,0xF9,0xC3,0x870x9D,0x810xC3,//0xC3,0x810xF9,0xC3,0x810x99,0x810xC3,//bitstaMute0;//uint8AlarmHour0x07;//闹钟时间的小时数uint8AlarmMin=0x30;//闹钟时间的分钟数structsTimeCurTime;//当前日期时间uint8SetIndex0;//uint8pdataSetAlarmHour;//闹钟小时数设置缓冲uint8pdataSetAlarmMin;//闹钟分钟数设置缓冲structsTimepdataSetTime;///**/voidRefreshTime(){ ShowLedNumber(5,CurTime.hour>>4,0);//时ShowLedNumber(4,CurTime.hour&0xF,1);ShowLedNumber(3,CurTime.min>>4,0);//分ShowLedNumber(2,CurTime.min&0xF,1);ShowLedNumber(1,CurTime.sec>>4,0);//秒ShowLedNumber(0,CurTime.sec&0xF,0);ShowLedArray(WeekMod+CurTime.week*8);//星期}/*日期刷新函数,ops-00*/voidRefreshDate(uint8ops){uint8pdatastr[12];staticuint8backup=0;if((backup!=CurTime.day)||{str[0]CurTime.year>>12)&0xF)0';//4str[1]=((CurTime.year>>8)&0xF)+'0';str[2]=((CurTime.year>>4)&0xF)+'0';str[3]=(CurTime.year&0xF)+'0';str[4] //分隔str[5](CurTime.mon4)0';//月份str[6]=(CurTime.mon&0xF)+'0';str[7] //分隔str[8](CurTime.day40';//日期str[9]=(CurTime.day&0xF)+'0';str[10]='\0'; LcdShowStr(0,0,str);//显示到液晶上backupCurTime.day;//刷新上次日期值}}/**/voidRefreshAlarm(){uint8pdataLcdShowStr(0,1,"Alarmat"); str[0]=(AlarmHour>>4)+'0';//闹钟小时数str[1]=(AlarmHour&0xF)+'0';str[2] //分隔str[3]=(AlarmMin>>4)+'0'; str[4]=(AlarmMin&0xF)+'0';str[5] //字符串结束LcdShowStr(9,1 //显示到液晶}/*闹钟函数,抵达设定的闹钟时间时执行闹铃*/voidAlarmMonitor(){if((CurTime.hour==AlarmHour&&(CurTime.min==AlarmMin{ifstaMute)//staBuzzer~staBuzzer;//实现蜂鸣器断续鸣叫staBuzzer=}{staMute=staBuzzer=}}/**/voidShowSetTime(){uint8pdatastr[0]=((SetTime.year>>4)&0xF)0';//2str[1]=(SetTime.year&0xF)+str[2]='-str[3]=(SetTime.mon4'0';//月份str[4]=(SetTime.mon&0xF)+'0';str[5]='-str[6]=(SetTime.day40';//日期str[7]=(SetTime.day&0xF)+'0';str[8]='-str[9]=(SetTime.week&0xF)0星期str[10]='';str[11(SetTime.hour4)0';//小时str[12]=(SetTime.hour&0xF)+'0';str[13]=str[14(SetTime.min4)0';//分钟str[15]=(SetTime.min&0xF)+'0';str[16]=LcdShowStr(0,0,"SetDateTime");//显示提示标题LcdShowStr(0,1, //显示设置时间}/**/voidShowSetAlarm(){uint8pdatastr[0](SetAlarmHour4)0';//小时str[1]=(SetAlarmHour&0xF)+'0';str[2]=str[3]=(SetAlarmMin>>4)+'0'; str[4]=(SetAlarmMin&0xF)+'0';str[5]=LcdShowStr(0,0,"SetAlarm");//显示提示标题LcdShowStr(0,1, //显示设定闹钟}/**/voidSwitchSystemSta(){if(staSystemE_NORMAL)//{staSystem=SetTime.yearCurTime.year;//当前时间拷贝到时间设置缓冲区中SetTime.mon=CurTime.mon;SetTime.day=CurTime.day;SetTime.hour=CurTime.hour;SetTime.min=CurTime.min;SetTime.sec=CurTime.sec;SetTime.week=CurTime.week;LcdClearScreen();//液晶清屏 SetIndex=255; LcdOpenCursor();//}elseif(staSystemE_SET_TIME)//{staSystem=SetTime.sec //0 SetAlarmHourAlarmHour;当前闹钟值拷贝到设置缓冲区SetAlarmMin=AlarmMin;LcdClearScreen();//液晶清屏 SetIndex=255; }else//{staSystem=AlarmHourSetAlarmHour;//设定的闹钟值写入闹钟时间AlarmMin=SetAlarmMin;LcdCloseCursor();//关闭光标LcdClearScreen();//液晶清屏RefreshTime();//刷新当前时间RefreshDate(1);//立即刷新日期显示RefreshTemp(1);//立即刷新温度显示RefreshAlarm();//闹钟设定值显示}}/**/voidCancelCurSet(){staSystem=E_NORMAL;LcdCloseCursor();//关闭光标LcdClearScreen();//液晶清屏RefreshTime();//刷新当前时间RefreshDate(1);//立即刷新日期显示RefreshTemp(1);//立即刷新温度显示RefreshAlarm();//闹钟设定值显示}/*void{if(staSystem=={switch{case0:SetIndex=1;LcdSetCursor(1,1);case1:SetIndex=2;LcdSetCursor(3,1);case2:SetIndex=3;LcdSetCursor(4,1);case3:SetIndex=4;LcdSetCursor(6,1);case4:SetIndex=5;LcdSetCursor(7,1);case5:SetIndex=6;LcdSetCursor(9,1);break;case6:SetIndex=7;LcdSetCursor(11,1);break;case7:SetIndex=8;LcdSetCursor(12,1);break;case8:SetIndex=9;LcdSetCursor(14,1);break;case9:SetIndex=10;LcdSetCursor(15,1);break;default:SetIndex=0;LcdSetCursor(0,1);break;}}elseif(staSystem=={switch{case0:SetIndex=1;LcdSetCursor(1,1);break;case1:SetIndex=2;LcdSetCursor(3,1);break;case2:SetIndex=3;LcdSetCursor(4,1);break;default:SetIndex=0;LcdSetCursor(0,1);break;}}}/**/voidSetLeftShift(){if(staSystem=={switch{case0:SetIndex=10;LcdSetCursor(15,1);break;case1:SetIndex=0;LcdSetCursor(0,1);break;case2:SetIndex=1;LcdSetCursor(1,1);case3:SetIndex=2;LcdSetCursor(3,1);case4:SetIndex=3;LcdSetCursor(4,1);case5:SetIndex=4;LcdSetCursor(6,1);case6:SetIndex=5;LcdSetCursor(7,1);case7:SetIndex=6;LcdSetCursor(9,1);break;case8:SetIndex=7;LcdSetCursor(11,1);break;case9:SetIndex=8;LcdSetCursor(12,1);break;default:SetIndex=9;LcdSetCursor(14,1);break;}}elseif(staSystem=={switch{case0:SetIndex=3;LcdSetCursor(4,1);break;case1:SetIndex=0;LcdSetCursor(0,1);break;case2:SetIndex=1;LcdSetCursor(1,1);break;default:SetIndex=2;LcdSetCursor(3,1);break;}}}/*输入设置数字,修改对应的设置位,并显示该数字,ascii-输入数字的ASCII*/voidInputSetNumber(uint8ascii){uint8num=ascii-if(num<=9)//0~9{if(staSystem=={switch{case0:SetTime.year=LcdShowChar(0,1,ascii); //年份数case1:SetTime.year=LcdShowChar(1,1,ascii);break; case2:SetTime.mon=(SetTime.mon&0x0F)|(num<<4);LcdShowChar(3,1,ascii); //月份数case3:SetTime.mon=LcdShowChar(4,1,ascii);break; case4:SetTime.day=(SetTime.day&0x0F)|(num<<4);LcdShowChar(6,1,ascii); //日期数case5:SetTime.day=LcdShowChar(7,1,ascii);break; case6:SetTime.week=(SetTime.week&0xF0)|(num);LcdShowChar(9,1,ascii);break; case7:SetTime.hourLcdShowChar(11,1,ascii); //小时数case8:SetTime.hour=LcdShowChar(12,1,ascii);break; case9:SetTime.min=(SetTime.min&0x0F)|(num<<4);LcdShowChar(14,1,ascii); //分钟数default:SetTime.min=(SetTime.min&0xF0)|(num);LcdShowChar(15,1,ascii);break; }SetRightShift();//}elseif(staSystem=={switch{case0:SetAlarmHour=(SetAlarmHour&0x0F)|LcdShowChar(0,1,ascii); //小时数case1:SetAlarmHour=(SetAlarmHour&0xF0)|LcdShowChar(1,1,ascii);break; case2:SetAlarmMin=(SetAlarmMin&0x0F)|(num<<4);LcdShowChar(3,1,ascii); //分钟数default:SetAlarmMin=(SetAlarmMin&0xF0)|(num);LcdShowChar(4,1,ascii);break; }SetRightShift();//}}}#ifndef_MAIN_H#defineenumeStaSystem{//系统运行状态枚举E_NORMAL,E_SET_TIME,E_SET_ALARM#ifndefexternenumeStaSystemstaSystem;voidRefreshTemp(uint8ops);voidConfigTimer0(uint16/***********************main.c文件程序源代码#define_MAIN_C#include"config.h"#include"Lcd1602.h"#include"LedBuzzer.h"#include"keyboard.h"#include"DS1302.h"#include"DS18B20.h"#include"Infrared.h"#include"Time.h"#include"main.h"bitflag2s //2s定时标志bitflag200ms=0;//200ms定时标志uint8T0RH=0; uint8T0RL= //T0重载值的低字enumeStaSystemstaSystemE_NORMAL;//void{EA=1; ConfigTimer0(1);//配置T0定时1ms //初始化LED模块 InitInfrared();//初始化红外接收模块 //启动首次温度转换whileflag2s);//2flag2s= RefreshDate(1);//立即刷新日期显

温馨提示

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

评论

0/150

提交评论