单片机实验代码——多功能时钟程序
来源:互联网 发布:java开发人员岗位职责 编辑:程序博客网 时间:2024/05/16 18:50
上次说的多功能时钟代码如下,闹钟功能暂时还没有搞定。另外,直接对P0赋值来改变S1、S2、S3、S4的值的想法竟然在多模式下是无效的,这使得我昨天整整一个白天都在纠结原因,结果还是没有结果。今天上课的时候有时间再研究下吧。
#include <reg51.h>#define uint unsigned int#define uchar unsigned charsbit S1 = P1^3;sbit S2 = P1^1;sbit S3 = P1^2;sbit S4 = P1^0;sbit beep = P2^7; //蜂鸣器sbit a = P0^0;sbit b = P0^1;sbit c = P0^2;sbit d = P0^3;sbit e = P0^4;sbit f = P0^5;sbit g = P0^6;sbit p = P0^7;sbit key1 = P1^4; //开始/暂停sbit key2 = P1^5; //功能键sbit key3 = P3^6;sbit key4 = P3^7;bit flag_add, flag_ring; //定义两个位变量uchar icount, th, tl, mode;uchar clock[5], stopwatch[5], tmp[5], alarm[2] = {0, 0};uchar *point = clock;uchar clockPosition = 3, alarmPosition = 0; //时钟设置模式下, 光标所在的位置; 默认在0uchar clockTmp = 0, alarmTmp = 0; //用于时钟模式下临时计数bit changeDisplay = 0, clockTmpBit = 0, alarmTmpBit = 0; //用于时钟模式下临时标志位uchar code N[10] = {0xc0, 0xf9 ,0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; //0-9数码管的编码(共阳极)uchar code Z[10] = {0x40, 0x79 ,0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10}; //0-9数码管的编码(共阳极), 带小数点//延时函数, 针对12MHz时钟void delayms(uint xms){uint i,j;for(i = xms; i > 0; i--)for(j = 110; j > 0; j--);}void alarm_ring() //蜂鸣器报警声音{beep = 0; delayms(100); beep = 1; }uchar alarmtime(){ uchar flag_alarm; for(icount = 0; icount < 2; icount++) { if(alarm[icount] == clock[icount+3]) flag_alarm = 1; else { flag_alarm = 0; break; }} return flag_alarm;}void setZero(uchar *p){for(icount = 0; icount < 5; icount++)p[icount] = 0;}void init(){TMOD = 0x11; //定时器1, 0 都工作方式1th = 0xd8; //(65536-10000)/256 //定时10mstl = 0xf0; //(65536-10000)%256TH0 = TH1 = th;TL0 = TL1 = tl;EA = 1; //打开总中断ET0 = ET1 = 1; //允许定时器1, 0 中断请求TR0 = 1; //时钟-定时器0TR1 = 0; //秒表-定时器1mode = 1;//初始化时钟和秒表的时分秒计数值setZero(clock);setZero(stopwatch);setZero(tmp);}void displayDatas(uchar thous, uchar hund, uchar ten, uchar pbit){P0 = 0xff;S1 = 0; S2 = S3 = S4 = 1; //P1 = 0x07;P0 = thous;delayms(5); S2 = 0; S1 = S3 = S4 = 1; //P1 = 0x0d;P0 = hund;delayms(5);S3 = 0; S2 = S1 = S4 = 1; //P1 = 0x0b;P0 = ten;delayms(5);S4 = 0; S2 = S3 = S1 = 1; //P1 = 0x0e;P0 = pbit;delayms(5);}void display(){switch(mode){ case 1: if(!changeDisplay) displayDatas(N[point[4]/10], Z[point[4]%10], N[point[3]/10], Z[point[3]%10]); else displayDatas(N[point[2]/10], Z[point[2]%10], N[point[1]], N[point[0]]); break;case 2://时钟设置模式下, 选中位置闪烁clockTmp++;if(clockTmp == 20){clockTmp = 0;clockTmpBit = ~clockTmpBit;}if(clockTmpBit) { switch(clockPosition) { case 3: displayDatas(N[point[4]/10], Z[point[4]%10], 0xff, 0xff);break; case 4: displayDatas(0xff, 0xff, N[point[3]/10], Z[point[3]%10]);break; }} else{ displayDatas(N[point[4]/10], Z[point[4]%10], N[point[3]/10], Z[point[3]%10]);} break;case 3: if(point[3]%10 == 0) { displayDatas(N[point[2]/10], Z[point[2]%10], N[point[1]], N[point[0]]); }else if(point[3]/10 == 0){displayDatas(Z[point[3]%10], N[point[2]/10], Z[point[2]%10], N[point[1]]);}else if(point[3]/10 < 6){displayDatas(N[point[3]/10], Z[point[3]%10], N[point[2]/10], Z[point[2]%10]);}else{displayDatas(N[5], Z[9], N[5], Z[9]);}break;case 4: alarmTmp++;if(alarmTmp == 20){alarmTmp = 0;alarmTmpBit = ~alarmTmpBit;}if(alarmTmpBit) { switch(alarmPosition) { case 0: displayDatas(N[point[1]/10], Z[point[1]%10], 0xff, 0xff);break; case 1: displayDatas(0xff, 0xff, N[point[0]/10], Z[point[0]%10]);break; }} else{ displayDatas(N[point[1]/10], Z[point[1]%10], N[point[0]/10], Z[point[0]%10]);}break;}}//检测功能模式键是否被按下void checkModeKey(){if(!key4){delayms(10);if(!key4){ while(!key4); mode++;switch(mode){ case 1: point = clock;TR0 = 1; break;case 2: //定时器0是不会关闭的, 即使在设置模式下for(icount = 0; icount < 5; icount++){tmp[icount] = clock[icount]; //将设置之前的值暂存到临时数组}point = tmp; clockPosition = 3;break;case 3: //秒表模式 //TR0 = 0;point = stopwatch;break;case 4: //闹钟设置模式point = alarm; alarmPosition = 0;break; case 5: mode = 1; point = clock;TR0 = 1; break;}}}}//选中位数值增1, 用于时钟模式的设置状态下void addValue(uchar Position){flag_add = 1;point[Position]++;switch(Position){case 2:case 3:if(point[Position] >= 60)point[Position] = 0;break;case 4:if(point[Position] >= 24)point[Position] = 0;break;default:if(point[Position] >= 10)point[Position] = 0;}}//检测是否有键按下, 并执行相应功能void checkKey(){checkModeKey();if(flag_ring && alarmtime()) {alarm_ring();if(!key1 || !key2 || !key3 || !key4)//这里用来取消闹钟报警,任一键取消报警{delayms(10);if(!key1 || !key2 || !key3 || !key4){while(!(key1 && key2 && key3 && key4));flag_ring = 0; //清除报警标志}}}switch(mode){ case 1: if(key1 == 0) { delayms(10); if(key1 == 0) { changeDisplay = ~changeDisplay; while(!key1); } } break;case 2:if(!key1) //左移光标位 { delayms(10); if(!key1) { while(!key1); clockPosition++; if(clockPosition > 4) { clockPosition = 3; } } } else if(!key2) //选中位增1 { delayms(10); if(!key2) { while(!key2); addValue(clockPosition); } } else if(!key3) //选中确定更改 { uchar timediff; delayms(10); if(!key3) { while(!key3); timediff = clock[3]*60+clock[2]-point[3]*60-point[2]; if(flag_add || timediff <= 30) //如果addValue()执行, 更新clock[], 否则超过30秒未操作返回时钟模式 { for(icount = 0; icount < 5; icount++) { clock[icount] = point[icount]; //将设置的值存到clock[] } } point = clock; mode = 1; //将模式变成时钟模式 flag_add = 0; } }break;case 3:if(!key1){delayms(10); //延时大约10ms, 去抖动if(!key1) //开始/暂停键按下{ while(!key1);TR1 = ~TR1;}}else if(!key2){delayms(10); //延时大约10ms, 去抖动if(!key2) //清零键按下{ while(!key2);TR1 = 0;TH1 = th;TL1 = tl;for(icount = 0; icount < 5; icount++){stopwatch[icount] = 0;}}}break; case 4: if(!key1) //左移光标位 { delayms(10); if(!key1) { while(!key1); clockPosition++; if(clockPosition > 1) { clockPosition = 0; } } } else if(!key2) //选中位增1 { delayms(10); if(!key2) { while(!key2); addValue(alarmPosition); } } else if(!key3) //选中确定更改 { delayms(10); if(!key3) { while(!key3); for(icount = 0; icount < 2; icount++) { alarm[icount] = point[icount]; //将设置的值存到clock[] } point = clock; mode = 1; //将模式变成时钟模式 flag_add = 0; flag_ring = ~flag_ring; } }break;}}void timeCounter(uchar *timer){timer[0]++; //0.01秒if(timer[0] >= 10){timer[0] = 0;timer[1]++; //0.1秒if(timer[1] >= 10){timer[1] = 0;timer[2]++; //秒if(timer[2] >= 60){timer[2] = 0;timer[3]++; //60秒if(timer[3] >= 60){timer[3] = 0;timer[4]++; //3600秒if(timer[4] >= 24){timer[4] = 0;}}}}}}main(){init();while(1){checkKey(); //检测是否有键按下display(); //显示计时值}}//定时器0中断响应函数, 用于时钟计时void T0_time() interrupt 1{TH0 = th; //重置计数值TL0 = tl;timeCounter(clock);}//定时器1中断响应函数, 用于秒表计时void T1_time() interrupt 3{TH1 = th; //重置计数值TL1 = tl;timeCounter(stopwatch);}
代码还是不够精简,有时间再改进吧。
- 单片机实验代码——多功能时钟程序
- 单片机实验代码——可调时间的时钟程序
- 单片机编写多功能电子时钟
- 单片机时钟实验
- 51单片机——多功能电子钟
- 单片机时钟程序
- 51单片机时钟程序
- 51单片机—串口时钟
- 51单片机—实时时钟
- 本科项目——51单片机多功能万年历
- 小小的单片机时钟程序
- 单片机——ds1302时钟芯片
- 【单片机】51单片机时钟——利用中断
- 51单片机—定时器显示时钟
- 多功能数字时钟
- 多功能时钟应用
- 51单片机(AT89C52)DS1302时钟芯片程序
- AVR单片机(ATMEGA16)DS1302时钟芯片程序
- 编程融入生活--设计模式总结
- Windows Azure Learning Note (3)
- Java Monitor Object在生产者消费者问题中的应用
- 使用GDI+,VS2008/C++环境配置
- 开发管理软件项目存在的风险(下)
- 单片机实验代码——多功能时钟程序
- SQVI和SAP查询QUERY的区别和使用注意事项
- jsp导出excel格式设置
- 几个数据库的相关概念
- VisionMobile:移动平台生态系统冲突报告(九)Chapter C:Bada
- QTP中常用的随机数生产函数
- DEDECMS获取无限栏目子分类的方法
- XP操作系统下,将大容量U盘格式化为NTFS的方法。
- php删除文件夹及其文件夹下所有文件