51单片机实现简易电子时钟的设计与实现

需积分: 50 39 下载量 2 浏览量 更新于2025-01-03 15 收藏 406KB ZIP 举报
资源摘要信息:"51单片机简易电子时钟" 知识点: 一、51单片机基础 51单片机是一种基于Intel 8051微控制器架构的微处理器,广泛应用于嵌入式系统和微电子项目。它通常具备一定数量的I/O端口,内部集成定时器/计数器、串行通信接口等功能,支持多种指令集,特别适合于学习和开发电子时钟等项目。 二、数字时钟实现功能 1. 数码管显示:数字时钟的核心显示部件,通过单片机的I/O端口控制数码管显示当前的时、分、秒信息。数码管通常为七段LED显示器,可以显示数字0到9。 2. 定时器计时:51单片机内部集成的定时器/计数器可以被配置为定时中断模式,通过定时器中断来实现计时功能。每过1秒钟,定时器中断就会发生一次,从而实现对秒的计数。 3. 按键调整时间:通过外部按键输入,用户可以进入设置模式,并调整时钟的时、分、秒。这需要编写代码来检测按键状态,并对当前时间进行增加或减少。 三、系统总体设计方案 1. 控制部分:主要由51单片机构成,执行程序指令,控制整个系统的运行逻辑。 2. 按键:作为输入设备,提供用户交互界面。根据按键的不同,实现不同的功能,如进入设置模式、调整时间、退出设置等。 3. LED数码管:作为输出设备,显示当前时间状态。不同的数码管可以被分配显示时、分、秒三个不同的时间单位。 四、功能说明 1. 上电初始化:系统上电后,数码管开始从0开始显示时间。这需要在程序中进行初始化设置,确保数码管能够正确显示时间。 2. 进入设置模式:通过按下SW1按钮,系统切换到设置模式。此时,数码管显示当前选中的时间单位(时、分、秒)。 3. 选择设置项:通过按下SW2或SW3按钮,实现时间设置模式的选择。该功能通常通过改变状态变量来实现。 4. 修改时间:在设置模式中,通过SW4或SW5按钮实现时间值的加减调整。每次按键操作需要更新相关的时间变量,并重新显示到数码管上。 5. 推出修改模式:修改时间完成后,用户需要按下SW1按钮以退出设置模式,并使更改生效。 五、Protues仿真 Protues是一种常用的电路仿真软件,它能够模拟单片机及其外围电路的工作环境。在设计51单片机电子时钟时,可以使用Protues软件进行电路设计和仿真测试,以验证程序和硬件设计的正确性。 六、 beep(蜂鸣器) 在51单片机电子时钟项目中,"beep"可能指代蜂鸣器。蜂鸣器可以用来提供声音反馈,例如,在设定时间的每一分钟,蜂鸣器发出响声提醒用户。 七、文件名称列表 在这个上下文中,"beep"是压缩包子文件的文件名列表中的一个项目。由于没有提供其他文件名,我们不能确定这个列表中其他文件的内容和作用。但是,"beep"作为文件名,可能表明包含了用于控制蜂鸣器发出声音的代码或声音文件。
1615 浏览量
准确延时,数码管显示!用于电子时钟 #include <reg51.h> //*** 函数定义 *** void long_delay(void); // 长延时 void short_delay(void); // 短延时 void delay10ms(unsigned char); // 延时10MS void write7279(unsigned char, unsigned char);// 写入到HD7279 unsigned char read7279(unsigned char);//从HD7279读入 void send_byte(unsigned char); // 发送一个字节 unsigned char receive_byte(void); //接收一个字节 void init_timer(); /*定时器T0初始化*/ void conv(); /*时、分、秒单元及走时单元转换*/ void dirve(); /*时间显示程序*/ void time_adj(); /*时间调整设置*/ unsigned char digit[6]; unsigned char j; unsigned int tmr; unsigned long wait_cnter; unsigned char hour=0,min=0,sec=0; /*时、分、秒单元清零*/ unsigned char deda=0; /*5mS计数单元清零*/ bit sign; //设置标志位 sbit cs=P1^5; // cs at P1.5 sbit clk=P1^4; // clk 连接于 P1.4 sbit dat=P1^3; // dat 连接于 P1.3 sbit set=P3^7; // key 连接于 P3.7 //****** HD7279A 指令 ****** #define CMD_RESET 0xa4 #define CMD_TEST 0xbf #define DECODE0 0x80 #define DECODE1 0xc8 #define CMD_READ 0x15 #define UNDECODE 0x90 #define RTL_CYCLE 0xa3 #define RTR_CYCLE 0xa2 #define RTL_UNCYL 0xa1 #define RTR_UNCYL 0xa0 #define ACTCTL 0x98 #define SEGON 0xe0 #define SEGOFF 0xc0 #define BLINKCTL 0x88 //*** 主函数 *** main() { for (tmr=0;tmr<0x2000;tmr++); // 上电延时 send_byte(CMD_RESET); // 复位HD7279A //****************************************** // 测试指令演示 //****************************************** send_byte(CMD_TEST); // 指令测试 for (j=0;j<3;j++) // 延时哟3秒? { delay10ms(100); } send_byte(CMD_RESET); // 清除显示 //********************************************** //时间显示 //********************************************** init_timer();/*定时器T0初始化*/ while(1) { if(set==0) time_adj(); conv(); /*时、分、秒单元及走时单元转换*/ dirve(); /*时、分、秒单元显示*/ } } /*定时器T0 5mS初始化*/ void init_timer() { TMOD=0x01; TH0=-(4800/256); TL0=-(4800%256); IE=0x82; TR0=1; } /*5mS定时中断服务子函数*/ void zd(void) interrupt 1 { TH0=-(4800/256); TL0=-(4800%256); deda++; } /*时、分、秒单元及走时单元转换*/ void conv() { if(deda>=200){sec++;deda=0;} if(sec==60){min++;sec=0;} if(min==60){hour++;min=0;} if(hour==24){hour=0;} } void dirve() { digit[0]=sec%10; //计数个位 write7279(DECODE0,digit[0]); //显示个位 digit[1]=0x80|(sec/10); //计数十位 write7279(DECODE0+1,digit[1]); //显示十位 digit[2]=0x80|(min%10); //计数百位 write7279(DECODE0+2,digit[2]); //显示百位 digit[3]=0x80|(min/10); //计数千位 write7279(DECODE0+3,digit[3]); //显示千位 digit[4]=0x80|(hour%10); //计数万位 write7279(DECODE0+4,digit[4]); //显示万位 digit[5]=hour/10; //计数十万位 write7279(DECODE0+5,digit[5]); } void write7279(unsigned char cmd, unsigned char dta) { send_byte (cmd); send_byte (dta); } unsigned char read7279(unsigned char command) { send_byte(command); return(receive_byte()); } void send_byte( unsigned char out_byte) { unsigned char i; cs=0; long_delay(); for (i=0;i<8;i++) { if (out_byte&0x80) { dat=1; } else { dat=0; } clk=1; short_delay(); clk=0; short_delay(); out_byte=out_byte*2; } dat=0; } unsigned char receive_byte(void) { unsigned char i, in_byte; dat=1; // 设置为输入状态 long_delay(); for (i=0;i<8;i++) { clk=1; short_delay(); in_byte=in_byte*2; if (dat) { in_byte=in_byte|0x01; } clk=0; short_delay(); } dat=0; return (in_byte); } void long_delay(void) { unsigned char i; for (i=0;i<0x30;i++); } void short_delay(void) { unsigned char i; for (i=0;i<8;i++); } // ********************* 延时 n*10ms ********************** void delay10ms(unsigned char time) { unsigned char i; unsigned int j; for (i=0;i<time;i++) { for(j=0;j<0x390;j++) { } } } /*时间调整程序*/ void time_adj() { if(set==0) //有键按下,判断按键时间 { delay10ms(200); //1s延时程序 if(set==0) //大于1s,进入时间设置 { ET0=0; TR0=0; //关定时器0 while(set==0) dirve(); //等键释放 // ET1=1;TR1=1; con=0xF3; //开定时器1,让调整位闪烁 write7279(BLINKCTL,0xF3); do { while(set!=0) dirve(); //等待按键 delay10ms(100); if(set!=0) //小于0.5s,进入分钟设置 { while(set==0) dirve(); //等待按键释放 sign=1; min++; if(min==60)min=0; //分钟加1 dirve(); } else sign=0; //大于0.5s,进入小时设置 }while(sign); while(set==0)dirve(); //等待按键释放 // con=0xCF; write7279(BLINKCTL,0xCF); do { while(set!=0) dirve(); //等待按键 delay10ms(100); if(set!=0) //小于0.5s,进入小时设置 { while(set==0) dirve(); //等待按键释放 sign=1; hour++; //小时加1 if(hour==24)hour=0; dirve(); } else sign=0; //大于0.5s,结束时间设置 }while(sign); // ET1=0;TR1=0; //关定时器1 ET0=1;TR0=1; //开定时器0 write7279(BLINKCTL,0xFF); } else //小于1s,进入省电模式 { ET0=1; TR0=1; //开定时器0 while(set!=0); //等待按键 do { dirve(); //有键按下,调显示程序消抖 }while(set!=0); //是干扰则继续循环 } while(set==0) dirve(); //等待按键释放 } else ; //无键按下,跳出按键扫描程序 }