首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

[原创]MCS51单片机时钟程序

[原创]MCS51单片机时钟程序

// 本实验采用c语言实现了数字钟实验,主要功能包括 用户设置时,分
// 考虑到键盘不多以及结构问题,本程序并没有实现一些复杂的功能。
// 采用模块化设计,用户要增加自己的功能也非常方便。
// 参见主程序的模块组织结构
// 在HJPC51-B上验证通过

#include "mcs51\8051.h"
#define uchar unsigned char
#define uint unsigned int

#define key1 P3_3 //键盘定义
#define key2 P3_4
#define key3 P3_5

#define segdata P0 //数据 输出
#define sege P2_7 //显示 选中
#define segb P2_6 //位 选
#define segd P2_5 //段 选

uchar flag; //键盘模式,=1增加,=0减少

// 这里定义了一组显示码表。前面的code 关键字表示,这组码表定义
// 在程序存储器区域,而不是采用数据存储器来定义;
// 在一般做这种固定数组时,都应该把他们放置在程序存储区。

uchar code disbuf_u[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,
0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};

uchar led_buf[6]; //段
uchar timead,t_s,t_m,t_h; //基准时间,秒,分,时

void reset(); //上电复位模块

void delay(uint ysz);//模糊延时

void led_buf_flush(void);//缓冲

void disp(void);//显示

void off_led(void);//关显示

void display(unsigned char disseg,unsigned char disdata);//显示输出

uchar keyb(); //键盘程序

void settimer();

void main()

{

SP=0x50; //设置堆栈
reset();
while(1)
{
led_buf_flush();
disp();
off_led();
settimer();
}
}


void reset()
{
TMOD = 0x1; //定时器T0模式1
TL0 = 0x0cf;//定时初值
TH0 = 0x3c;
TR0 = 1; //开始运行
ET0 = 1; //允许定时器T0中断
EA = 1; //总的中断允许
t_m = 0;
t_s = 0;
t_h = 0;
flag = 1; //键盘模式
P3_7 = 0; //关闭蜂鸣器
P0 = 0; //关闭数码管显示
P2 = 255;
}

//中断
void time0() interrupt 1 using 1
{
TR0 = 0;
TL0=0x0cf;
TH0=0x3c;
timead+=1;
if(timead==20) //12M==50ms延时,6M=100ms延时
{
timead=0;
t_s += 1; //1s到了,把秒单元加1

P1_0=!P1_0; //同时闪烁p1.0/1两个灯
P1_1=!P1_1;

if(t_s==60) //一些进位的判断
{
t_s = 0,t_m ++;
if(t_m ==60)
t_m =0,t_h ++;
if(t_h == 24)
t_h = 0;
}

}
TR0 = 1; //开始计数,由于前面一些函数也需要占用时间
//因此,需要在定时初值中减去这段时间的延时常数
}

//延时
void delay(uint ysz)
{
while(ysz--){};
}
//设置时间
void settimer()
{
switch(keyb())
{
case 3:{
if(flag)
{if(t_h != 23) t_h ++;} //设置时
else
{if(t_h !=0 ) t_h --;}
break;}

case 2:{if(flag)
{if(t_m != 59) t_m ++;} //设置分
else
{if(t_m !=0 ) t_m --;}
break;}
case 1:{if(flag) flag = 0; //设置模式切换
else flag = 1;
break;}
}
}

//显示缓冲区
void led_buf_flush(void)
{
led_buf[0]=t_s%10;
led_buf[1]=t_s/10;
led_buf[2]=t_m%10;
led_buf[3]=t_m/10;
led_buf[4]=t_h%10;
led_buf[5]=t_h/10;
}

//显示刷新子程序
void disp()
{
uchar i;
for(i=0;i<6;i++)
{
display(i,led_buf); //调用输出显示

}
}

//显示
//这里是显示子程序,入口参数为
// disseg -> 位选 可选范围 0-7 一共8个数码管
// disdata -> 段选 可选范围 0-31 一个32个字符
// 段选 0-15 16个字符 为 "0"->"F"
// 段选 16-31 16个字符 为 "0."->"F."

void display(unsigned char disseg,unsigned char disdata)
{
unsigned char dataf;
dataf = 1;
while(disseg)
{
dataf <<= 1;
disseg--;
}
sege = 0;
segdata = dataf; //这里首先把要显示的数据放到数据总线
segb = 1; //这里给出一个脉冲,数据送往位选端
segb = 0;

segdata = disbuf_u[disdata];
segd = 1; //这里给出一个脉冲,数据送往段选端
segd = 0;
delay(50);
}

//关显示
void off_led(void)
{
segdata = 255;
segd = 1; //这里给出一个脉冲,数据送往段选端
segd = 0;
}

uchar keyb()
{
uchar key,keytmp;

key1 = 1; //将输出线拉高
key2 = 1;
key3 = 1;

key = P3 ; //读回来
key = key & 0x38; //获得键盘结果
if(key == 56 ) return 0; //如果用户没有按键返回 0
else
{
keytmp = key;
delay(1000); //判断是不是干扰
key = P3;
key = key & 0x38;
if (key != keytmp ) return 0; //是干扰,返回 0
else //不是干扰,等待用户释放按键
{
do{
key1 = 1; //输出拉高
key2 = 1;
key3 = 1;
key = P3 & 0x38; //读回来
}while(key != 56 ); //等待用户释放
P1_2 = 1; //用户释放以后,清除p1.0指示灯
switch(keytmp)
{
case 24: return 3;//返回用户按键结果
case 40: return 2;
case 48: return 1;
}

}


}

return 0;

}

返回列表