用这个程序吧 C和汇编都有。
数字钟[★]
1. 实验任务
(1. 开机时,显示12:00:00的时间开始计时;
(2. P00/AD0控制“秒”的调整,每按一次加1秒;
(3. P01/AD1控制“分”的调整,每按一次加1分;
(4. P02/AD2控制“时”的调整,每按一次加1个小时;
2. 电路原理图
图4201
3. 系统板上硬件连线
(1. 把“单片机系统”区域中的P10-P17端口用8芯排线连接到“动态数码显示”区域中的A-H端口上;
(2. 把“单片机系统:区域中的P30-P37端口用8芯排线连接到“动态数码显示”区域中的S1-S8端口上;
(3. 把“单片机系统”区域中的P00/AD0、P01/AD1、P02/AD2端口分别用导线连接到“独立式键盘”区域中的SP3、SP2、SP1端口上;
4. 相关基本知识
(1. 动态数码显示的方法
(2. 独立式按键识别过程
(3. “时”,“分”,“秒”数据送出显示处理方法
5. 程序框图
6. 汇编源程序
SECOND EQU 30H
MINITE EQU 31H
HOUR EQU 32H
HOURK BIT P00
MINITEK BIT P01
SECONDK BIT P02
DISPBUF EQU 40H
DISPBIT EQU 48H
T2SCNTA EQU 49H
T2SCNTB EQU 4AH
TEMP EQU 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 P1,A
MOV A,DISPBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P3,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 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H
TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
END
7. C语言源程序
#include <AT89X51H>
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
unsigned char dispbuf[8]={0,0,16,0,0,16,0,0};
unsigned char dispbitcnt;
unsigned char second;
unsigned char minite;
unsigned char hour;
unsigned int tcnt;
unsigned char mstcnt;
unsigned char i,j;
void main(void)
{
TMOD=0x02;
TH0=0x06;
TL0=0x06;
TR0=1;
ET0=1;
EA=1;
while(1)
{
if(P0_0==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_0==0)
{
second++;
if(second==60)
{
second=0;
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
while(P0_0==0);
}
}
if(P0_1==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_1==0)
{
minite++;
if(minite==60)
{
minite=0;
}
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
while(P0_1==0);
}
}
if(P0_2==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_2==0)
{
hour++;
if(hour==24)
{
hour=0;
}
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
while(P0_2==0);
}
}
}
}
void t0(void) interrupt 1 using 0
{
mstcnt++;
if(mstcnt==8)
{
mstcnt=0;
P1=dispcode[dispbuf[dispbitcnt]];
P3=dispbitcode[dispbitcnt];
dispbitcnt++;
if(dispbitcnt==8)
{
dispbitcnt=0;
}
}
tcnt++;
if(tcnt==4000)
{
tcnt=0;
second++;
if(second==60)
{
second=0;
minite++;
if(minite==60)
{
minite=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
}
}
在8051单片机的时钟频率为6MHz,那么定时器的计数脉冲周期就是 2uS;
sbit CP=P1^0;
void Timer0_init()
{
TMOD |=0x01; //T0定时器,方式1,采用16位定时器
TH0 = (65536-500)/256; //定时器装初值500, 即 1000uS 中断一次
TL0 = (65536-500)%256;
EA=1; ET0=1; TR0=1;
}
void timer0() interrupt 1
{
TH0 = (65536-500)/256; //定时器装初值500, 1mS 中断一次
TL0 = (65536-500)%256;
CP=~CP; //改变脉冲信号的输出状态
}
void main()
{
Timer0_init();
CP=0;
while(1) { }
}
汇编语言,才看到,算了,你别人的回答吧
我给你个,你试试把。
#include<reg52h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrinsh>
sbit SCK=P3^6; //时钟
sbit SDA=P3^4; //数据
sbit RST = P3^5;// DS1302复位
sbit LS138A=P2^2;
sbit LS138B=P2^3;
sbit LS138C=P2^4;
bit ReadRTC_Flag;//定义读DS1302标志
unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00
unsigned char l_tmpdisplay[8];
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位读写位
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
//共阴数码管 0-9 '-' '熄灭‘表
//
/ 函数声明 /
//
void Write_Ds1302_byte(unsigned char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_RTC(void);//read RTC
void Set_RTC(void); //set RTC
void InitTIMER0(void);//inital timer0
//
/ 主函数 /
//
void main(void)
{
InitTIMER0(); //初始化定时器0
Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽
while(1)
{
if(ReadRTC_Flag)
{
ReadRTC_Flag=0;
Read_RTC();
l_tmpdisplay[0]=l_tmpdate[2]/16; //数据的转换,因我们采用数码管0~9的显示,将数据分开
l_tmpdisplay[1]=l_tmpdate[2]&0x0f;
l_tmpdisplay[2]=10; //加入"-"
l_tmpdisplay[3]=l_tmpdate[1]/16;
l_tmpdisplay[4]=l_tmpdate[1]&0x0f;
l_tmpdisplay[5]=10;
l_tmpdisplay[6]=l_tmpdate[0]/16;
l_tmpdisplay[7]=l_tmpdate[0]&0x0f;
}
}
}
//
/ 定时器0初始化 /
//
void InitTIMER0(void)
{
TMOD|=0x01;//定时器设置 16位
TH0=0xef;//初始化值
TL0=0xf0;
ET0=1;
TR0=1;
EA=1;
}
//
/ 写一个字节 /
//
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCK=0;
SDA=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
SCK=1;
}
}
//
/ 写入DS1302 /
//
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_(); //启动
Write_Ds1302_Byte(address); //发送地址
Write_Ds1302_Byte(dat); //发送数据
RST=0; //恢复
}
//
/ 读出DS1302数据 /
//
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80; //每次传输低字节
SCK=0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
RST=0;
_nop_(); //以下为DS1302复位的稳定时间
_nop_();
RST=0;
SCK=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCK=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
return (temp); //返回
}
//
/ 读时钟数据 /
//
void Read_RTC(void) //读取 日历
{
unsigned char i,p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++) //分7次读取 秒分时日月周年
{
l_tmpdate[i]=Read_Ds1302(p);
p++;
}
}
//
/ 设定时钟数据 /
//
void Set_RTC(void) //设定 日历
{
unsigned char i,p,tmp;
for(i=0;i<7;i++){ //BCD处理
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp16;
}
Write_Ds1302(0x8E,0X00);
p=write_rtc_address; //传地址
for(i=0;i<7;i++) //7次写入 秒分时日月周年
{
Write_Ds1302(p,l_tmpdate[i]);
p++;
}
Write_Ds1302(0x8E,0x80);
}
//
/ 定时器中断函数 /
//
void tim(void) interrupt 1 using 1
//中断,用于数码管扫描
{
static unsigned char i,num;
TH0=0xf5;
TL0=0xe0;
P0=table[l_tmpdisplay[i]]; //查表法得到要显示数字的数码段
switch(i)
{
case 0:LS138A=0; LS138B=0; LS138C=0; break;
case 1:LS138A=1; LS138B=0; LS138C=0; break;
case 2:LS138A=0; LS138B=1; LS138C=0; break;
case 3:LS138A=1; LS138B=1; LS138C=0; break;
case 4:LS138A=0; LS138B=0; LS138C=1; break;
case 5:LS138A=1; LS138B=0; LS138C=1; break;
case 6:LS138A=0; LS138B=1; LS138C=1; break;
case 7:LS138A=1; LS138B=1; LS138C=1; break;
}
i++;
if(i==8)
{
i=0;
num++;
if(10==num) //隔段时间读取1302的数据。时间间隔可以调整
{
ReadRTC_Flag=1; //使用标志位判断
num=0;
}
}
}
你好这是基于DS1302日历时钟的单片机汇编程序 51单片机
ORG 0000H
MOV SP,#30H
LOAD EQU P20
CLR LOAD
MOV R0,#0FH
MOV R1,#0AH ;亮度
ACALL TRT
MOV R0,#02H
MOV R1,#0BH ;扫描位数
ACALL TRT
MOV R0,#0FFH
MOV R1,#09H ;译码
ACALL TRT
MOV R0,#01H
MOV R1,#0CH
CALL TRT
SETB P10
MOV 22H,#00H
;以下为按键扫描输入初值子程序
KEYSET: MOV 73H,#01H ;设温度初值为10度
MOV 74H,#00H
MOV 75H,#00H
CALL DISPLAY
KEY1: CALL KS1 ;调判断有无键按下子程序
JNZ LK1 ;有键按下(A)<>0转消抖延时
AJMP KEY1 ;无键按下返回,等键按下
LK1: CALL DEL10MS ;延时
CALL KS1 ;若有键按下则为真实按下
JNZ KEYI ;键按下(A)<>0转键扫描
AJMP KEY1 ;不是键按下返回
KEYI: JNB ACC0,KEYR ;加1键未按下,转查减1键
LK2: CALL KS1 ;等待键释放
CALL DEL10MS
JNZ LK2 ;未释放,等待
INC 75H ;末位加1
MOV A,75H
CJNE A,#0AH,PPA
MOV 75H,#00H
INC 74H
MOV A,74H
CJNE A,#0AH,PPA
MOV 74H,#00H
INC 73H
PPA: CALL DISPLAY
AJMP KEY1 ;转再次扫描
KEYR: JNB ACC1,KEYH ;减1键未按下,转查上限确认键
LK3: CALL KS1
CALL DEL10MS
JNZ LK3
MOV A,75H
CJNE A,#00H,PPC
MOV 75H,#09H
MOV A,74H
CJNE A,#00H,PPD
MOV 74H,#09H
DEC 73H
AJMP PPB
PPD: DEC 74H
AJMP PPB
PPC: DEC 75H
PPB: CALL DISPLAY
AJMP KEY1 ;再次扫描
KEYH: JNB ACC2,KEYL ;上限键未按下,转查下限确认键
LK4: CALL KS1
CALL DEL10MS
JNZ LK4
MOV A,73H
MOV 70H,A ;保存上限
MOV A,74H
MOV 71H,A
MOV A,75H
MOV 72H,A
AJMP KEY1
;KEYL: JNB ACC3,KEY1
LK5: CALL KS1
CALL DEL10MS
JNZ LK5
MOV A,73H
MOV 6DH,A ;保存下限
MOV A,74H
MOV 6EH,A
MOV A,75H
MOV 6FH,A
EX_CON: ;CPL P13 ;使用仪器测试时用
CALL DS18B20 ;转DS18B20采样子程序
CALL DISPLAY
;以下为后向通道控制部分
CONTROL:MOV A,73H
CJNE A,6DH,NEQA
MOV A,74H
CJNE A,6EH,NEQB
CLR P15
CLR P16
JMP EX_CON ;样温=下限,返回采样
NEQA: JNC NEQD ;CY=0,即(73H)>(6DH)时转比上限
SETB P15
CLR P16
JMP EX_CON
NEQB: JNC NEQD
SETB P15
CLR P16
JMP EX_CON
NEQD: MOV A,73H
CJNE A,70H,NEQE
MOV A,74H
CJNE A,71H,NEQF
CLR P15
CLR P16
JMP EX_CON ;样温=上限,返回采样
NEQE: JNC NEQH ;CY=0,即(73H)>(70H)时转打开降温开关
CLR P15
CLR P16
JMP EX_CON
NEQF: JNC NEQH
CLR P15
CLR P16
JMP EX_CON
NEQH: CLR P15
SETB P16
JMP EX_CON
KS1: MOV P0,#0FFH
MOV A,P0
CPL A
ANL A,#0FH
RET
DEL10MS:MOV R7,#20
S2: MOV R6,#250
S1: DJNZ R6,S1
DJNZ R7,S2
RET
;以下为显示
DISPLAY:MOV A,73H ;字码
MOV R0,A
MOV R1,#01H ;位置
ACALL TRT
MOV A,74H
MOV R0, A
MOV R1,#02H
ACALL TRT
MOV A,75H
MOV R0,A
MOV R1,#03H
ACALL TRT
RET
;JMP DIS
DS18B20:LCALL RESET ;测试温度探头存在否
MOV A,#0CCH
LCALL WRITE
MOV A,#44H
LCALL WRITE ;命令字写入探头内
MOV R7,#70D ;延时
CALL DE11
LCALL RESET
MOV A,#0CCH
LCALL WRITE
MOV A,#0BEH
LCALL WRITE
LCALL READ ;读取探头内的温度值
MOV B,A
MOV 21H,A ;保存温度值低位
LCALL READ
MOV 20H,A ;保存温度值高位
LCALL EXCHANG ;温度值B转D并送入显示缓存
RET
RESET:
LA: SETB P10 ;复位
NOP
LB: CLR P10 ;480US < TS < 960US
MOV R7,#36D
CALL DE11
SETB P10 ;60US < T <90US
LC: MOV R7,#6D
CALL DE11
CLR C
ORL C,P10
JC LB
LF: MOV R7,#18D ;T > 270
CALL DE11
SETB P10
RET
WRITE:
MOV R3,#8
WR1: SETB P10
CLR P10 ;延时
MOV R4,#2
WR2: DJNZ R4,WR2
RRC A
MOV P10,C ;写的数据在线上需延时
MOV R4,#18
WR3: DJNZ R4,WR3
NOP
SETB P10
DJNZ R3,WR1
SETB P10
RET
READ:
MOV R3,#8
RD1: CLR C
SETB P10 ;适当延时
NOP
NOP
CLR P10 ;适当延时
NOP
NOP
SETB P10 ;延时
MOV R4,#9
RD2: DJNZ R4,RD2
MOV C,P10
RRC A
MOV R5,#23
RD3: DJNZ R5,RD3
DJNZ R3,RD1
RET
DELAY: MOV R7,#10
DL2: MOV R6,#200
DL1: MOV R5,#250
DL0: DJNZ R5,DL0
DJNZ R6,DL1
DJNZ R7,DL2
RET
EXCHANG: MOV A,21H
SWAP A
ANL A,#0FH
MOV 24H,A
MOV A,20H
ANL A,#07H
SWAP A
ADD A,24H
MOV B,#10D
DIV AB
MOV 73H,A
MOV 74H,B
MOV A,21H
ANL A,#0FH
mov dptr,#SADDR ;小数部分的转换查表
movc a,@a+dptr
MOV 75H,A
ret
SADDR: DB 00H,1H,02h ; bo_ying address in eeprom 0800h-0A08H
DB 03H,3H,04h ; da_ling address in eeprom 0A10H-0AD3H
DB 04H,05H,06h ;shou_ying address in eeprom 0AE0H-0C25H
DB 06H,7H,08h ; lu_ying address in eeprom 0C30H-0D75H
DB 08H,9H,9h,9H
DELAY15US: ;12MHZ ,15US
DE11: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DJNZ R7,DE11
RET
TRT: CLR P20 ;LOAD
MOV R2,#08H
MOV A,R1
T_1: CLR P22 ;SETB P22 ;CLK
RLC A
MOV P21,C ;DATA
CALL TDELAY
SETB P22 ;CLR P22
DJNZ R2,T_1
CALL TDELAY
MOV R2, #08H
MOV A,R0
TT2: CLR P22 ;SETB P22
RLC A
MOV P21,C
CALL TDELAY
SETB P22 ;CLR P22
DJNZ R2,TT2
SETB P20 ;CLR P20
RET
TDELAY: MOV R6,#01H
TMS0: MOV R7,#03H
TMS1: DJNZ R7,TMS1
DJNZ R6,TMS0
RET
以上就是关于用单片机制作可调数字时钟要汇编语言程序的全部的内容,包括:用单片机制作可调数字时钟要汇编语言程序的、51单片机编程题,用汇编语言怎么做、51单片机时钟程序,C语言,汇编都行等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)