SJMP STAR1循环显示中断服务程序INT_Timer0:
MOV TL0,#176-550ms定时器计数器初始值再装入(-5为微调,含响应中断用时) MOV TH0,#60 PUSH 01H压入堆栈 MOV R1,#ms50装入50ms计数内存地址数31H INC @R150ms计数内存加1
CJNE @R1,#20,ExitInt不够1秒,退出 MOV @R1,#050ms计数内存复位为0(31H)
INC R1转为秒内存地址(32H)
INC @R1秒计数内存加1 CJNE @R1,#60,ExitInt1不够60秒,退出 MOV @R1,#0够60秒,秒计数复位为0 INC R1转为分计数内存地址(33H)
INC @R1 分计数内存加1 CJNE @R1,#60,ExitInt1不够60分,退出 MOV @R1,#0够60分,分复位为0 INC R1转为时内存地址(34H) INC @R1 时计数内存加1 CJNE @R1,#24,ExitInt1不够24时,退出 MOV @R1,#0时计数内存复位为0ExitInt1:
SETB F0置位中断处理完成标志ExitInt:
POP 01H恢复现场 RETI 退出中断
HexToBCD:16进制转BCD码
MOV B,#10 DIV AB MOV @R0,B存余数(10进制个位) INC R0转伤地址 MOV @R0,A存伤(10进制十位) INC R0转下一次余数地址 RET
Display:显示转换与调用显示程序
MOV R0,#buffer10进制BCD秒显示缓存地址(35H) MOV A,sec ACALL HexToBCD十进制秒转换后存在(35H)、(36H) MOV @R0,#10H(37H)=#10H,秒与分之间的间隔,无实际意义,或与dispaly8有关
INC R010进制BCD分显示缓存地址(38H)
MOV A,min ACALL HexToBCD十进制分转换后存在(38H)、(39H)
MOV @R0,#10H(3AH)=#10H,分与时之间的间隔,无实际意义,或与dispaly8有关
INC R010进制BCD时显示缓存地址(3BH)
MOV A,hour ACALL HexToBCD十进制时转换后存在(3CH)、(3DH)
MOV R0,#buffer恢复显示缓存地址(35H),为dispaly8置初始显示地址 LCALL Display8调用实际显示程序 RET END
A方案--------------------------
外加一颗时钟芯片DS1302(非常准确)。
按键为单片机中断。
--------------------------
1、上电时自动显示时、分、秒;
实现方式:上电时单片机去启动DS1202,然后读取里面的时间值,自动显示时、分、秒;
2、设置一个控制按键,按下按键,则时钟以秒为单位开始计时;
实现方式:将DS1302此时的值暂时保存,最为计时开始的时间。
然后不停地读取DS1302里的新的时间值,
并将新的时间值 - 计时开始的时间 = 已计时数值
3、运行状态下可通过控制按键使时钟暂停,同时显示已计时数值;
实现方式:显示步骤2里的已计时数值。
4、停止状态下(已上电),按下复位按钮,时钟复位(清零),并进入下一次计时状态。
实现方式:计时开始的时间换成当前时间。
B方案
--------------------------
采用单片机内部定时器计时(不准)。
按键为单片机中断。
--------------------------
步骤类似,不用去读DS1302的时间,读自己内部的时间。
-------------------------------------------------------------------------------------------------------------------------------------------------------分割线。--------------------------------------------------------------------------
楼上的方案是当前比较常见的方案了。
没有给出程序
先给出A 方案程序如下。。。。//C语言编写。
*头文件*/
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define nop() _nop_()
sbit T_CLK = P1^4 /*实时时钟时钟线引脚 */
sbit T_IO = P1^5 /*实时时钟数据线引脚 */
sbit T_RST = P2^2 /*实时时钟复位线引脚 */
sbit ACC0 = ACC^0
sbit ACC7 = ACC^7
sbit time_en_port = P3^7/*时间控制通道寄存器LE控制脚*/
sbit sled_en_port = P3^6/*数码管控制通道寄存器LE控制脚*/
#define sled_dm_port P0 /*定义数码管段码的控制脚*/
#define sled_wm_port P2/*定义数码管位码的控制脚*/
/*定义数码管显示字符跟数字的对应数组关系*/
uchar code mun_to_char[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}
/* 0123456789abcdef */
/*定义需要点亮的数码管*/
uchar code sled_bit_table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}
uchar data sled_data[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}/*0-7号SLED缓冲值*/
uchar data led_lighten_bit=0 /*LED灯点亮标志位0-7*/
uchar data time_data[8]={0x00,0x57,0x16,0x00,0x00,0x00,0x00,0x00}/*格式为: 秒 分 时 日 月 星期 年 */
/*-----------------------------------------------
显示部分程序,采用定时器0产生中断,1MS更新一次
------------------------------------------------*/
void SLED_Disp() interrupt 1 using 3
{
TH0 = (65536-1000)/256
TL0 = (65536-1000)/256
time_en_port = 0/*关闭时钟控制通道*/
sled_wm_port = sled_bit_table[led_lighten_bit]/*输出位码数据到数码管*/
sled_dm_port = sled_data[led_lighten_bit]/*输出段码数据到数码管*/
sled_en_port = 1/*打开数码管控制通道*/
sled_en_port = 0/*关闭数码管控制通道*/
sled_wm_port = 0xdf/* 释放P2端口,同时关闭发光二极管显示*/
time_en_port = 1/*打开时钟控制通道*/
led_lighten_bit++
if(led_lighten_bit>=8) led_lighten_bit=0/*8位数码管全动态输出*/
}
void T0_valueSet() /*定义中断方式,中断时间*/
{
TMOD = 0x01 /*定时0,工作在方式1*/
TH0 = (65536-1000)/256
TL0 = (65536-1000)/256
TR0 = 1/*启动计数*/
EA = 1/*开总中断*/
ET0 = 1/*开定时器0中断*/
return
}
/********************************************************************
函 数 名:RTInputByte()
功能:实时时钟写入一字节
说明:往DS1302写入1Byte数据 (内部函数)
入口参数:d 写入的数据
返 回 值:无
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
void RTInputByte(uchar d)
{
uchar i
ACC = d
for(i=8i>0i--)
{
T_IO = ACC0 /*相当于汇编中的 RRC */
T_CLK = 1
T_CLK = 0
ACC = ACC >>1
}
}
/********************************************************************
函 数 名:RTOutputByte()
功能:实时时钟读取一字节
说明:从DS1302读取1Byte数据 (内部函数)
入口参数:无
返 回 值:ACC
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
uchar RTOutputByte(void)
{
uchar i
for(i=8i>0i--)
{
ACC = ACC >>1/*相当于汇编中的 RRC */
ACC7 = T_IO
T_CLK = 1
T_CLK = 0
}
return(ACC)
}
/********************************************************************
函 数 名:W1302()
功能:往DS1302写入数据
说明:先写地址,后写命令/数据 (内部函数)
调用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
void W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0
T_CLK = 0
T_RST = 1
RTInputByte(ucAddr) /* 地址,命令 */
RTInputByte(ucDa) /* 写1Byte数据*/
T_CLK = 1
T_RST = 0
}
/********************************************************************
函 数 名:R1302()
功能:读取DS1302某地址的数据
说明:先写地址,后读命令/数据 (内部函数)
调用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址
返 回 值:ucData :读取的数据
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
uchar R1302(uchar ucAddr)
{
uchar ucData
T_RST = 0
T_CLK = 0
T_RST = 1
RTInputByte(ucAddr)/* 地址,命令 */
ucData = RTOutputByte()/* 读1Byte数据 */
T_CLK = 1
T_RST = 0
return(ucData)
}
/********************************************************************
函 数 名:BurstW1302T()
功能:往DS1302写入时钟数据(多字节方式)
说明:先写地址,后写命令/数据
调用:RTInputByte()
入口参数:pWClock: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年 控制
8Byte (BCD码)1B 1B 1B 1B 1B 1B 1B 1B
返 回 值:无
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
void BurstW1302T(uchar *pWClock)
{
uchar i
W1302(0x8e,0x00)/* 控制命令,WP=0,写 *** 作?*/
T_RST = 0
T_CLK = 0
T_RST = 1
RTInputByte(0xbe) /* 0xbe:时钟多字节写命令 */
for (i = 8i>0i--) /*8Byte = 7Byte 时钟数据 + 1Byte 控制*/
{
RTInputByte(*pWClock)/* 写1Byte数据*/
pWClock++
}
T_CLK = 1
T_RST = 0
}
/********************************************************************
函 数 名:BurstR1302T()
功能:读取DS1302时钟数据
说明:先写地址/命令,后读数据(时钟多字节方式)
调用:RTInputByte() , RTOutputByte()
入口参数:pRClock: 读取时钟数据地址 格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B
返 回 值:无
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
void BurstR1302T(uchar *pRClock)
{
uchar i
T_RST = 0
T_CLK = 0
T_RST = 1
RTInputByte(0xbf)/* 0xbf:时钟多字节读命令 */
for (i=8i>0i--)
{
*pRClock = RTOutputByte() /* 读1Byte数据 */
pRClock++
}
T_CLK = 1
T_RST = 0
}
/********************************************************************
函 数 名:Set1302()
功能:设置初始时间
说明:先写地址,后读命令/数据(寄存器多字节方式)
调用:W1302()
入口参数:pClock: 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B
返 回 值:无
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
void Set1302(uchar *pClock)
{
uchar i
uchar ucAddr = 0x80
EA = 0
W1302(0x8e,0x00) /* 控制命令,WP=0,写 *** 作?*/
for(i =7i>0i--)
{
W1302(ucAddr,*pClock) /* 秒 分 时 日 月 星期 年 */
pClock++
ucAddr +=2
}
W1302(0x8e,0x80) /* 控制命令,WP=1,写保护?*/
EA = 1
}
/********************************************************************
函 数 名:Get1302()
功能:读取DS1302当前时间
说明:
调用:R1302()
入口参数:ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
返 回 值:无
设计:zhaojunjie 日期:2002-03-19
修改: 日期:
***********************************************************************/
void Get1302(uchar ucCurtime[])
{
uchar i
uchar ucAddr = 0x81
EA = 0
for (i=0i<7i++)
{
ucCurtime[i] = R1302(ucAddr)/*格式为: 秒 分 时 日 月 星期 年 */
ucAddr += 2
}
EA = 1
}
void delay_1ms(uchar x)
/* 1MS为单位的延时程序 */
{
uchar j
while(x--){
for(j=0j<125j++)
{}
}
}
void main()
{
T0_valueSet()
Set1302(time_data)
while(1){
Get1302(time_data)
sled_data[0]=mun_to_char[time_data[2]/0x10]
sled_data[1]=mun_to_char[time_data[2]%0x10]
sled_data[3]=mun_to_char[time_data[1]/0x10]
sled_data[4]=mun_to_char[time_data[1]%0x10]
sled_data[6]=mun_to_char[time_data[0]/0x10]
sled_data[7]=mun_to_char[time_data[0]%0x10]
delay_1ms(200)
}
}
方案B.
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6
sbit wela=P2^7
sbit rs=P3^5
sbit lcden=P3^4
sbit s1=P3^0
sbit s2=P3^1
sbit s3=P3^2
sbit rd=P3^7
uchar count,s1num
char miao,shi,fen
uchar code table[]=" 2007-7-30 MON"
uchar code table1[]="00:00:00"
void delay(uint z)
{
uint x,y
for(x=zx>0x--)
for(y=110y>0y--)
}
void write_com(uchar com)
{
rs=0
lcden=0
P0=com
delay(5)
lcden=1
delay(5)
lcden=0
}
void write_date(uchar date)
{
rs=1
lcden=0
P0=date
delay(5)
lcden=1
delay(5)
lcden=0
}
void init()
{
uchar num
dula=0
wela=0
lcden=0
// fen=59
// miao=53
// shi=23
write_com(0x38)
write_com(0x0c)
write_com(0x06)
write_com(0x01)
write_com(0x80)
for(num=0num<15num++)
{
write_date(table[num])
delay(5)
}
write_com(0x80+0x40)
for(num=0num<12num++)
{
write_date(table1[num])
delay(5)
}
TMOD=0x01
TH0=(65536-50000)/256
TL0=(65536-50000)%256
EA=1
ET0=1
TR0=1
}
void write_sfm(uchar add,uchar date)
{
uchar shi,ge
shi=date/10
ge=date%10
write_com(0x80+0x40+add)
write_date(0x30+shi)
write_date(0x30+ge)
}
void keyscan()
{
rd=0
if(s1==0)
{
delay(5)
if(s1==0)
{ s1num++
while(!s1)
if(s1num==1)
{
TR0=0
write_com(0x80+0x40+10)
write_com(0x0f)
}
}
if(s1num==2)
{
write_com(0x80+0x40+7)
}
if(s1num==3)
{
write_com(0x80+0x40+4)
}
if(s1num==4)
{
s1num=0
write_com(0x0c)
TR0=1
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(5)
if(s2==0)
{
while(!s2)
if(s1num==1)
{
miao++
if(miao==60)
miao=0
write_sfm(10,miao)
write_com(0x80+0x40+10)
}
if(s1num==2)
{
fen++
if(fen==60)
fen=0
write_sfm(7,fen)
write_com(0x80+0x40+7)
}
if(s1num==3)
{
shi++
if(shi==24)
shi=0
write_sfm(4,shi)
write_com(0x80+0x40+4)
}
}
}
if(s3==0)
{
delay(5)
if(s3==0)
{
while(!s3)
if(s1num==1)
{
/* if(miao==0)
{
miao=59
write_sfm(10,miao)
write_com(0x80+0x40+10)
}*/
miao--
if(miao==-1)
miao=59
write_sfm(10,miao)
write_com(0x80+0x40+10)
}
if(s1num==2)
{
fen--
if(fen==-1)
fen=59
write_sfm(7,fen)
write_com(0x80+0x40+7)
}
if(s1num==3)
{
shi--
if(shi==-1)
shi=23
write_sfm(4,shi)
write_com(0x80+0x40+4)
}
}
}
}
}
void main()
{
init()
while(1)
{
keyscan()
}
// while(1)
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256
TL0=(65536-50000)%256
count++
if(count==18)
{
count=0
miao++
if(miao==60)
{
miao=0
fen++
if(fen==60)
{
fen=0
shi++
if(shi==24)
{
shi=0
}
write_sfm(4,shi)
}
write_sfm(7,fen)
}
write_sfm(10,miao)
}
}
以上的程序都是用C编写 如果是初学还是直接用C编写吧 虽然汇编也很好用 但是C已经是时代的趋势了。。
如果以上能帮到你 请给分哦。。 有什么不懂得也可以问我。
这个电子钟程序已经基本符合你的要求。希望能对你有用。程序说明:
显示的时间格式为:12-00-00,既,时-分-秒
按键说明:P3.2为时调节。P3.3为分调节。P3.4为秒调节。这三个按键均是每按一次加一。
晶振说明:12MHZ
数码管说明:共阳数码管。共8个数码管。共用了两个4连共阳数码管。
其中,P0口为数码管的段选,P2口为数码管的位选。
本程序已通过实践验证!!!
汇编源程序如下:
SECOND EQU 30H
MINITE EQU 31H
HOUREQU 32H
HOURK BIT P3.2
MINITEK BIT P3.3
SECONDK BIT P3.4
DISPBUF EQU 40H
DISPBIT EQU 48H
T2SCNTA EQU 49H
T2SCNTB EQU 4AH
TEMPEQU 4BH
ORG 00H
LJMP START
ORG 0BH
LJMP INT_T0
START:MOV SECOND,#00H
MOV MINITE,#00H
MOV HOUR,#12
MOV DISPBIT,#00H
MOV T2SCNTA,#00H
MOV T2SCNTB,#00H
MOV TEMP,#0FEH
LCALL DISP
MOV TMOD,#01H
MOV TH0,#(65536-2000) / 256
MOV TL0,#(65536-2000) MOD 256
SETB TR0
SETB ET0
SETB EA
WT:JB SECONDK,NK1
LCALL DELY10MS
JB SECONDK,NK1
INC SECOND
MOV A,SECOND
CJNE A,#60,NS60
MOV SECOND,#00H
NS60:LCALL DISP
JNB SECONDK,$
NK1:JB MINITEK,NK2
LCALL DELY10MS
JB MINITEK,NK2
INC MINITE
MOV A,MINITE
CJNE A,#60,NM60
MOV MINITE,#00H
NM60:LCALL DISP
JNB MINITEK,$
NK2:JB HOURK,NK3
LCALL DELY10MS
JB HOURK,NK3
INC HOUR
MOV A,HOUR
CJNE A,#24,NH24
MOV HOUR,#00H
NH24:LCALL DISP
JNB HOURK,$
NK3:LJMP WT
DELY10MS:MOV R6,#10
D1:MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
DISP:MOV A,#DISPBUF
ADD A,#8
DEC A
MOV R1,A
MOV A,HOUR
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV @R1,A
DEC R1
MOV A,MINITE
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV@R1,A
DEC R1
MOV A,SECOND
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
RET
INT_T0:MOV TH0,#(65536-2000) / 256
MOV TL0,#(65536-2000) MOD 256
MOV A,#DISPBUF
ADD A,DISPBIT
MOV R0,A
MOV A,@R0
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P0,A
MOV A,DISPBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P2,A
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,KNA
MOV DISPBIT,#00H
KNA:INC T2SCNTA
MOV A,T2SCNTA
CJNE A,#100,DONE
MOV T2SCNTA,#00H
INC T2SCNTB
MOV A,T2SCNTB
CJNE A,#05H,DONE
MOV T2SCNTB,#00H
INC SECOND
MOV A,SECOND
CJNE A,#60,NEXT
MOV SECOND,#00H
INC MINITE
MOV A,MINITE
CJNE A,#60,NEXT
MOV MINITE,#00H
INC HOUR
MOV A,HOUR
CJNE A,#24,NEXT
MOV HOUR,#00H
NEXT:LCALL DISP
DONE:RETI
TABLE:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0BFH
TAB:DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
END
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)