duanEQUP0;
weiEQUP2;
keyBITP37;
ORG0000H
AJMPMAIN;绝对转移指令,2kb范围(11位)内跳转LJMP16位64kb范围内跳转
;短转移指令的功能是先使程序计数器PC加1两次(即:取出指令码),然后把加2后的地址和rel相加作为目标转移地址。因此,短转移指令是一条相对转移指令,是一条双字节双周期指令
ORG0030H;指明后面的程序从程序存储器的0030H单元开始存放
DELAY200US:;@110592MHz
NOP
NOP
NOP
PUSH30H
PUSH31H
MOV30H,#2
MOV31H,#179
NEXT:
DJNZ31H,NEXT
DJNZ30H,NEXT
POP31H
POP30H
RET
ORG0060H
;DISPLAY子程序
DISPLAY:
PUSHACC;不能写A,此处ACC代表地址,push后跟地址,代表把地址内的内容压入栈中
PUSH00H;R0
PUSH06H;R6
PUSH07H;R7
PUSH83H;DPH
PUSH82H;DPL
MOVR6,#01H;位选数据,01指的是缓冲区最低位数据
MOVR7,#08H;循环次数
FLAG:
MOVduan,#0x00;消影
MOVA,R6
CPLA;取反
MOVwei,A;位选
MOVA,#disBufDat
ADDA,R7
SUBBA,#0X08
MOVR0,A
MOVA,@R0;读出要显示的数据到A
MOVDPTR,#disTab
MOVCA,@A+DPTR;从rom取数据,取出要显示的数据对应的段码
MOVduan,A;段选
MOVA,R6
RLA
MOVR6,A;更新下一次位选
LCALLDELAY200US
DJNZR7,FLAG
POP82H;DPL
POP83H;DPH
POP07H
POP06H
POP00H
POPACC
RET
ORG0100H
;定时器中断0初始化
T0_INIT:
MOVTMOD,#0X01
MOVTH0,#0X3C
MOVTL0,#0XB0
SETBEA
SETBTR0
SETBET0
RET
ORG0130H
;T0中断处理程序
INT_TIMERE0:
PUSHACC
SETBRS0
MOVTH0,#0X3C
MOVTL0,#0XB0
INCR0
MOVA,R0
SUBBA,#0X14
JBCY,SECFLAG
MOVR0,#0x00
INCsec
SECFLAG:
CLRRS0
POPACC
RETI
ORG000BH;定时器/计数器T0入口地址
LJMPINT_TIMERE0;跳转到定时器/计数器中断服务程序中去
disTab:DB0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40;0-f,空白,横杠的段选数据
disBufDatEQU47H;定义显示缓冲数据变量区,8个
disBufDatHeadEQU40H//单片机上显示在最左边
secEQU48H
;主程序
ORG0180H
MAIN:
MOVSP,#0X60;将0x60到0x7f设为堆栈区
LCALLT0_INIT
MOVdisBufDatHead,#0X00
MOVdisBufDatHead+1,#0X00
MOVdisBufDatHead+2,#0X11
MOVdisBufDatHead+3,#0X11
MOVdisBufDatHead+4,#0X11
MOVdisBufDatHead+5,#0X11
MOVdisBufDatHead+6,#0X11
MOVdisBufDatHead+7,#0X11
MOVsec,#0X3A
WHILE:
JBkey,KEYSCAN
MOVsec,0x00
KEYSCAN:
MOVA,sec
SUBBA,#3CH;超过60s归零
JBCY,CLEAR
MOVsec,#0X00;clr加ram地址无效
CLEAR:
MOVA,sec
MOVB,#0AH
DIVAB;A/B,商存到A中,余数存B中
MOVdisBufDatHead,A
MOVdisBufDatHead+1,B
LCALLDISPLAY
LJMPWHILE;循环
END;
扩展资料
51机器周期和指令周期
1、机器周期是指单片机完成一个基本 *** 作所花费的时间,一般使用微秒来计量单片机的运行速度,51单片机的一个机器周期包括12个时钟振荡周期,也就是说如果51单片机采用12MHz晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz的晶振,那么执行一个机器周期就需要2μs。
2、指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。在51单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。
除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。也就是说,如果51单片机采用的是12MHz晶振,那么它执行一条指令一般只需1~2微秒的时间;如果采用的是6MH晶振,执行一条指令一般就需2~4微秒的时间。
; 谁有XONIX手表的说明书(见图)
XONIX电子表怎么设置
XONIX手表 CD的具体使用方法和调整方法
精准xonix CR2016手表按键怎么按
xonix手表的闹钟怎么调啊,求解,还有,那个选时区,北京时间是怎么显示的啊,我看不懂啊求解
谁有XONIX手表的说明书(见图)
我的说明书也找不到了,简单告诉你这么调吧:
按M:秒表
长按M:调闹表时钟,再按S调:闹表分钟;
长按M,再按一下M:调秒钟,按S:陆续调分钟、时钟、月份、日期和星期;
按住S,再按M:调整时间显示方式(12小时制/24小时制);
按住S,再按R:调整日期显示方式(日/月or月/日);
按住R,再按S:陆续整点报时、闹表、取消整点报时、取消闹表;
XONIX电子表怎么设置
1、调整时间
第一步:长按set/el键3到5秒,听到滴的一声放手。
第二步:按mode键可以切换时、分、秒、年、月、日、24时区切换,还可以设置时区。比如香港时间,北京时间等。
第三步:st/stp或reset键对时间进行加减
第四步:如果调好时间以后,再按一下set/el键就可以显示你需要的时间。
2、设置跑表
按一下mode就可以,st/stp键开始,resent归零。
其它的参照说明书,不清楚的可以问我。
XONIX手表 CD的具体使用方法和调整方法
这个的话,很多电子表都是这样的,无法消除的。因为按键直接跟那个小喇叭是挂钩的。
精准xonix CR2016手表按键怎么按
先点 RESET选择要调的模块,再按MODE。然后自己看着办
xonix手表的闹钟怎么调啊,求解,还有,那个选时区,北京时间是怎么显示的啊,我看不懂啊求解
S1=ST/STP S2=RESET S3=MODE
1设置闹钟时间
闹钟BIBI声20秒,按S2键手动停止
按住S3键3秒,显示闹钟时间
时钟数闪动,按S2设置
按S1键 分钟数闪动 按S2设置
按住S2键可加快设置,按S3返回正常模式
2闹钟和整点响铃开关
按住S2键轻按S1设置闹钟和报时开关
3设置时间和日历
按住S3键3秒,显示闹钟时间,再轻按S3可以设置时间和日历
秒钟数闪动,按S2键重置为0
S1键选择,S2键设置
S3返回
4显示日期模式
按住S1然后轻按S2调整日期模式
5时间显示模式
按住S2或S1,再轻按S3调整时间模式
我的没有时区设置
基于DS1302的日历时钟
#include<reg51h> //包含单片机寄存器的头文件
#include<intrinsh> //包含_nop_()函数定义的头文件
/
以下是DS1302芯片的 *** 作程序
/
unsigned char code digit[10]={"0123456789"}; //定义字符数组显示数字
sbit DATA=P1^1; //位定义1302芯片的接口,数据输出端定义在P11引脚
sbit RST=P1^2; //位定义1302芯片的接口,复位端口定义在P11引脚
sbit SCLK=P1^0; //位定义1302芯片的接口,时钟输出端口定义在P11引脚
/
函数功能:延时若干微秒
入口参数:n
/
void delaynus(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
;
}
/
函数功能:向1302写一个字节数据
入口参数:x
/
void Write1302(unsigned char dat)
{
unsigned char i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写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=0;i<8;i++) //连续读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位定义为P20引脚
sbit RW=P2^1; //读写选择位,将RW位定义为P21引脚
sbit E=P2^2; //使能信号位,将E位定义为P22引脚
sbit BF=P0^7; //忙碌标志位,,将BF位定义为P07引脚
/
函数功能:延时1ms
(3j+2)i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/
函数功能:延时若干毫秒
入口参数:n
/
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
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); //显示年
}
}
改改 就是你的了
; 这篇文章算是对我前段时间学习的一个学习总结 以及对自己学习过程的一个回顾 本文通过一个简单的例子来尽可能的展示VCL组件开发的各个方面 本文针对即将学习组件开发的初学者 如果你已经熟悉组件开发或认为本文内容过于基础简单 那么本文对你毫无用处 阅读本文 假设你已经熟悉delphi的普通程序设计以及vcl的结构层次 还有一些重要的关键字 published property等 (注 本文内容建立在delphi 及以上版本)
在这篇文章中我们将建立一个和时间有关的组件 这个组件通过设置它的不同状态有以下基本功能 显示系统的当前时间(包括设置闹钟) 跑表 倒计时 这是一个简单的例子 然而我们将在这个例子中尽可能多的用到delphi在组件开发中的多种特性 你可以通过以下列举出的本文涉及特性有选择的阅读
·组件和组件包
·组件的属性类别
·组件的属性编辑器
·组件编辑器
一 组件和组件包 以及一些你应该知道的文件类型
组件和组件包的关系就如同普通工程中unit和工程文件的关系一样 通常你所安装的组件都是以组件包的形式发布的 一个组件包中可以有很多个组件 在组件开发中 组件包就是项目的工程文件 为了开始开发我们的组件(我们把他叫做TClock)并将它包括在我们自己的组件包(ClockPackage)中 我们选择Fileànewàother在d出的窗口中的New页选择Package新建一个组件包 得到一个组件包窗口 查看这个组件包的原文件( dpk) 得到以下代码
package ClockPackage;
{$R res}
{$ALIGN }
{$ASSERTIONS ON}
……
……
{$DESCRIPTION Our Clock Pack }
{$IMPLICITBUILD OFF}
requires
rtl;
end
这个文件其实就是组件开发中的工程文件 requires关键字指示了组件包所需组件包的列表 随着向组件包中加入组件(类似于单元文件) 你还会看到contains关键字 指示了组件包所包含的组件 你可以通过组件包窗口中的add和remove按纽来添加新的组件和删除已有的组件 另外这个代码中所包含的大量的编译器开关大多都可以在组件包窗体上的Options中设置 这里需要补充说明的是组件包的 种重要属性(都在Options中) Designtime Only Runtime Only Designtime and runtime(这 个词的意思有英语基础的朋友应该都知道吧) 对于大多数的组件包我们只要选择最后一个就可以了 然而有些组件包设计为只运行时(这样你用这套组件开发的程序不能脱离组件而单独运行 组件包也不能被安装) 有些组件包被设计为只设计时(这将在后文有更详细的说明)
了解了组件和组件包 我们对组件开发中可能出现的一些你没有见过的文件做一些说明 dpk文件既组件包的原代码 bpl文件 组件包编译后的结果 在没有发布dpk的情况下可以通过bpl来安装组件包到delphi(ProjectàOptionsàPackagesàadd) pas在这里就是组件包中组件的原代码了 dcu为pas编译后的结果 在你选择将组件包含进组件包时(contains关键字) 你可以选择发布原代码或是不发布(dcu文件) dcp如果你将组件作为运行时组件 连接器将使用该文件
二 开始开发组件
了解了上面的知识后 我们就可以开始开发组件了!在组件窗体中单击add 选择NewComponent页 在第一个组合框中选择我们的组件将要继承自哪个类(通常新的组件是通过继承已有的组件来开发的) 由于这个组件的主要作用是要显示时间 跑表 倒计时种的文字信息 所以我们选择继承自TCustomLabel(由于我们并不需要Tlabel的全部功能 我们选择了能够隐藏Tlabel属性并有选择的发布它的属性的TcustomLabel类) 接下来为我们的新组件取一个名字Tclock 然后指定我们想把组件安装到哪一个页中 这里我们自己键入一个ClockAndTime页 这将出现在RegisterComponents过程中(后面会详细说明) 选择好文件保存的路径后(最好把它和组件dpk包放在同一目录)确认 这是组件包窗体中的contains下已经多了我们刚才建立的组件的文件 双击它开始编写代码
在代码中我们需要注意在interface部分的一个新的过程 procedure Register;(注意 delphi规定Register的R必须大写 这是一个保留字) 这个过程是作为每一个组件所必须有的 它完成组件的注册 包括组件本身以及如属性编辑器等多种组件特性的注册)
procedure Register;
begin
RegisterComponents( ClockAndTime [TClock]);
//这个过程注册组件本身 注意到前面定义的ClockAndTime页了吗?
//这里在后面还会出现一些新的过程 包括注册组件的属性类别等等
end;
组件的代码由于假设你已经熟悉delphi开发(它和一般开发没什么不同) 我们就直接贴出来并加上适当的注释
unit Clock;
interface
uses
SysUtils Classes Controls StdCtrls ExtCtrls;
type
TState=(StClock StRunClock StBackClock);//定义枚举类表示控件的 种状态 时钟 跑表 倒计时钟
TClock = class(TCustomLabel)
private
fState:TState;
fTimer:TTimer;//为什么使用这个组件作为我们组件的私有成员就不用说了吧
RCD:array[ ] of integer;//跑表中的各个数位
fBeginTime:string;//到计时时的开始时钟 之所以没用TTime类型是为了在后面演示属性编辑器
fWakeTime:string;//闹钟时间 出于和上面同样的理由
fAllowWake:boolean;//是否开启闹钟功能
fOnWakeUp:TNotifyEvent;//为了使组件更加完美 我们允许组件用户能够响应闹钟到来时的时件
fOnTimeUp:TNotifyEvent;//同上能够响应倒计时种完成时的事件 我们将发布这两个事件
function GetActive:boolean;//控制Timer是否工作以控制 种状态的钟是否工作
procedure SetActive(Value:boolean);
procedure SetState(Value:TState);
procedure SetBeginTime(Value:string);
procedure SetWakeTime(Value:string);
protected
procedure WalkClock(sender:TObject);//作为时钟时走种的事件
procedure RunClock(sender:TObject); //跑表
procedure BackClock(sender:TObject);//倒计时
public
constructor Create(AOwner:TComponent);override;//完成一些初始化工作
procedure ReSetRunClock; //跑表和倒计时都需要一个复位方法给组件使用者调用
procedure ReSetBackClock;
published
property State:TState read fState write SetState default StClock;//默认为时钟状态
property Active:boolean read GetActive write SetActive;//控制 种状态的钟是否工作
property BeginTime:string read fBeginTime write SetBeginTime;
property WakeTime:string read fWakeTime write SetWakeTime;
property AllowWake:boolean read fAllowWake write fAllowWake;
property OnWakeUp:TNotifyEvent read fOnWakeUp write fOnWakeUp;
property OnTimeUp:TNotifyEvent read fOnTimeUp write fOnTimeUp;
//最后我们再发布一些被TCustomLabel所隐藏而我们又需要的属性
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
property Transparent;
property OnClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents( ClockAndTime [TClock]);
end;
{ TClock }
constructor TClock Create(AOwner: TComponent);
begin
inherited Create(AOwner);
//设置默认值
fTimer:=TTimer Create(self);
//将它属于我们的组件 这样便不用编写析构函数 而可以自动在释放本组件时释放Timer
Active:=false;
AllowWake:=false;
State:=StClock;
BeginTime:= : : ;
WakeTime:= : : ;
end;
function TClock GetActive: boolean;
begin
result:=fTimer Enabled;
end;
procedure TClock SetActive(Value: boolean);
begin
fTimer Enabled:=Value;
end;
procedure TClock SetState(Value: TState);
var
i:integer;
begin
case Value of
StClock:
begin
Active:=false;
fTimer Interval:= ;
fTimer OnTimer:=WalkClock;
Active:=true;
end;
StRunClock://由于Time类型不好处理微秒 *** 作 我们只有手工模仿这个 *** 作 代码会稍微烦琐
begin
Active:=false;
for i:= to do RCD[i]:= ;
Caption:=IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ]);
Caption:=Caption+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ]);
fTimer Interval:= ;
//经过测试 这个秒表的效果很好 然而这只是一个技术上的演示
//实际上这么频繁( / 秒)的不断执行RunClock会使CPU的占用一直达到 %
//这并不是一个好注意 事实上要想在跑表中显示微秒级别并做到合理的占用CPU
//这需要更加灵活和复杂的编程
fTimer OnTimer:=RunClock;
end;
StBackClock:
begin
Active:=false;
Caption:=BeginTime;
fTimer Interval:= ;
fTimer OnTimer:=BackClock;
end;
end;
fState:=Value;
end;
procedure TClock SetBeginTime(Value: string);
begin
try
StrToTime(Value);
fBeginTime:=Value;
if State=StBackClock then
begin
Active:=false;
Caption:=Value;
end;
except
on Exception do
begin
fBeginTime:= : : ;
if State=StBackClock then Caption:= : : ;
end;
end;
end;
procedure TClock SetWakeTime(Value: string);
begin
try
StrToTime(Value);
fWakeTime:=Value;
except
on Exception do
begin
fWakeTime:= : : ;
end;
end;
end;
procedure TClock WalkClock(sender: TObject);
begin
Caption:=TimeToStr(Time);
if AllowWake and (StrToTime(Caption)=StrToTime(WakeTime)) then
begin
Beep;//蜂鸣器
if Assigned(fOnWakeUp) then
fOnWakeUp(self);
end;
end;
procedure TClock RunClock(sender: TObject);
begin
RCD[ ]:=RCD[ ]+ ;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then RCD[ ]:= ; //我们的跑表最多可计 个小时;
Caption:=IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ]);
Caption:=Caption+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ]);
end;
procedure TClock BackClock(sender: TObject);//可以在一天之类的时间倒计时
begin
if StrToTime(Caption)<>StrToTime( : : ) then
Caption:=TimeToStr(StrToTime(Caption) )
else
begin
Active:=false;
Beep;
if Assigned(fOnTimeUp) then
fOnTimeUp(self);
end;
end;
procedure TClock ReSetBackClock;
var
i:integer;
begin
if State=StRunClock then
begin
Active:=false;
for i:= to do RCD[i]:= ;
Caption:= : : : ;
end;
end;
procedure TClock ReSetRunClock;
begin
if State=StBackClock then
begin
Active:=false;Caption:=BeginTime;
end;
end;
end 为了测试我们的组件 现在你就可以安装这个组件包并建立一个应用测试它了 点击组件包窗体中的install即可(注意 一但你安装了组件包 当你想对组件修改时 在修改了原代码以后只用点击组件窗体的pile就可以了更新组件了) 这时delphi的组件页的最后多出了我们定义的页 其中有了我们的组件!
lishixinzhi/Article/program/Delphi/201311/24840
/
ILONG编做
注意P3口输出模拟和在{实验板}上不一样。实验板不用取反
目的:用20次T0定时产生1s进而形成 HH-mm-ss时间
参数说明:
40H~47H :显示管,每位暂存器,存放要显示的数码的地址。可根据地址加1,实现该位数加1;
并且低4位可以代表管子要显示的值(42H、45H除外)。
48H :要显示的位值(0~7,由译码器翻译出)
49H :每位每次刷出时要显示的时间0~256us
4A :20次定时,的次数计数器
4BH,4CH :小时十位进位刷0,时,小时两位数的暂存
4DH :调试时,要调整类型,每次INT0中断自增一次
50H~5FH :0~F 16个数的码值
60H :"-"的码值
61H :"空" 的码值
62H,63H :要闪的两位地址暂存 (好像没用着)
R0 :存放 每位暂存器 的地址,用于 刷新位时 移位
00H(位) :是否有INT0(调整)中断
01H(位) :是闪亮,还是闪空,即:闪烁时的亮暗状态
存在问题:
1,调整时间时,分钟位开始乱码。
2,调整时间时,必须亮的时候才能调
3,时间差:慢于实际时间
20111021 ilong(crazy night)
/
SJMP 0x0030
ORG 0x0030
MAIN:
//启动外部中断
SETB IT0
SETB IE0
SETB EX0
SETB PX0
SETB IT1
SETB IE1
SETB EX1
SETB PX1
SETB EA
CLR 00H //没有调整中断
CLR 01H //闪空
MOV 4DH,#04H //0xFC
MOV P3,#0FH
MOV 62H,46H //从分开始闪
MOV 63H,47H
//十位数
MOV 50H,#3FH
MOV 51H,#06H
MOV 52H,#5BH
MOV 53H,#4FH
MOV 54H,#66H
MOV 55H,#6DH
MOV 56H,#7DH
MOV 57H,#07H
MOV 58H,#7FH
MOV 59H,#6FH
MOV 5AH,#77H
MOV 5BH,#7CH
MOV 5CH,#39H
MOV 5DH,#5EH
MOV 5EH,#79H
MOV 5FH,#71H
MOV 60H,#40H
MOV 61H,#00H
//八位管的暂存 从左到右40-47
MOV 40H,#50H
MOV 41H,#50H
MOV 42H,#60H
MOV 43H,#50H
MOV 44H,#50H
MOV 45H,#60H
MOV 46H,#50H
MOV 47H,#50H
MOV 48H,#00H //扫描位暂存
MOV R0,#40H //扫描值地址
MOV 4AH,00H //20次定时 计数
LCALL TIMER_GO20 //开启并初始定时器
//主函数进程,就是扫描码管值并显示,其他为中断 *** 作
SCAN: //显示器扫描输出
MOV P2,48H //选择显示位(从左到右0-7)
MOV A,@R0 //获取该位的数码值 地址
MOV R1,A
MOV A,@R1 //获取该位码值
//CPL A //根据数码管是共阴、共阳 是否取反
MOV P0,A //从P0输出每位的码值,注意:该端口时下面的“清屏”一起改
LCALL DELAY //进入每位延时
MOV P0,#0FFH //清屏
INC 48H //暂存器后移
INC R0 //位后移
MOV A,48H //通过 (48H)的值+08H 判断是否到了 位尾
ADD A,#08H
JB 0D6H,RER //D6H(位)为AC(辅助进位:半进位)。为1时说明(48H)的值+08H=F,即(48H)=8,此时跳向RER
SJMP SCAN
RER: //扫描重置
CLR 0D6H //重置 AC(辅助进位:半进位)
MOV 48H,#00H
MOV R0,#40H
SJMP SCAN
//End 主函数
DELAY: //延时,用于扫描7段管时,在每一位停留的时间时间太短,回使不该亮的段也有些亮
MOV 49H,#25H //49H的值不可以等于FF,因为FF取反后49H为0,不会延迟了
MOV A,0FEH //用取反设置循环次数,
CPL A
MOV 49H,A
ADD_1:
INC 49H
MOV R1,49H //因为DJNZ判断完后要把判断的地址减去1,所以为了DJNZ不对49H的内容造成影响,把49H的值装到R1中去判断
DJNZ R1,ADD_1
RET
//20次定时
TIMER_GO20:
//用4AH 设置循环次数
MOV 4AH,#15H //20(=0x15)次定时
MOV A,4AH //用取反设置定时次数,
CPL A
MOV 4AH,A
SJMP TIMER_S
TIMER_GO5: //与TIMER_GO20类似,只是这里只让定时5次一循环。用于调整闪烁
MOV 4AH,#05H //5(=0x05)次定时
MOV A,4AH //用取反设置定时次数,
CPL A
MOV 4AH,A
TIMER_S://未重置(4AH)的调用,
//设置启动T0
MOV TMOD,#01H //设置模式:T0模式1
MOV TH0,#3CH //T0初值高8位
MOV TL0,#0AH //T0初值低8位
//CLR TF0 //未知问题
SETB ET0 //T0允许中断
SETB EA //CPU允许中断
SETB TR0 //启动T0
RET
T0_INT: //T0中断程序段
CPL P17 //测试端口:T0重新定时一次发生一次跳转
LCALL TIMER_S //T0重新定时,继续跑。但:不会初始化20次计数
INC 4AH //T0定时次数加1
MOV A,4AH
JNZ CY_20 //50H加到FF再加就到0了。不为0回去接着执行主程序;为0 则20次定时 溢出即:00H(位)为1
CPL P16 //测试端口每秒发生一次跳转
JB 00H,GO_BLINK //如果00H(位)被置1,则不再执行时间系统加1。用于调整时显示闪烁
LCALL CLOCK_GO //时间系统加1秒
LCALL TIMER_GO20 //20次重新开始
SJMP CY_20
GO_BLINK:
LCALL TIMER_GO5 //5次重新开始,
LCALL BLINK
CY_20: RET
//时间系统进位设置
CLOCK_GO:
INC 47H //秒加1
//个位秒 进位 十位
MOV A,#5AH //主要是看"#5A"中的“A”,
SUBB A,47H
JNZ SS_OUT //如果(47H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 47H,#50H
INC 46H
SS_OUT:
//秒 进位 分
MOV A,#56H //
SUBB A,46H
JNZ SM_OUT //如果(46H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 46H,#50H
CLOCK_GO_M:INC 44H
//分调整用
SM_OUT:
//分个位 进位 分
MOV A,#5AH //
SUBB A,44H
JNZ MM_OUT //如果(44H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 44H,#50H
INC 43H
MM_OUT:
//分 进位 时
MOV A,#56H //
SUBB A,43H
JNZ MH_OUT //如果(43H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 43H,#50H
CLOCK_GO_H:INC 41H
//时调整用
MH_OUT:
//时个位 进位 时
MOV A,#5AH //
CLR CY //排除借位影响
SUBB A,41H
JNZ HH_OUT //如果(41H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 41H,#50H
INC 40H
HH_OUT:
//时十位置0
MOV 4BH,40H //为了不影响暂存器数据,把40H、41H转到4BH、4CH中进行 *** 作
MOV 4CH,41H
MOV A,4BH
SWAP A //获得小时十位数,并放到A的高4位上
ANL A,#0F0H //清0低4位
ANL 4CH,#0FH //小时个位 高4位清0
ADD A,4CH //小时的十位与个位相加(高4位来自小时的十位暂存器40H,低四位来自小时个位的寄存器41H)
SUBB A,#24H
JNZ HD_OUT //如果(46H)值 低4 与A中的低4不相同,跳到“SS_OUT”,不进位
MOV 41H,#50H //个位 清零
MOV 40H,#50H //十位清零
HD_OUT:
CG_OUT: RET
//END 时间系统进位设置
//INTO中断程序段
INT0_INT:
SETB 00H
CPL P15
CPL P15
CLR 01H //使得在换位闪烁时不会把上位的数带给下一位,
HMS_BACK: //在每次换位时都要把,被放到暂存上的值那回去,使其显示出来
MOV A,4DH
CJNE A,#02H,BSH_S //back second OR hour _select
LCALL LIGHT_M
SJMP B_END
BSH_S: //恢复秒小时选择
JB CY,B_H
SJMP B_S
B_S: LCALL LIGHT_S //把调好的数据装回暂存器
SJMP B_END
B_H: LCALL LIGHT_H
B_END:
// CLR TR0 //定时器0,停止计时
DEC 4DH //调整类型(时、分、秒)改变
MOV A,4DH
JNZ INT0_OUT //是否恢复时钟
CLR 00H //置0,调整中断(ilong 定义)
CLR 01H
MOV 4DH,#04H //初始化调整类型
INT0_OUT:
RET
////闪烁
BLINK:
CPL P11
CPL 01H
MOV A,4DH
CJNE A,#02H,SH_S
SJMP MM_SET
SH_S: //闪烁秒小时选择
JB CY,HH_SET
SJMP SS_SET
SS_SET: //秒钟设置
JB 01H,DACK_S
LIGHT_S:
MOV 46H,4EH
MOV 47H,4FH
SJMP BLINK_OUT
DACK_S:
MOV 4EH,46H
MOV 4FH,47H
MOV 46H,#61H
MOV 47H,#61H
RET
MM_SET: // 分钟设置
JB 01H,DACK_M
LIGHT_M:
MOV 43H,4EH
MOV 44H,4FH
SJMP BLINK_OUT
DACK_M:
MOV 4EH,43H
MOV 4FH,44H
MOV 43H,#61H
MOV 44H,#61H
RET
HH_SET: //小时设置
JB 01H,DACK_H
LIGHT_H:
MOV 40H,4EH
MOV 41H,4FH
SJMP BLINK_OUT
DACK_H:
MOV 4EH,40H
MOV 4FH,41H
MOV 40H,#61H
MOV 41H,#61H
BLINK_OUT:RET
//INT1中断程序段
INT1_INT:
//lcall HMS_BACK
//clr tr0
CPL P14
MOV A,4DH
CJNE A,#02H,ADDSH_S //ADD Hour OR ADD second OR _select
SJMP ADD_M
ADDSH_S: //调整秒小时选择
JB CY,ADD_H
SJMP ADD_S
ADD_S: LCALL CLOCK_GO
SJMP ADD_END
ADD_M: LCALL CLOCK_GO_M
SJMP ADD_END
ADD_H: LCALL CLOCK_GO_H
ADD_END:
// LCALL CLOCK_GO
RET
/
最后放中断保险些
/
//T0中断程序
ORG 000BH
LCALL T0_INT
RETI
//INT0中断
ORG 0003H
LCALL INT0_INT
RETI
//INT1中断
ORG 0013H
LCALL INT1_INT
RETI
END
org 0000h
ajmp main
org 0030h
main:
mov dptr,#tab
mov 30h,#00h
mov 31h,#00h
mov 32h,#00h
mov 33h,#00h
mov 34h,#00h
mov 35h,#00h
loop:
mov r4,#5
tt1:
lcall display
djnz r4,tt1
lcall update
ajmp loop
display: mov p3,#0h
mov r7,#100
dd1:
mov a,30h
movc a,@a+dptr
mov p1,a
CLR P33
CLR P34
CLR P35
lcall delay100us
mov a,31h
movc a,@a+dptr
mov p1,a ;将要显示的数送入P0口
SETB P33
CLR P34
CLR P35
lcall delay100us ;延时100US
mov a,32h ;将显示缓冲区32H中的值送入ACC
movc a,@a+dptr ;查表取要显示的数并把查表的结果送入ACC
mov p1,a ;将要显示的数送入P0口
SETB P33
SETB P34
CLR P35
lcall delay100us ;延时100US
mov a,33h ;将显示缓冲区33H中的值送入ACC
movc a,@a+dptr ;查表取要显示的数并把查表的结果送入ACC
mov p1,a ;将要显示的数送入P0口
CLR P33
CLR P34
SETB P35
lcall delay100us ;延时100US
mov a,34h ;将显示缓冲区别31H中的值送入A
movc a,@a+dptr ;查表取要显示的数并把查表的结果送入ACC
mov p1,a ;将要显示的数送入P0口
CLR P33
SETB P34
SETB P35
lcall delay100us ;延时100US
mov a,35h ;将显示缓冲区别31H中的值送入A
movc a,@a+dptr ;查表取要显示的数并把查表的结果送入ACC
mov p1,a ;将要显示的数送入P0口
SETB P33
SETB P34
SETB P35
lcall delay100us ;延时100US
djnz r7,dd1 ;R7不等于0返回至DD1处
ret ;R7等于0子程序返回
update: ;刷新显示子程序
inc 30h ;个位显示缓冲单元加一
mov a,30h
cjne a,#10,exit ;还没加到十,退出
mov 30h,#00h ;加到十了,个位清零
inc 31h ;十位显示缓冲单元加一
mov a,31h
cjne a,#6,exit ;还没加到十,退出
mov 31h,#00h ;加到十了,十位清零
inc 32h ;百位显示缓冲单元加一
mov a,32h
cjne a,#10,exit ;还没加到十,退出
mov 32h,#00h ;加到十了,百位清零
inc 33h ;千位显示缓冲单元加一
mov a,33h
cjne a,#6,exit ;还没加到十,退出
mov 33h,#00h ;加到十了,千位清零
inc 34h ;十位显示缓冲单元加一
mov a,34h
cjne a,#10,exit ;还没加到十,退出
mov 34h,#00h ;加到十了,十位清零
inc 35h ;十位显示缓冲单元加一
mov a,35h
cjne a,#10,exit ;还没加到十,退出
mov 35h,#00h ;加到十了,十位清零
exit:
ret ;刷新显示子程序返回
delay100us:
mov r5,#147
djnz r5,$
ret
delay10ms:
mov r6,#100
tt2:
mov r5,#147
djnz r5,$
djnz r6,tt2
ret
tab: db 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0D8H,80H,90H
end
以上就是关于用51单片机实现时钟功能程序全部的内容,包括:用51单片机实现时钟功能程序、XONIX电子表怎么设置xonix电子表调时间、单片机做时钟程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)