实时时钟设计实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告
/ 115
/ 215
/ 315
4 / 15
源代码:
#pragma sfr //使用特殊功能寄存器
#pragma EI //开中断
#pragma DI //关中断
#pragma access //使用绝对地址指令
#pragma interrupt INTTM000 Time //定义时间中断函数为Time
#pragma interrupt INTKR OnKeyPress //定义按键中断为OnKeyPress #pragma interrupt INTP5 OnKeyOver //定义INT中断为OnKeyOver
void Init_Led();
void InitKey_INTKR(); void Init_Lcd();
void Init_Inter();
void LightOneLed(unsigned char ucNum);
void LightOff();
int Count_Day(int month);
char i=0; //定义变量i,是切换时间的标志
int key=0; //定义key=0
int temp=1; //用于存放当前月的天数
int temp1=1;
int second=0; //默认的秒second=0
int minute=0; //默认的分minute=0
int hour=12; //默认的时hour=12
int day=1; //默认的天day=1
int month=5; //默认的月month=5
int year=2014; //默认的年year=2014
int c_hour=1; //默认的闹钟时=1
int c_minute=1; //默认的闹钟分=1
int buffs[2]; //秒的数码显示缓存区
int buffm[2]; //分的数码显示缓存区
int buffh[2]; //时的数码显示缓存区
int buffday[2]; //天的数码显示缓存区
int buffmonth[2]; //月的数码显示缓存区
int buffyear[4]; //年的数码显示缓存区
int buffmd[4]; //月,天的数码显示缓存区
int buffhm[4]; //时,分的数码显示缓存区
int buffms[4]; //分,秒的数码显示缓存区
int buffch[2]; //闹钟时的数码显示缓存区
int buffcm[2]; //闹钟分的数码显示缓存区
unsigned char Que = 0; //INT中断中间变量
int
LCD_num[10]={0X070d,0x0600,0x030e,0x070a,0x0603,0x050b,0x050f,0x0700,0x070f,0x070 b};//
数字0~~9的显示码
unsigned char Scond;
//…………………………延时函数1……………………//
void Delay(int k){
int i,j;
for(i=0;i<k;i++){
for(j=0;j<k;j++){
5 / 15
}
} }
//………………………初始化Led函数……………………//
void Init_Led(){
PM13=0XF0; //端口13的第四位为输出模式
PM14=0XF0; //端口14的第四位为输出模式
PM15=0XF0; //端口15的第四位为输出模式
}
//……………………………按键中断函数……………………//
void InitKey_INTKR(){
PM4 = 0x3F; //P4的六个端口设置为输入模式
PU4 = 0x3F; //接通上拉电阻
KRM = 0x3F; //允许六个按键中断
KRMK = 0;
PM3.0 = 1;
PU3.0 = 1; EGP.5 = 1;
PMK5 = 0;
PPR5 = 0;
KRPR = 1;
}
//……………初始化lcd函数……………………//
void Init_Lcd(){
PFALL=0x0F; //所有接lcd引脚指定为lcd引脚
LCDC0=0x34; //设置原时钟和时钟频率
LCDMD=0x30; //设置lcd电压为3/5电压
LCDM=0xC0; //4分时1/3偏压模式
}
//………………初始化定时器Inter函数……………………// void Init_Inter(){
CRC00.0=0; //CR000为比较寄存器
PRM00=0X04; //计数时钟为fprs/2^8
CR000=0X7FFF;//时间间隔为1s
TMMK010=1; //TMMK010中断屏蔽
TMMK000=0; //TMMK000中断允许
TMC00=0X0C; //TM00和CR000相等时进入清零&启动模式}
void Time(){
second++;
}
//……………………………按键中断函数……………………// void OnKeyPress(){
DI();
switch(P4&0x3F) //判断哪个按键按下
{
case 0x3e:
6 / 15
key=1; //按键key1按下
break;
case 0x3d:
key=2; //按键key2按下
break;
case 0x3b:
key=3; //按键key3按下
break; case 0x37:
key=4; //按键key4按下
break;
case 0x2f:
key=5; //按键key5按下
break; case 0x1f:
key=7; //按键key6按下
break; default:
break;
}
EI();
}
//……………………………INT按键中断函数……………………//
void OnKeyOver(){
DI();
Que = 0; //判断Que是否为0
BZOE = 0; //蜂鸣器关闭
EI();
}
//………………………Led小灯函数……………………//
void LightOneLed(unsigned char ucNum){
switch(ucNum){ //检测变量ucNum
case 0: case 1:
case 2:
case 3:
P13 |= (unsigned char) 1 << (ucNum);
//如果为0到3中的一个值则让LED1到LED4中的一个亮break;
case 4:
case 5:
case 6:
case 7: P14 |= (unsigned char) 1 << (ucNum - 4);
//如果为4到7中的一个值则让LED5到LED8中的一个亮break;
case 8: case 9:
case 10:
case 11:
P15 |= (unsigned char) 1 << (ucNum - 8);
//如果为8到11中的一个值则让LED9到LED12中的一个亮break;
default:
break;
7 / 15
}
}
//………………………Led小灯熄灭函数……………………//
void LightOff(){
P13 = 0; P14 = 0;
P15 = 0;
//……………………时间函数……………………//
void Time1(){
if((second % 5) == 0){ //秒大于5变为0
Scond = second / 5 + 1;
LightOff(); //调用小灯亮函数
LightOneLed(Scond % 12);
} if(second>=60){
minute++; //秒大于60时分加1
second=0; if(minute>=60){
minute=0;
hour++; //分大于60时时加1
if(hour>=24){ hour=0;
day++; //时大于24时天加1
temp=Count_Day(month); if(day>=temp){
day=1;
month++; //天大于当前月份的天数时月加1
if(month>=13){ month=1;
year++; //月大于12时年加1
} }
}
}
}
}
//…………………计算当前月的天数……………………//
int Count_Day(int month){
int day;
if((month==4)||(month==6)||(month==9)||(month==11))//4,6,9,11月为30天day=30;
else if(month==2)
{if((year%4==0&&year_x0010_0==0)||(year@0==0))
day=29; //闰年2月29天
else
day=28; //平年2月28天
}
else
day=31; //1,3,5,7,8,10,12月为31天return (day);
}
8 / 15
//………………倒计时函数.............//
void Show_Time(){
pokew(0xFA40,0x00);
pokew(0xFA42,0x00);
pokew(0XFA48,buffs[1]); //在lcd右边显示1
pokew(0XFA4A,buffs[0]); //在lcd右边显示0
pokew(0XFA44,buffm[1]); //在lcd右边显示1 pokew(0XFA46,buffm[0]); //在lcd右边显示0
pokew(0xFA4C,0x00); pokew(0xFA4E,0x00);
Delay(100);
}
//………………………………日期显示函数……………………// void Display_Date(){
buffm[0]|=0x0800;
pokew(0xFA40,buffyear[3]); //显示年
pokew(0xFA42,buffyear[2]);
pokew(0xFA44,buffyear[1]);
pokew(0xFA46,buffyear[0]);
pokew(0xFA48,buffmonth[1]); //显示月
pokew(0xFA4A,buffmonth[0]);
pokew(0xFA4C,buffday[1]); //显示日
pokew(0xFA4E,buffday[0]);
temp1=0;
}
//………………………………时间显示函数……………………// void Display_Time(){
pokew(0xFA40,0x00);
pokew(0xFA42,0x00);
pokew(0xFA44,buffh[1]); //显示时pokew(0xFA46,buffh[0]);
pokew(0xFA48,buffm[1]); //显示分pokew(0xFA4A,buffm[0]);
pokew(0xFA4C,buffs[1]); //显示秒pokew(0xFA4E,buffs[0]);
}
//………………………………设定时间函数……………………// void Set_D_T(){
int lcd_addr;
lcd_addr = 0xFA40;
switch(i){
pokew(lcd_addr,buffyear[3]); //时间年
pokew(lcd_addr+2,buffyear[2]);
pokew(lcd_addr+4,buffyear[1]);
pokew(lcd_addr+6,buffyear[0]);
pokew(lcd_addr+8,0x00); pokew(lcd_addr+10,0x00);
pokew(lcd_addr+12,0x00);
pokew(lcd_addr+14,0x00);
break;
case 2: pokew(lcd_addr,0x00);
9 / 15
pokew(lcd_addr+2,0x00);
pokew(lcd_addr+4,0x00); pokew(lcd_addr+6,0x00);
pokew(lcd_addr+8,buffmonth[1]); //时间月
pokew(lcd_addr+10,buffmonth[0]);
pokew(lcd_addr+12,0x00); pokew(lcd_addr+14,0x00);
break;
case 3:
pokew(lcd_addr,0x00);
pokew(lcd_addr+2,0x00);
pokew(lcd_addr+4,0x00); pokew(lcd_addr+6,0x00);
pokew(lcd_addr+8,0x00);
pokew(lcd_addr+10,0x00);
时间日pokew(lcd_addr+12,buffday[1]); // pokew(lcd_addr+14,buffday[0]); break;
case 4:
pokew(lcd_addr,0x00);
pokew(lcd_addr+2,0x00);
// 时间时pokew(lcd_addr+4,buffh[1]);
pokew(lcd_addr+6,buffh[0]);
pokew(lcd_addr+8,0x00); pokew(lcd_addr+10,0x00);
pokew(lcd_addr+12,0x00);
pokew(lcd_addr+14,0x00);
break;
case 5:
pokew(0xFA40,0x00);
pokew(0xFA42,0x00); pokew(0xFA44,0x00);
pokew(0xFA46,0x00);
时间分// pokew(0xFA48,buffm[1]);
pokew(0xFA4A,buffm[0]);
pokew(0xFA4C,0x00);
pokew(0xFA4E,0x00);
break;
pokew(0xFA40,0xd1); pokew(0xFA42,0xd0);
pokew(0xFA44,0xd7);
pokew(0xFA46,0xd1);
pokew(0xFA48,0x50);
pokew(0xFA4A,0x56);
闹钟时// pokew(0xFA4C,buffch[1]);
pokew(0xFA4E,buffch[0]);
break;
case 7: pokew(0xFA40,0xd1);
pokew(0xFA42,0xd0);
pokew(0xFA44,0xd7);
pokew(0xFA46,0xd1);
pokew(0xFA48,0x50);
pokew(0xFA4A,0x00);
闹钟分// pokew(0xFA4C,buffcm[1]);
pokew(0xFA4E,buffcm[0]);
break;
10 / 15
default:
break; }
}
//…………………………切换时间函数……………………// void d_c_inter(){
DI(); //关中断
i++;
if(i>7) //切换标志>7,i=1,否则i++
i=1;
EI(); //开中断
}
//…………………………调整时间加函数……………………// void UpNum(){
switch(i){
case 1:
year++; case 2:
month++;
if(month > 12){
month = 1;
}
break; case 3:
temp = Count_Day(month);
day++;
if(temp < day)
day = 1; break;
case 4:
hour++;
if(hour > 23)
hour = 1;
break;
case 5: minute++;
if(minute > 59)
minute = 0;
break;
case 6:
c_hour++; if(c_hour > 23)
c_hour = 1;
break;
case 7: c_minute++;
if(c_minute > 59)
c_minute = 0;
break;
default:
break; }
}
11 / 15
//…………………………调整时间减函数……………………// void DownNum(){
switch(i){
case 1:
year--;
case 2: month--;
if(month < 1){
month = 12;
}
break;
case 3: temp = Count_Day(month);
day--;
if(day < 1)
day = temp;
break;
case 4: hour--;
if(hour < 1)
hour = 23;
break;
case 5: minute--;
if(minute < 0)
minute = 59;
break;
case 6:
c_hour--;
if(c_hour < 1) c_hour = 23;
break;
case 7:
c_minute--;
if(c_minute < 0) c_minute = 59;
break;
default:
break;
} }
//………………………闹铃以及小灯函数……………………//
void noise(){
if(c_hour == hour && c_minute == minute && Que == 1){ //闹铃的时,分与系统时,分
相等,并且闹钟标志开启
CKS=0XE0; //开启蜂鸣器输出,输出频率为0.98khz的音频
Time1(); //调用时间函数
}
}
//…………………………显示缓存区刷新时间函数……………………//
void Freshddisplaybuffer(){
buffs[1]=LCD_num[second/10];//秒的显示码放入秒的数码显示缓存区
12 / 15
buffs[0]=LCD_num[second_x0010_];
buffm[1]=LCD_num[minute/10];//分的显示码放入分的数码显示缓存区
buffm[0]=LCD_num[minute_x0010_];
buffm[0]|=0x0800; //分的后面显示一个.
buffh[1]=LCD_num[hour/10]; //时的显示码放入时的数码显示缓存区
buffh[0]=LCD_num[hour_x0010_];
buffh[0]|=0x0800; //时的后面显示一个.
buffday[1]=LCD_num[day/10]; //天的显示码放入天的数码显示缓存区
buffday[0]=LCD_num[day_x0010_];
buffmonth[1]=LCD_num[month/10];//月的显示码放入月的数码显示缓存区buffmonth[0]=LCD_num[month_x0010_];
buffmonth[0]|=0x0800; //月的后面显示一个.
buffyear[3]=LCD_num[year/100/10];//年的显示码放入年的数码显示缓存区buffyear[2]=LCD_num[(year/100)_x0010_];
buffyear[1]=LCD_num[(year_x0010_0)/10];
buffyear[0]=LCD_num[(year_x0010_0)_x0010_];
buffyear[0]|=0x0800; //年的后面显示一个.
buffmd[3]=LCD_num[month/10];//月,天的显示码放入月,天的数码显示缓存区buffmd[2]=LCD_num[month_x0010_];
buffmd[2]|=0x0800; //月,天后显示一个.
buffmd[1]=LCD_num[day/10];
buffmd[0]=LCD_num[day_x0010_];
buffhm[3]=LCD_num[hour/10];//时,分的显示码放入时,分的数码显示缓存区buffhm[2]=LCD_num[hour_x0010_];
buffhm[2]|=0x0800; //时,分的后显示一个.
buffhm[1]=LCD_num[minute/10];
buffhm[0]=LCD_num[minute_x0010_];
buffms[3]=LCD_num[minute/10];//分,秒的显示码放入分,秒的数码显示缓存区buffms[2]=LCD_num[minute_x0010_];
buffms[2]|=0x0800; //分,秒的后显示一个.
buffms[1]=LCD_num[second/10];
buffms[0]=LCD_num[second_x0010_];
buffch[1]=LCD_num[c_hour/10];//闹钟时的显示码放入闹钟时的数码显示缓存区buffch[0]=LCD_num[c_hour_x0010_];
buffcm[1]=LCD_num[c_minute/10];//闹钟分的显示码放入闹钟分的数码显示缓存区buffcm[0]=LCD_num[c_minute_x0010_];
}
//………………主函数……………………//
void main(){
DI(); //关中断
PM3.4 = 0; //P3.3,P3.4端口设置为输出模式
P3.4 = 1; //led灯初始化为点亮状态
PM3.3 = 0;
P3.3 = 0;
BZOE = 0; //蜂鸣器初始化为熄灭
Init_Lcd(); //初始化lcd
Init_Led(); //初始化led
InitKey_INTKR(); //初始化按键
EI(); //开中断
Init_Inter(); //初始化中断
13 / 15
while(1){
Time1(); //调用计算时间函数
noise(); //调用闹钟函数
switch(key){
case 0: //没有按键执行
Freshddisplaybuffer(); //调用刷新函数
Time1(); //计算时间
Show_Time(); //调用显示时间函数
Show_Time();
break;
case 1: //按键1执行
Time1(); //计算时间
调用刷新函数// Freshddisplaybuffer();
//调用显示日期函数Display_Date();
noise(); //调用闹钟函数break;
//按键2执行case 2:
//计算时间Time1();
//调用刷新函数Freshddisplaybuffer();
Display_Time(); //调用时间显示函数
//调用闹钟函数noise();
break;
case 3: //按键3执行
d_c_inter(); //调用时间切换函数
调用刷新函数Freshddisplaybuffer(); //
Set_D_T(); //调用时间设置函数调用闹钟函数noise();
//key=7;
break;
4执行按键case 4: // UpNum(); //调用时间加函数
Freshddisplaybuffer(); //调用刷新函数
Set_D_T(); 调用时间设置函数//
// 调用闹钟函数noise();
key=7; break;
case 5: 5按键执行//
DownNum(); 调用时间减函数// Freshddisplaybuffer(); //调用刷新函数// Set_D_T(); 调用时间设置函数
// 调用闹钟函数noise();
key=7;
break;
执行按键case 6: //6
key = 0;
判断是否确认if(i > 5) //
Que = 1;
i = 0;
noise(); // 调用闹钟函数case 7: 7 虚拟按键// Time1();
调用刷新函数Freshddisplaybuffer(); //
Set_D_T(); // 调用时间设置函数
/ 1415
noise(); //调用闹钟函数
break;
}
}
}
15 / 15。