汇编和C语言的程序都有,请支持一下,谢谢
/***************************************/
//clock.c
//单片机电子钟C语言程序XSCLK V1.0
//MCU:AT89C2051晶振频率:12MHZ
//编写:舒新生日期:2007-11-23
/***************************************/
//最简单的单片机电子钟程序,学习单片机必经之路
//免费单片机辅导,尽最大努力回答您遇到的问题
//电话:13073399262QQ:625608148(白天在线)
/***************************************/
#include <at89x51.h> //头文件包含
#define uchar unsigned char //宏定义
#define uintunsigned int
#define ON0 //定义0为打开
#define OFF 1 //定义1为关闭
#define LEDBus P1 //定义p1口为数码管段码口
sbit MIAO =P1^2; //秒点
sbit HOU_S=P3^0; //时十位位选
sbit HOU_G=P3^1; //时个位位选
sbit MIN_S=P3^2; //分十位位选
sbit MIN_G=P3^3; //分个位位选
sbit H_KEY=P3^4; //时调整键
sbit M_KEY=P3^5; //分调整键
bitSHAN; //闪烁标志位
uchar second,minute,hour; //定义秒、分、时寄存器
uchar code LEDTab[]={0x14,0xd7,0x4c,//数码管段码表0--9
0x45,0x87,0x25,0x24,0x57,0x04,0x05};
void delay(uchar t); //延时函数
void init(); //初始化函数
void display(); //显示函数
void min_tiao(); //分调整函数
void hou_tiao(); //时调整函数
/***************************************
函 数 名:main
功 能:主函数
说 明:
入口参数:无
返 回 值:无
****************************************/
void main()
{
init(); //调用初始化函数
while(1) //主程序循环
{
if(!H_KEY) hou_tiao(); //如果时调整键按下(为0),调用时调整函数
if(!M_KEY) min_tiao(); //如果分调整键按下(为0),调用分调整函数
display(); //调用显示函数
}
}
/***************************************
函 数 名:init
功 能:初始化函数
说 明:初始化定时器及中断
入口参数:无
返 回 值:无
***************************************/
void init()
{
TMOD=1;TH0=0X3C;TL0=0XB0; //定时器0模式1,50毫秒
ET0=1;TR0=1;EA=1; //开定时器0中断、启动定时器0、开总中断
}
/***************************************
函 数 名:display
功 能:显示函数
说 明:
入口参数:无
返 回 值:无
***************************************/
void display()
{
LEDBus=LEDTab[minute%10]; //分个位送数码管显示
MIAO=SHAN; //秒点闪烁
MIN_G=ON; //打开分个位位选
delay(1); //显示1毫秒
MIN_G=OFF; //关闭分个位位选
LEDBus=LEDTab[minute/10]; //分十位送数码管显示
MIAO=SHAN; //秒点闪烁
MIN_S=ON; //打开分十位位选
delay(1); //显示1毫秒
MIN_S=OFF; //关闭分十位位选
LEDBus=LEDTab[hour%10]; //时个位送数码管显示
HOU_G=ON; //打开时个位位选
delay(1); //显示1毫秒
HOU_G=OFF; //关闭时个位位选
if(hour/10) //如果时十位为0,不显示十位数字
{
LEDBus=LEDTab[hour/10]; //时十位送数码管显示
HOU_S=ON; //打开时十位位选
delay(1); //显示1毫秒
HOU_S=OFF; //关闭时十位位选
}
}
/***************************************
函 数 名:min_tiao
功 能:分调整
说 明:
入口参数:无
返 回 值:无
***************************************/
void min_tiao()
{
while(!M_KEY) display(); //等待分调整键松开
second=0;minute++; //秒清零、分加1
if(minute==60) minute=0; //如果分等于60,分变0
}
/***************************************
函 数 名:hou_tiao
功 能:时调整
说 明:
入口参数:无
返 回 值:无
***************************************/
void hou_tiao()
{
while(!H_KEY) display(); //等待时调整键松开
second=0;hour++; //秒清零,时加1
if(hour==24) hour=0; //如果时等于24,时变0
}
/***************************************
函 数 名:delay
功 能:延时函数
说 明:
入口参数:t:延时时间长短
返 回 值:无
***************************************/
void delay(uchar t)
{
uchar i; //定义变量
for(;t>0;t--) //如果t大于0,t减1(外层循环)
for(i=124;i>0;i--); //i等于124,如果i大于0,i减1
}
/***************************************
函 数 名:timer0
功 能:定时器0中断函数
说 明:
入口参数:无
返 回 值:无
***************************************/
void timer0() interrupt 1 //定时器0(中断1)
{
uchar tim1,tim2; //定义临时变量
TL0=TL0+0XB0;TH0=0X3C; //重装定时器初值
tim1++; //每中断一次tim1加1
if(tim1==10) //中断10(0.5秒)
{
SHAN=!SHAN; //闪烁标志取反
tim1=0;tim2++; //tim1清零,tim2加1
if(tim2==2) //到了1秒
{
tim2=0;second++; //tim2清零,秒加1
if(second==60) //如果秒到60
{
second=0;minute++; //秒变0,分加1
if(minute==60) //如果分到60
{
minute=0;hour++; //分变0,时加1
if(hour==24) hour=0; //如果时到24,时变0
}
}
}
}
}
/***************************************
program end 程序结束
***************************************/
以下是汇编程序
;********************************
;单片机电子钟汇编程序
;MCU:AT89C2051 晶振:12M
;编写:舒新生 日期:2007.11.08
;手机:13073399262QQ:625608148
;********************************
MIAO BIT P1.2 ;秒点位
HOU_S BIT P3.0 ;时十位
HOU_G BIT P3.1 ;时个位
MIN_S BIT P3.2 ;分十位
MIN_G BIT P3.3 ;分个位
H_KEY BIT P3.4 ;时调整键
M_KEY BIT P3.5 ;分调整键
SHAN BIT 0 ;秒点闪烁
LEDBUS EQU P1 ;显示数据总线
SECONDEQU 30H ;秒寄存器
MINUTEEQU31H ;分寄存器
HOUREQU32H ;时寄存器
TIM_1 EQU 33H ;定时器0中断次数
TIM_2 EQU 34H ;定时器0中断次数
;********************************
ORG0000H;程序开始
LJMPINIT
ORG000BH;定时器0中断入口地址
LJMPTIMER0
ORG0030H;程序从30H开始
;********************************
; 单片机初始化
INIT: MOVSECOND, #0 ;秒置0
MOVMINUTE, #0 ;分置0
MOVHOUR,#0 ;开机后显示0点
MOVTIM_1,#10 ;中断10次为0.5秒
MOVTIM_2,#2 ;0.5*2=1秒
MOVSP,#60H ;堆栈指针指向60H
MOVTMOD,#01H ;定时器0为模式1(16位)
MOVTH0,#03CH
MOVTL0,#0B0H ;50毫秒初值(晶振12M)
SETB ET0;定时器0中断允许
SETBTR0;启动定时器0
SETB EA;开总中断
;********************************
; 主程序
MAIN: JNBH_KEY,HT ;时调整键按下转到HT
JNBM_KEY,MT ;分调整键按下转到MT
ACALLDISP;调用显示子程序
AJMPMAIN;转LOOP继续检测按键状态
;********************************
; 时间调整
;-----分调整-----------------
MT: ACALLDISP;调用显示子程序
JNBM_KEY,MT ;判断按键是否松开
INCMINUTE;分加一
MOVA,MINUTE
CJNEA,#60,MAIN ;判断分是否加到60
MOVMINUTE, #0 ;分到60变为0
MOV SECOND, #0 ;秒置0
AJMPMAIN
;-----时调整-----------------
HT: ACALLDISP;调用显示子程序
JNBH_KEY,HT ;判断按键是否松开
INCHOUR;时加1
MOVA,HOUR
CJNEA,#24,MAIN
MOVHOUR,#0 ;判断时是否到24,时到24变0
AJMPMAIN
;********************************
; 显示子程序
DISP: MOVDPTR,#LEDTAB ;数码管段码表首地址送DPTR
MOVA,MINUTE;分放入ACC
MOVB,#10 ;B放入10
DIVAB;A/B,商在A余数在B
MOVC A,@A+DPTR ;查表取分十位段码
MOVLEDBUS, A ;段码送LEDBUS口显示
MOV C, SHAN
MOV MIAO, C ;秒点闪烁
CLRMIN_S;打开分十位显示
ACALLD1MS;延时1毫秒
SETBMIN_S;关闭分十位显示
MOVA,B
MOVCA,@A+DPTR ;查表取分个位段码
MOVLEDBUS, A
MOV C, SHAN
MOV MIAO, C ;秒点闪烁
CLRMIN_G;打开分个位显示
ACALLD1MS;延时1毫秒
SETBMIN_G;关闭分十位显示
MOVA,HOUR
MOVB,#10
DIVAB;拆分小时的十位和个位
JZ DISP0;十位为0不显示十位
MOVCA,@A+DPTR
MOVLEDBUS, A
CLRHOU_S;打开时十位显示
DISP0: ACALLD1MS
SETBHOU_S;关闭时十位显示
MOVA,B
MOVCA,@A+DPTR
MOV LEDBUS, A
CLRHOU_G;打开时个位显示
ACALLD1MS
SETBHOU_G;关闭时个位显示
MOV P1, #0FFH
RET
;********************************
; 定时器0中断服务程序
TIMER0: PUSHACC;入栈保护ACC和PSW
PUSHPSW
MOVA,#0B1H ;定时器0中断服务子程序
ADDA,TL0 ;同步修正(参考本人的<如何是自制的单片机电子钟走时精准>)
MOVTL0,A
MOVTH0,#03CH ;重装定时器0初值
DJNZTIM_1,RETI_1
MOVTIM_1,#10 ;中断10次为0.5秒
CPLSHAN;取反闪烁位
DJNZTIM_2,RETI_1
MOVTIM_2,#2 ;1秒时间到
INCSECOND;秒加1
MOVA,SECOND
CJNEA,#60,RETI_1
MOVSECOND, #0 ;秒到60变0
INCMINUTE;分加1
MOVA,MINUTE
CJNEA,#60,RETI_1
MOVMINUTE, #0 ;分到60变0
INCHOUR;时加1
MOVA,HOUR
CJNEA,#24,RETI_1
MOVHOUR,#0 ;时到24变0
RETI_1: POPPSW;出栈
POPACC
RETI
;********************************
; 延时子程序
D1MS: MOVR7,#2 ;延时1毫秒子程序
D_1: MOVR6,#250 ;延时时间估算250*2*2=1000微秒=1毫秒
DJNZR6,$
DJNZR7,D_1
RET
;********************************
; 数码管段码表
LEDTAB: DB14H,0D7H,4CH,45H,87H
; 0 1 23 4
DB 25H,024H,57H,04H,05H
; 5 6 78 9
END