用单片机制作可调数字时钟要汇编语言程序的

用单片机制作可调数字时钟要汇编语言程序的,第1张

用这个程序吧 C和汇编都有。

数字钟[★]

1. 实验任务

(1. 开机时,显示12:00:00的时间开始计时;

(2. P0.0/AD0控制“秒”的调整,每按一次加1秒;

(3. P0.1/AD1控制“分”的调整,每按一次加1分;

(4. P0.2/AD2控制“时”的调整,每按一次加1个小时;

2. 电路原理图

图4.20.1

3. 系统板上硬件连线

(1. 把“单片机系统”区域中的P1.0-P1.7端口用8芯排线连接到“动态数码显示”区域中的A-H端口上;

(2. 把“单片机系统:区域中的P3.0-P3.7端口用8芯排线连接到“动态数码显示”区域中的S1-S8端口上;

(3. 把“单片机系统”区域中的P0.0/AD0、P0.1/AD1、P0.2/AD2端口分别用导线连接到“独立式键盘”区域中的SP3、SP2、SP1端口上;

4. 相关基本知识

(1. 动态数码显示的方法

(2. 独立式按键识别过程

(3. “时”,“分”,“秒”数据送出显示处理方法

5. 程序框图

6. 汇编源程序

SECOND EQU 30H

MINITEEQU 31H

HOUR EQU 32H

HOURKBIT P0.0

MINITEK BIT P0.1

SECONDK BIT P0.2

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 <AT89X51.H>

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=5i>0i--)

for(j=248j>0j--)

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=5i>0i--)

for(j=248j>0j--)

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=5i>0i--)

for(j=248j>0j--)

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

}

}

基于DS1302的日历时钟

#include<reg51.h>//包含单片机寄存器的头文件

#include<intrins.h> //包含_nop_()函数定义的头文件

/***********************************************************************

以下是DS1302芯片的 *** 作程序

************************************************************************/

unsigned char code digit[10]={"0123456789"} //定义字符数组显示数字

sbit DATA=P1^1 //位定义1302芯片的接口,数据输出端定义在P1.1引脚

sbit RST=P1^2 //位定义1302芯片的接口,复位端口定义在P1.1引脚

sbit SCLK=P1^0 //位定义1302芯片的接口,时钟输出端口定义在P1.1引脚

/*****************************************************

函数功能:延时若干微秒

入口参数:n

***************************************************/

void delaynus(unsigned char n)

{

unsigned char i

for(i=0i<ni++)

}

/*****************************************************

函数功能:向1302写一个字节数据

入口参数:x

***************************************************/

void Write1302(unsigned char dat)

{

unsigned char i

SCLK=0 //拉低SCLK,为脉冲上升沿写入数据做好准备

delaynus(2) //稍微等待,使硬件做好准备

for(i=0i<8i++) //连续写8个二进制位数据

{

DATA=dat&0x01 //取出dat的第0位数据写入1302

delaynus(2) //稍微等待,使硬件做好准备

SCLK=1 //上升沿写入数据

delaynus(2) //稍微等待,使硬件做好准备

SCLK=0 //重新拉低SCLK,形成脉冲

dat>>=1 //将dat的各数据位右移1位,准备写入下一个数据位

}

}

/*****************************************************

函数功能:根据命令字,向1302写一个字节数据

入口参数:Cmd,储存命令字;dat,储存待写的数据

***************************************************/

void WriteSet1302(unsigned char Cmd,unsigned char dat)

{

RST=0 //禁止数据传递

SCLK=0 //确保写数居前SCLK被拉低

RST=1 //启动数据传输

delaynus(2)//稍微等待,使硬件做好准备

Write1302(Cmd) //写入命令字

Write1302(dat) //写数据

SCLK=1 //将时钟电平置于已知状态

RST=0 //禁止数据传递

}

/*****************************************************

函数功能:从1302读一个字节数据

入口参数:x

***************************************************/

unsigned char Read1302(void)

{

unsigned char i,dat

delaynus(2) //稍微等待,使硬件做好准备

for(i=0i<8i++) //连续读8个二进制位数据

{

dat>>=1 //将dat的各数据位右移1位,因为先读出的是字节的最低位

if(DATA==1)//如果读出的数据是1

dat|=0x80 //将1取出,写在dat的最高位

SCLK=1 //将SCLK置于高电平,为下降沿读出

delaynus(2) //稍微等待

SCLK=0 //拉低SCLK,形成脉冲下降沿

delaynus(2) //稍微等待

}

return dat //将读出的数据返回

}

/*****************************************************

函数功能:根据命令字,从1302读取一个字节数据

入口参数:Cmd

***************************************************/

unsigned char ReadSet1302(unsigned char Cmd)

{

unsigned char dat

RST=0//拉低RST

SCLK=0 //确保写数居前SCLK被拉低

RST=1//启动数据传输

Write1302(Cmd) //写入命令字

dat=Read1302() //读出数据

SCLK=1 //将时钟电平置于已知状态

RST=0 //禁止数据传递

return dat //将读出的数据返回

}

/*****************************************************

函数功能: 1302进行初始化设置

***************************************************/

void Init_DS1302(void)

{

WriteSet1302(0x8E,0x00)//根据写状态寄存器命令字,写入不保护指令

WriteSet1302(0x80,((0/10)<<4|(0%10))) //根据写秒寄存器命令字,写入秒的初始值

WriteSet1302(0x82,((0/10)<<4|(0%10))) //根据写分寄存器命令字,写入分的初始值

WriteSet1302(0x84,((12/10)<<4|(12%10)))//根据写小时寄存器命令字,写入小时的初始值

WriteSet1302(0x86,((16/10)<<4|(16%10)))//根据写日寄存器命令字,写入日的初始值

WriteSet1302(0x88,((11/10)<<4|(11%10)))//根据写月寄存器命令字,写入月的初始值

WriteSet1302(0x8c,((8/10)<<4|(8%10))) //根据写小时寄存器命令字,写入小时的初始值

}

/*******************************************************************************

以下是对液晶模块的 *** 作程序

*******************************************************************************/

sbit RS=P2^0 //寄存器选择位,将RS位定义为P2.0引脚

sbit RW=P2^1 //读写选择位,将RW位定义为P2.1引脚

sbit E=P2^2 //使能信号位,将E位定义为P2.2引脚

sbit BF=P0^7 //忙碌标志位,,将BF位定义为P0.7引脚

/*****************************************************

函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒

***************************************************/

void delay1ms()

{

unsigned char i,j

for(i=0i<10i++)

for(j=0j<33j++)

}

/*****************************************************

函数功能:延时若干毫秒

入口参数:n

***************************************************/

void delaynms(unsigned char n)

{

unsigned char i

for(i=0i<ni++)

delay1ms()

}

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:result。result=1,忙碌result=0,不忙

***************************************************/

bit BusyTest(void)

{

bit result

RS=0 //根据规定,RS为低电平,RW为高电平时,可以读状态

RW=1

E=1 //E=1,才允许读写

_nop_() //空 *** 作

_nop_()

_nop_()

_nop_() //空 *** 作四个机器周期,给硬件反应时间

result=BF //将忙碌标志电平赋给result

E=0//将E恢复低电平

return result

}

/*****************************************************

函数功能:将模式设置指令或显示地址写入液晶模块

入口参数:dictate

***************************************************/

void WriteInstruction (unsigned char dictate)

{

while(BusyTest()==1) //如果忙就等待

RS=0 //根据规定,RS和R/W同时为低电平时,可以写入指令

RW=0

E=0 //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E从0到1发生正跳变,所以应先置"0"

_nop_()

_nop_() //空 *** 作两个机器周期,给硬件反应时间

P0=dictate //将数据送入P0口,即写入指令或地址

_nop_()

_nop_()

_nop_()

_nop_() //空 *** 作四个机器周期,给硬件反应时间

E=1 //E置高电平

_nop_()

_nop_()

_nop_()

_nop_() //空 *** 作四个机器周期,给硬件反应时间

E=0 //当E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*****************************************************

函数功能:指定字符显示的实际地址

入口参数:x

***************************************************/

void WriteAddress(unsigned char x)

{

WriteInstruction(x|0x80)//显示位置的确定方法规定为"80H+地址码x"

}

/*****************************************************

函数功能:将数据(字符的标准ASCII码)写入液晶模块

入口参数:y(为字符常量)

***************************************************/

void WriteData(unsigned char y)

{

while(BusyTest()==1)

RS=1 //RS为高电平,RW为低电平时,可以写入数据

RW=0

E=0 //E置低电平(根据表8-6,写指令时,E为高脉冲,

// 就是让E从0到1发生正跳变,所以应先置"0"

P0=y //将数据送入P0口,即将数据写入液晶模块

_nop_()

_nop_()

_nop_()

_nop_() //空 *** 作四个机器周期,给硬件反应时间

E=1 //E置高电平

_nop_()

_nop_()

_nop_()

_nop_() //空 *** 作四个机器周期,给硬件反应时间

E=0 //当E由高电平跳变成低电平时,液晶模块开始执行命令

}

/*****************************************************

函数功能:对LCD的显示模式进行初始化设置

***************************************************/

void LcdInitiate(void)

{

delaynms(15) //延时15ms,首次写指令时应给LCD一段较长的反应时间

WriteInstruction(0x38)//显示模式设置:16×2显示,5×7点阵,8位数据接口

delaynms(5) //延时5ms ,给硬件一点反应时间

WriteInstruction(0x38)

delaynms(5) //延时5ms ,给硬件一点反应时间

WriteInstruction(0x38)//连续三次,确保初始化成功

delaynms(5) //延时5ms ,给硬件一点反应时间

WriteInstruction(0x0c)//显示模式设置:显示开,无光标,光标不闪烁

delaynms(5) //延时5ms ,给硬件一点反应时间

WriteInstruction(0x06)//显示模式设置:光标右移,字符不移

delaynms(5) //延时5ms ,给硬件一点反应时间

WriteInstruction(0x01)//清屏幕指令,将以前的显示内容清除

delaynms(5)//延时5ms ,给硬件一点反应时间

}

/**************************************************************

以下是1302数据的显示程序

**************************************************************/

/*****************************************************

函数功能:显示秒

入口参数:x

***************************************************/

void DisplaySecond(unsigned char x)

{

unsigned char i,j//j,k,l分别储存温度的百位、十位和个位

i=x/10//取十位

j=x%10//取个位

WriteAddress(0x49) //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]) //将百位数字的字符常量写入LCD

WriteData(digit[j]) //将十位数字的字符常量写入LCD

delaynms(50)//延时1ms给硬件一点反应时间

}

/*****************************************************

函数功能:显示分钟

入口参数:x

***************************************************/

void DisplayMinute(unsigned char x)

{

unsigned char i,j//j,k,l分别储存温度的百位、十位和个位

i=x/10//取十位

j=x%10//取个位

WriteAddress(0x46) //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]) //将百位数字的字符常量写入LCD

WriteData(digit[j]) //将十位数字的字符常量写入LCD

delaynms(50)//延时1ms给硬件一点反应时间

}

/*****************************************************

函数功能:显示小时

入口参数:x

***************************************************/

void DisplayHour(unsigned char x)

{

unsigned char i,j//j,k,l分别储存温度的百位、十位和个位

i=x/10//取十位

j=x%10//取个位

WriteAddress(0x43) //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]) //将百位数字的字符常量写入LCD

WriteData(digit[j]) //将十位数字的字符常量写入LCD

delaynms(50)//延时1ms给硬件一点反应时间

}

/*****************************************************

函数功能:显示日

入口参数:x

***************************************************/

void DisplayDay(unsigned char x)

{

unsigned char i,j//j,k,l分别储存温度的百位、十位和个位

i=x/10//取十位

j=x%10//取个位

WriteAddress(0x0c) //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]) //将百位数字的字符常量写入LCD

WriteData(digit[j]) //将十位数字的字符常量写入LCD

delaynms(50)//延时1ms给硬件一点反应时间

}

/*****************************************************

函数功能:显示月

入口参数:x

***************************************************/

void DisplayMonth(unsigned char x)

{

unsigned char i,j//j,k,l分别储存温度的百位、十位和个位

i=x/10//取十位

j=x%10//取个位

WriteAddress(0x09) //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]) //将百位数字的字符常量写入LCD

WriteData(digit[j]) //将十位数字的字符常量写入LCD

delaynms(50)//延时1ms给硬件一点反应时间

}

/*****************************************************

函数功能:显示年

入口参数:x

***************************************************/

void DisplayYear(unsigned char x)

{

unsigned char i,j//j,k,l分别储存温度的百位、十位和个位

i=x/10//取十位

j=x%10//取个位

WriteAddress(0x06) //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]) //将百位数字的字符常量写入LCD

WriteData(digit[j]) //将十位数字的字符常量写入LCD

delaynms(50)//延时1ms给硬件一点反应时间

}

/*****************************************************

函数功能:主函数

***************************************************/

void main(void)

{

unsigned char second,minute,hour,day,month,year //分别储存苗、分、小时,日,月,年

unsigned char ReadValue //储存从1302读取的数据

LcdInitiate()//将液晶初始化

WriteAddress(0x01) //写Date的显示地址,将在第1行第2列开始显示

WriteData('D') //将字符常量写入LCD

WriteData('a') //将字符常量写入LCD

WriteData('t') //将字符常量写入LCD

WriteData('e') //将字符常量写入LCD

WriteData(':') //将字符常量写入LCD

WriteAddress(0x08) //写年月分隔符的显示地址, 显示在第1行第9列

WriteData('-') //将字符常量写入LCD

WriteAddress(0x0b) //写月日分隔符的显示地址, 显示在第1行第12列

WriteData('-') //将字符常量写入LCD

WriteAddress(0x45) //写小时与分钟分隔符的显示地址, 显示在第2行第6列

WriteData(':') //将字符常量写入LCD

WriteAddress(0x48) //写分钟与秒分隔符的显示地址, 显示在第2行第9列

WriteData(':') //将字符常量写入LCD

Init_DS1302() //将1302初始化

while(1)

{

ReadValue = ReadSet1302(0x81) //从秒寄存器读数据

second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//将读出数据转化

DisplaySecond(second) //显示秒

ReadValue = ReadSet1302(0x83) //从分寄存器读

minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//将读出数据转化

DisplayMinute(minute) //显示分

ReadValue = ReadSet1302(0x85) //从分寄存器读

hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//将读出数据转化

DisplayHour(hour) //显示小时

ReadValue = ReadSet1302(0x87) //从分寄存器读

day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//将读出数据转化

DisplayDay(day) //显示日

ReadValue = ReadSet1302(0x89) //从分寄存器读

month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//将读出数据转化

DisplayMonth(month) //显示月

ReadValue = ReadSet1302(0x8d) //从分寄存器读

year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//将读出数据转化

DisplayYear(year) //显示年

}

}

改改 就是你的了


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7888899.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-11
下一篇 2023-04-11

发表评论

登录后才能评论

评论列表(0条)

保存