单片机——时钟调节"/>
单片机——时钟调节
软件(Keil uVision4 + Proteus 8 Professional + stc-isp-15xx-v6.85p)
图标
“万年历”设计任务书
功能简述
数码管以3秒的间隔交替显示日期和时间,并且时间可以修改。
系统硬件部分主要由单片机最小系统、数码管显示、按键模块、LED显示等模块组成。系统组成框图如图 1 所示:
图 1 系统组成框图 |
设计任务及要求
一、显示界面
1. 当前日期界面
把考试当日的年、月、日数据显示在数码管上,当前日期(以2023年1月12日为例)界面如图 2 所示
图 2 日期显示图
|
2. 当前时间显示界面
把从当前时间的时、分、秒数据显示在数码管上,当前日期(以9时31分30秒为例)界面如图 3 所示:
图 2 时间显示图
|
3、设置时间
设置界面分小时设置界面和分钟设置界面,小时设置界面如图4所示,分钟设置界面如图5所示。
图 3 修改小时图
|
图 4 小时设置界面 |
图 3 修改分钟图
|
二、整分LED显示模块
当时间达到整分时,8个LED灯以0.2秒的间隔时间向左流水2次。
三、按键设置模块
按键模块采用矩阵按键,系统初始时,当前日期、时间每隔3秒轮流显示,当系统显示当前温度界面时,按S2、S3无效,当第1次按下S1时,系统显示设置小时界面,此时按S2,小时增1,按S3小时减1,当第2次按下S1时,系统显示设置分钟界面,此时按S2,分钟增1,按S3分钟减1,当第3次按下S1时,系统回到当前日期、时间显示界面。按键流程如图6所示。
led.c
#include<reg51.h>
#include <intrins.h>
#include <stdio.h>
#include "SEG.h"
#include "key.h"
/*
1.数码管显示display_dat, seg_fresh P0:s1-s8 P2:a-e
2.字符解析显示码值char_to_code,display_code,
3.定时器初始化,函数声明 ,写中断函数
4.3s交替显示日期、时间变量计数,
5.流水灯变量计数,P1:灯,x=0xfe,0.2s ,fun_led() ,调用
6.按键P3,key_scan(), flag_mode, key_old , key_new
*/
//sbit LED1=0X90;//变量区
bit change_mode=0;//日期、时间切换
bit is_min=0;//流水标志
bit is_200ms=0;
char led_count=0;//0-16
char led_x=0xfe;
//key 变量
unsigned char flag_mode=0,key_new,key_old=0;//函数声明
void TR0_init();
void seg_pro();
void fun_led();
void key_pro();unsigned char display_dat[8]={0XC6,0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82}; //c0-6
unsigned char display_show[10] ;
char hour=12,minute=59,second=57,month=4,day=18;
int year=2023;void main()
{unsigned int i; unsigned char key_new,key_old=0;sprintf(display_show,"%02d-%02d-%02d",(int)hour,(int)minute,(int)second);char_to_code(display_show,display_dat);SEG_Fresh(display_dat); TR0_init();while(1){key_pro(); //按键seg_pro(); //数码管fun_led(); //led}
}void TR0_init()
{TMOD=0X01;TH0=0X3C; TL0=0XB0; TR0=1;EA=1;ET0=1;
}void seg_pro()
{if(flag_mode==0){if(!change_mode){sprintf(display_show,"%02d-%02d-%02d",(int)hour,(int)minute,(int)second);char_to_code(display_show,display_dat);SEG_Fresh(display_dat);}else{sprintf(display_show,"%4d%02d%02d",(int)year,(int)month,(int)day);char_to_code(display_show,display_dat);SEG_Fresh(display_dat);}}else if(flag_mode==1){ sprintf(display_show,"E1 %02d",(int)hour);char_to_code(display_show,display_dat);SEG_Fresh(display_dat);}else if(flag_mode==2){sprintf(display_show,"E2 %02d",(int)minute);char_to_code(display_show,display_dat);SEG_Fresh(display_dat);}}
void fun_led()
{if(is_200ms) //0.2s{is_200ms=0;if(is_min) //整分{P1=led_x;led_x=_crol_(led_x,1);if(++led_count==17){led_count=0;P1=0xff;is_min=0; }}}}
void key_pro()
{key_new=key_can();switch(key_new ^ key_old & key_new){case 1:if(++flag_mode==3) flag_mode=0; break;case 2:if(flag_mode==1) {if(++hour==24) hour=0;}else if(flag_mode==2) {if(++minute==60) minute=0;}break;case 3:if(flag_mode==1) {if(--hour==-1) hour=23;}else if(flag_mode==2) {if(--minute==-1) minute=59;}break;}key_old=key_new;
}
void timer0( ) interrupt 1
{static unsigned char i=0,j=0,times=0;TH0=0X3C; TL0=0XB0;if(++times==20) //1s{times=0;if(++second==60){second=0;//is_minif(++minute==60){minute=0;if(++hour==24){hour=0;} }}}if(++i==60){i=0;//3schange_mode=~change_mode;}if(second==0)//整分{is_min=1;}if(++j==4) //是0.2s{j=0;is_200ms=1;}}
seg.c(数码管刷新函数+字符转数码管显示码函数)
#include<reg51.h>
#include <intrins.h>
#include <stdio.h>
#include "SEG.h"unsigned char code display_code[]={'E',0x86,'C',0XC6,'0',0xC0,'1',0xF9,'2',0xA4,'3',0xB0,'4',0x99,'5',0x92,'6',0x82,'7',0xF8,'8',0x80,'9',0x90,'-',0xbf,' ',0xff};
void SEG_Fresh(unsigned char *p)
{static char i=0,x=0xfe;P2=0xff;P0=x;P2=p[i];x=_crol_(x,1);i++;if(i==8) i=0;}void char_to_code(unsigned char *p,unsigned char *q)
{static unsigned char i,j,k;for(i=0,k=0;i<8;i++,k++){for(j=0;j<14;j++){if(p[i]==display_code[2*j]){q[k]=display_code[2*j+1];break;}} }}
key.c(按键扫描函数)
#include<reg51.h>
#include <intrins.h>unsigned char key_can()
{static char i=0,x=0xfe;for(i=0;i<4;i++){P3=x;if(P3!=x){switch(P3){case 0x7e: return 1;case 0x7d: return 2;case 0x7b: return 3;}}x=_crol_(x,1); }return 0x00;
}
2023.4.18
更多推荐
单片机——时钟调节
发布评论