单片机电子时钟直接设置定时时间,并实时显示剩余时间

单片机电子时钟直接设置定时时间,并实时显示剩余时间,第1张

#include<reg51h>

#define uchar unsigned char

#define uint  unsigned int

#define u8 unsigned char

#define u16  unsigned int

sbit k1=P3^1;  //第一个按键,选择设置

uchar code distab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管段码表

uchar disbuf[8]; //声明显示缓冲区8个单元

uchar hour=12;   //声明小时变量,初值为12

uchar minute=59; //声明分变量,初值为59

uchar second;    //声明秒变量

uchar t0n;       //定时器T0中断计数,定时50ms,中断20次为1秒

uchar dis;       //调时状态下,显示小数点位

void delay()     //延时子程序,用于显示子程序

{

uint j;

for(j=300;j>0;j--);

}

//显示子程序,参数dis为显示小数点位

void display(uchar dis)

{

uchar j,disbit=0x01; //位码

for(j=0;j<8;j++)

{

P2=~disbit;       //P2口输出位码

if(dis>0&&dis==j) //调时状态下,显示小数点

P0=distab[disbuf[j]]+0x80; //在小时,分,秒位上显示小数点

else

P0=distab[disbuf[j]]; //其它位正常显示

disbit<<=1;           //取下一个位码

delay();              //延时

}

}

#define RxBUFSIZE 10

u8 RxBuf[RxBUFSIZE];

u8 Rxcount=0;

u8 Rxtime=0;

void UartInit(){

SCON=0x50;

TMOD&=0x0f;

TMOD|=0x20;

TH1=TL1=0xfd;//1105926  9600

TR1=1;

ES=1;

EA=1;

}

//格式  Txx:xx:xx

//解析时间

void JX1(){

u8 a;

a=(RxBuf[1]-'0')10+(RxBuf[2]-'0');

if(a>23)return;

hour=a; //时

a=(RxBuf[4]-'0')10+(RxBuf[5]-'0');

if(a>59)return;

minute=a; //分

a=(RxBuf[7]-'0')10+(RxBuf[8]-'0');

if(a>59)return;

second=a; //秒

}

void UartCl(){

if((Rxtime>4)&&(Rxcount>=9)){

if(RxBuf[0]=='T'){

JX1();

}

Rxcount=0;

}

}

void UartInterrupt() interrupt 4

{

if(RI){

RI=0;

Rxtime=0;

if(Rxcount<RxBUFSIZE){

RxBuf[Rxcount++]=SBUF;

}

}

}

void main()

{

disbuf[2]=disbuf[5]=10;//数码管第3,6位显示-

TMOD=0x01;

TH0 =0x3C;    //单片机晶振频率=12M,定时50ms,时间常数=3CB0

TL0 =0xB0;

IE  =0x82;    //开定时器T0中断

TR0 =1;       //启动定时器T0

IT0 =1;       //设置外部中断为下降沿有效

IT1 =1;

UartInit();

while(1)

{

display(dis); //调显示子程序

UartCl();

if(k1==0)     //选择设置

{

dis++;    //停止计时,进入调时状态

EX0=1;    //调时状态下,允许外部INT0,INT1中断

EX1=1;    //用来调小时,分,秒

if(dis>7) //调小时,在小时位显示小数点

{

dis=0; //灭小数点

t0n=0; //调时结束,开始计时

TR0=1;

EX0=0; //关外部中断

EX1=0;

}

else if(dis==2)dis=4; //调分,在分位显示小数点

else if(dis==5)dis=7; //调秒,在秒位显示小数点

while(k1==0)display(dis); //等待按键释放

}

if(t0n>=20&&dis==0) //中断20次,1秒到,计时状态下时钟计时

{

t0n=0;

second++;      //秒加1

if(second>=60) //到60秒

{

second=0;

minute++;      //分加1

if(minute>=60) //到60分

{

minute=0;

hour++;    //小时加1

if(hour>=24)

hour=0;

}

}

}

disbuf[0]=hour/10;    //显示小时十位

disbuf[1]=hour%10;    //显示小时个位

disbuf[3]=minute/10;  //显示分十位

disbuf[4]=minute%10;  //显示分个位

disbuf[6]=second/10;  //显示秒十位

disbuf[7]=second%10;  //显示秒个位

}

}

//定时器T0中断服务子程序

void T0_isr() interrupt 1

{

TH0=0x3C;  //重写时间常数

TL0=0xb0;

t0n++;     //中断次加1

if(++Rxtime>(205)){//超时处理

Rxtime=0;

Rxcount=0;

}

}

//外部中断INT0服务程序,调时状态下,加1

void INT0_ISR() interrupt 0

{

if(dis==1)     //调小时

{

hour++;    //小时加1

if(hour>=24)

hour=0;

}

if(dis==4)     //调分

{

minute++;  //分加1

if(minute>=60)

minute=0;

}

if(dis==7)     //调秒

{

second++;  //秒加1

if(second>=60)

second=0;

}

}

//外部中断INT1服务程序,调时状态下,减1

void INT1_ISR() interrupt 2

{

if(dis==1)   //调小时

{

hour--;  //小时减1

if(hour==0xff)

hour=23;

}

if(dis==4)    //调分

{

minute--; //分减1

if(minute==0xff)

minute=59;

}

if(dis==7)   //调秒

{

second--;//秒减1

if(second==0xff)

second=59;

}

}

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;20h1半点标示位

;20H2闹钟设置中标示,为了显示区别用

;20H3闹钟设置时间CHECK到,使能标志位

;20H5开/关闹钟设置中标示;

;20H6闹钟1开关标志位

;20H7闹钟2开关标志位

;psw5用来做显示开关标志位

;21,22,23,24这里设置第一个闹钟的时间

;25,26,27,28这里设置第二个闹钟的时间

;29H

;P0口输出数码管段码,

;P2口 输出位选信号

;

;70H存放P10--3按钮值,

;71H--78H存放当前系统定时时间;

;78H 77H 76H 75H 74H 73H 72H 71H

; 星期 小时 分钟 秒钟

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ts equ 24h ;这里设置`24小时周期制

trr equ #0bbh ;这个是温度,晶振等的时间补偿值,

org 0000h ;定时太慢此值调大,定时太快调小;

jmp main

;org 0bh ;定时器0中断入口矢量

;jmp bz

org 1bh ;定时器1中断入口矢量

jmp t1int

org 0100h ;主程序

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;主程序

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

main:clr p30; ;关继电器

mov sp,#30h

mov r3,#20

mov tmod,#10h

;mov tl0,#06h ;定时器1,方式1,定时 50 MS;

;mov th0,#06h

mov tl1,#0b0h

mov th1,#3ch

mov ie,#88h ;开定时器1中断

;mov 65h,#5

; mov 66h,#100

;mov 64h,#4

;clr psw5

clr p30

setb pt1 ;设置T1为高优先级中断

;setb tr1

clr tr1 ;开启T1中断

acall send ;71h--78h 清零;

acall send1 ;20h--29h 清零;

dd: acall daa ;进行十进制调整71H-79H

;acall compare ;第一闹钟

;acall compare1 ;第二闹钟 设置值

;acall sound

acall disp ;数码管显示,78H--71H分别对应着8个数码管显示

acall key_scanf ;按钮控制

acall time_adj ;时间调整

acall lasttime ;调用上一次的设置值为当前定时值

;acall alarm1_set ;设置定时开/关闹钟

ajmp dd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;调用上次值为设置时间

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

lasttime:push acc

mov a,70h

jnb acc2,return1

clr p30; 紧急暂停按钮,按下后暂停,并把上次设定值恢复

clr tr1

mov 73h,21h

mov 74h,22h

wait7:acall disp

acall key_scanf

mov a,70h

jnb acc0,wait7

mov 71h,#0

mov 72h,#0

mov 79h,#0

mov tl1,trr

mov th1,#3ch

mov r3,#20

setb tr1

setb p30

return1:pop acc

ret

daa: push acc ;对当前系统时间进行十进制调整

mov 71h,79h

mov r1,#71h

cjne @r1,#10,s2

mov 71h,#0h

mov 79h,#0

inc 72h

mov r1,#72h

cjne @r1,#6,s2

mov 72h,#0h

dec 73h

mov r1,#73h

cjne @r1,#255,s2

dec 74h

mov 73h,#9

s1: pop acc

ret

s2: mov r1,#73h

cjne @r1,#0,s1

mov r1,#74h

cjne @r1,#0,s1

clr p30

clr tr1

sjmp s1

h_half: ;半点CHECK

mov r1,#73h

mov a,74h

swap a

xchd a,@r1

cjne a,#29h,o25 ;CHECK 当前时间是否为29分钟

xchd a,@r1

mov r1,#71h

mov a,72h

swap a

xchd a,@r1

cjne a,#59h,o25 ;CHECK 当前时间为59秒

setb tr0 ;启动T0

setb 20h1 ;enable 半点flag bit

o25: xchd a,@r1

ret

compare: ;闹钟1设置时间与当前时间比较

push acc

jnb 20h6,nequ ;闹钟1开/关标志位

mov a,73h

cjne a,21h,nequ ;分低位

mov a,74h

cjne a,22h,nequ ;分高位

mov a,75h

cjne a,23h,nequ ;小时低位

mov a,76h

cjne a,24h,nequ ;小时高位

setb 20h3 ;到闹钟设置时间,使能闹钟报警标志位

nequ:pop acc

ret

compare1: ;闹钟2设置时间与当前时间比较

push acc

jnb 20h7,nequ33 ;闹钟2开/关标志位

mov a,73h

cjne a,25h,nequ33

mov a,74h

cjne a,26h,nequ33

mov a,75h

cjne a,27h,nequ33

mov a,76h

cjne a,28h,nequ33

setb 20h3 ;到闹钟设置时间,使能闹钟报警标志位

nequ33:

pop acc

ret

sound:

acall h_half ;check 是否半点

jb 20h1,s23 ;半点则返回

jb 20h0,s23

mov r1,#73h

mov a,74h

swap a

xchd a,@r1

cjne a,#59h,s25

xchd a,@r1

mov r1,#71h

mov a,72h

swap a

xchd a,@r1

s20: cjne a,#56h,s21

ajmp s26

s21: cjne a,#58h,s22

ajmp s26

s22: cjne a,#59h,s25

setb tr0

ajmp s26

s25: xchd a,@r1

s23: ret

s26: jb 20h0,s25

setb tr0

xchd a,@r1

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;T0中断服务程序,报时铃音信号输出

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

bz: djnz 64h,rrr

jb 20h3,alarmsign;闹钟到点报时有效

jb 20h1,next ;半点报时

mov 64h,#4 ;05KHZ

ajmp justh

alarmsign:

mov 64h,#1; 2KHZ信号

justh:

djnz 66h,ccc

mov 66h,#100

djnz 65h,ccc ;产生1000次中断后关中断

mov 65h,#5 ;响05秒

setb 20h0

clr tr0

reti

next:mov 64h,#2 ;1KHZ信号,半点报时音

ccc: jb 20h3,cc

cpl p14 ;半点报时输出声音信号

rrr: reti

cc: cpl p14 ;闹钟报时输出声音信号

reti

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;T1中断服务程序,定时器主时钟;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

t1int:

clr ea

mov tl1,trr

mov th1,#3ch

djnz r3,sd ;2050MS=1S

mov r3,#20

;cpl p14

inc 79h

clr 20h0

clr 20h1 ;半点报时标志清零

jb 20h3,sdd ;闹钟CHECK有效与否

clr tr0 ;关T0

sd: setb ea

reti

sdd: setb tr0 ;开T0,即开闹铃声音

setb ea

reti

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;显示子函数

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dispnum1:; 显示

ajmp disp_num

disp:

push acc

;jb 20h5,dispnum1;开/关闹钟设置中界面

;jb 20h2,alarmcheck;闹钟设置时间中界面

jb psw5,closedisp

mov r2,#01h;位选通信号输出到P2口

mov r5,#2; 显示的位数循环控制

mov r0,#73h;分别取出内存76H-71H

cjne r3,#10,dot1;在小时和分之间闪烁DOT point

dot1:jnc dsp1

orl 73h,#10h

;dot1:cjne r3,#11,dsp1

;anl 73h,#0efh

dsp1:mov a,r2

;cpl a

mov p2,a

mov a,@r0

dsp2:mov dptr,#bcd

movc a,@a+dptr

mov p0,a

acall delay

mov a,r2

rl a

mov r2,a

inc r0

djnz r5,dsp1

anl 73h,#0efh

pop acc

ret

closedisp:; 关显示

acall delay

mov p0,#0ffh

mov p2,#0

pop acc

ret

;;;;;;;;;;;;;;;;;闹钟的定时设置显示

alarmcheck:

mov r2,#01h

mov r5,#2 ;两位显示22-21H对应定时设置值

mov r0,#21h

dsp21:

mov a,r2

;cpl a

mov p2,a

mov a,@r0

mov dptr,#bcd

movc a,@a+dptr

mov p0,a

acall delay

mov a,r2

rl a

mov r2,a

inc r0

djnz r5,dsp21

pop acc

ret

bcd:; 共阳接法数码管段码表

db 0c0h,0f9h,0a4h,0b0h

db 99h,92h,82h,0f8h

db 80h,90h,88h,83h

db 0c6h,0a1h,86h,8eh; 不带小数点七段

db 40h,79h,24h,30h,19h

db 12h,02h,78h,00h,10h

db 0ffh,0bfh,7fh,3fh; 带小数点七段

delay:mov r6,#4h

tm: mov r4,#0h

ee: djnz r4,ee; 延时2048US=2MS

djnz r6,tm

ret

send:mov r7,#9; 初始化设置

mov r0,#71h

mov a,#0h

ss: mov @r0,a

inc r0

djnz r7,ss

mov 78h,#1h

mov 77h,#01ah

;mov 71h,#1

;mov 72h,#2

;mov 73h,#3

;mov 74h,#4

ret

send1:; 初始化

mov r7,#10

mov r0,#20h

mov a,#0

ss1: mov @r0,a

inc r0

djnz r7,ss1

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;开/关闹钟界面显示

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

disp_num:

mov p2,#0f7h

mov a,29h ;当前要 *** 作的闹钟号码

mov dptr,#bcd

movc a,@a+dptr

mov p0,a

acall delay

pop acc

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

key_scanf:; 按钮处理

push acc

mov 70h,#0

orl p1,#0fh

mov a,p1

cpl a

anl a,#07h

jz nokey1

acall daa

acall disp

mov a,p1

cpl a

anl a,#07h

jz nokey1

mov 70h,a

key_wait:; 等按钮放下

acall daa

acall disp

mov a,p1

cpl a

anl a,#07h

jnz key_wait

mov a,70h

jnb acc1,nokey1

cpl psw5

nokey1:; 无按钮

pop acc

ret

a_on_off:

jnb 29h0,iii

cpl 20h6

iii: jnb 29h1,out_2

cpl 20h7

out_2:

ajmp alarmnum

alarmnum:

setb 20h5

acall daa

acall disp

acall key_scanf

clr 20h5

mov a,70h

jb acc0,a_on_off

jb acc1,alar_adj_1

jb acc2,a_num_inc

acall numb

ajmp alarmnum

alarm1_set:

push acc

mov a,70h

jb acc1,alarmnum

alarm1_out:

clr 20h2

pop acc

ret

a_num_inc:

inc 29h

mov a,29h

anl a,#0fh

cjne a,#3,alarmnum

anl 29h,#0

ajmp alarmnum

alar_adj_1:

setb 20h2

acall daa

orl 21h,#10h

acall disp

anl 21h,#0fh

acall key_scanf

mov a,70h

jb acc1,hadj_1

jb acc2,minc_1

ajmp alar_adj_1

madj_2:

acall daa

orl 25h,#10h

acall disp

anl 25h,#0fh

acall key_scanf

mov a,70h

jb acc1,hadj_2

jb acc2,minc_2

ajmp madj_2

hadj_1:

acall daa

orl 23h,#10h

acall disp

anl 23h,#0fh

acall key_scanf

mov a,70h

jb acc1,madj_2

jb acc2,hinc_1

ajmp hadj_1

hadj_2:acall daa

orl 27h,#10h

acall disp

anl 27h,#0fh

acall key_scanf

mov a,70h

jb acc1,alarm1_out

jb acc2,hinc_2

ajmp hadj_2

minc_1:

inc 21h

mov r1,#21h

cjne @r1,#10,alar_adj_1

mov 21h,#0

inc 22h

mov r1,#22h

cjne @r1,#6,alar_adj_1

mov 22h,#0h

ajmp alar_adj_1

minc_2:

inc 25h

mov r1,#25h

cjne @r1,#10,madj_2

mov 25h,#0

inc 26h

mov r1,#26h

cjne @r1,#6,madj_2

mov 26h,#0

ajmp madj_2

hinc_1:

inc 23h

mov r1,#23h

cjne @r1,#10,ss14

mov 23h,#0

inc 24h

ss14:

mov a,24h

swap a

xchd a,@r1

cjne a,#ts,ss15

mov 23h,#0

mov 24h,#0

ajmp hadj_1

ss15:xchd a,@r1

ajmp hadj_1

hinc_2:

inc 27h

mov r1,#27h

cjne @r1,#10,sss14

mov 27h,#0

inc 28h

sss14:

mov a,28h

swap a

xchd a, @r1

cjne a,#ts,sss15

mov 27h,#0

mov 28h,#0

ajmp hadj_2

sss15:

xchd a,@r1

ajmp hadj_2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;时间调整程序

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

time_adj:;

clr psw5

push acc

mov a,70h

jb acc0,l1;P10调时功能键,每按一次切换一位

ajmp nokeyout

adj_out:

mov 21h,73h

mov 22h,74h

setb p30 ;闭合继电器

setb tr1

nokeyout:

pop acc

ret

QQ: anl 73h,#0fh

anl 74h,#0fh

;anl 78h,#0fh

ret

l1: clr tr1;acall dab; 分钟调整

orl 73h,#10h;点亮分右下角的小数点,当前调整位置

acall disp

acall QQ

acall key_scanf

clr psw5

mov a,70h

jb acc0,h_adj;切换到小时调整

jb acc1,m_inc;P12加1按钮

ajmp l1

h_adj:; 小时调整

;acall dab

orl 74h,#10h

acall disp

acall QQ

acall key_scanf

clr psw5

mov a,70h

jb acc0,out_adj;切换到星期调整

jb acc1,h_inc;小时加1

ajmp h_adj

w_adj:

acall daa

orl 78h,#10h

acall disp

acall QQ

acall key_scanf

clr psw5

mov a,70h

jb acc0,out_adj

jb acc2,w_inc

ajmp w_adj

out_adj:

ajmp adj_out

m_inc:;;;;;;;;;;;;;;; 调整分时,对定时复位,初始化

clr tr1

mov 71h,#0

mov 72h,#0

mov 79h,#0

mov tl1,trr

mov th1,#3ch

mov r3,#20

inc 73h

mov r1,#73h

cjne @r1,#10,s12

mov 73h,#0

inc 74h

mov r1,#74h

cjne @r1,#10,s12

mov 74h,#0

s12: ajmp l1

;;;;;;;;;;;;;;;;;;;;;;调整小时位

h_inc:

inc 74h

mov r1,#74h

cjne @r1,#10,s14

mov 74h,#0

;inc 76h

s14: ajmp h_adj

;mov a,76h

;swap a

;xchd a,@r1

;cjne a,#ts,s15;;;12进制,24进制设置值决定

;mov 75h,#0

;mov 76h,#0

;ajmp h_adj

;s15: ;xchd a,@r1

;ajmp h_adj

;;;;;;;;;;;;;;;;;;;;;;;调整星期位

w_inc:

inc 78h

mov r1,#78h

cjne @r1,#8,s16

mov 78h,#1h

s16: ajmp w_adj

;;;;;;;;;;;;;;;;;;;;;;;当前闹钟开/关情况报告位

numb:clr 29h4

jnb 29h0,iii1

jnb 20h6,iii1

setb 29h4

iii1:jnb 29h1,out_21

jnb 20h7,out_21

setb 29h4

out_21:

jnb 20h6,out_12

jnb 20h7,out_13

mov 77h,#1dh

ajmp out_22

out_12:

jnb 20h7,out_14

mov 77h,#1bh

ajmp out_22

out_13:

mov 77h,#1ch

ajmp out_22

out_14:

mov 77h,#1ah

out_22:

ret

end

1 例如当时间达到09年6月3日20点31分20秒的时候,CPU转到停止,前提是CPU有硬件时钟,并且正确设置了时间。

LD SM05

EU

TODR VB0 //读取时间

LDB>= VB0, 16#09 //读取的时间是BCD码,这样用省去格式转换

AB>= VB1, 16#06

AB>= VB2, 16#03

AB>= VB3, 16#20

AB>= VB4, 16#31

AB>= VB5, 16#20

STOP

2 如果定时开启关闭外部设备,那PLC可以轻松完成。

例如每天早上6点到晚上8点开机

LD SM05

EU

TODR VB0

LDB>= VB3, 16#06

AB= Q00

3 PLC运行一段时间停止

LD SM04

EU

INCD MD0 //每分钟累加一次,

LDD= MD0, 4320 //3天后CPU停止,4320=3天24小时60分钟

STOP //在系统块里将MD0设置为断电保持,那么计时不受停**响,停电自动保存计时时间。

关键是如何读系统时钟:

S7-200的硬件实时时钟可以提供年、月、时、分、秒的日期/时间数据。

CPU221、CPU222没有内置的实时时钟,需要外插“时钟/电池卡”才能获得此功能。CPU224、CPU226和CPU226 XM都有内置的实时时钟。

为了提高运算效率,应当避免每个程序周期都读取实时时钟。实际上可读取的最小时间单位是1秒,可每秒读取一次(使用SM05上升沿触发读取指令)。

使用程序读取的实时时钟数据为BCD格式,可在状态图中使用十六进制格式查看。

CPU靠内置超级电容(+外插电池卡)在失去供电后为实时时钟提供电源缓冲;缓冲电源放电完毕后,再次上电后时钟将停止在缺省值,并不开始走动。

要设置日期、时间值,使之开始走动,可以:

用编程软件(Micro/WIN)的菜单命令PLC > Time of Day Clock,通过与CPU的在线连接设置,完成后时钟开始走动

编用户程序使用Set_RTC(设置时钟)指令设置

Micro/WIN可以通过任何编程连接实现实时时钟的设置。

使用 S7-200 的 READ_RTC(读取实时时钟)和 SET_RTC(设置实时时钟)指令时, 读取和设置的数据格式都是 BCD 码的。如果觉得不便计算、处理,可使用 Clock Integer 指令库。

if(T0IF&&T0IE) //定时器T0中断类型判别

{

int i;

TMR0=TMR0+11;

T0IF=0;

asm("clrwdt");

count+=1;

if(count==5) //计数基数58250=001s

{

count=0;

i=0;

do{

s[i]+=1;

i++;

}while(i<3); //3个计数基数累加

}

} //Tmr0_int服务子程序3

#include<reg51h>

#define uchar unsigned char

uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9

unsigned char sec=0,min=0,hour=12,scanled;

unsigned char key,flashbit,mode,time;

unsigned char disdat[6];

sbit led=P1^0;

void delay(unsigned int x)

{

unsigned int i,j;

for(i=0;i<x;i++)

for(j=0;j<120;j++);

}

void dischg()

{

disdat[0]=sec%10;

disdat[1]=sec/10;

disdat[2]=min%10;

disdat[3]=min/10;

disdat[4]=hour%10;

disdat[5]=hour/10;

}

void flash()

{

switch(flashbit)

{

case 0:break;

case 1:

disdat[4]=0x10;

disdat[5]=0x10;

delay(50);

dischg();

delay(80);

break;

case 2:

disdat[2]=0x10;

disdat[3]=0x10;

delay(50);

dischg();

delay(80);

break;

case 3:

disdat[0]=0x10;

disdat[1]=0x10;

delay(50);

dischg();

delay(80);

break;

default:break;

}

}

void t0isr() interrupt 1 //秒计时

{

TH0=0x3c;

TL0=0xb0;

time++;

switch(mode)

{

case 0:

if(time==20)

{

time=0;

sec++;

if(sec>59)

{

sec=0;

min++;

if(min>59)

{

hour++;

if(hour>23)hour=0;

}

}

}

break;

case 1:

if(time==20)

{

time=0;

if(sec>0)sec--;

else if(min>0){sec=59;min--;}

else if(hour>0){sec=59;min=59;hour--;}

else {hour=0;min=0;sec=0;}

}

break;

}

dischg();

}

void t1isr() interrupt 3 //显示

{

TH1=0xec;

TL1=0x78;

switch(scanled)

{

case 0:

P2=0x01;

P0=~ledtab[disdat[5]];

break;

case 1:

P2=0x02;

P0=~ledtab[disdat[4]];

break;

case 2:

P2=0x04;

P0=~ledtab[disdat[3]];

break;

case 3:

P2=0x08;

P0=~ledtab[disdat[2]];

break;

case 4:

P2=0x10;

P0=~ledtab[disdat[1]];

break;

case 5:

P2=0x20;

P0=~ledtab[disdat[0]];

break;

default:break;

}

scanled++;

scanled%=6;

}

main()

{

TMOD=0x11;

TH0=0x3c;

TL0=0xb0;

TH1=0xec;

TL1=0x78;

EA=1;

TR1=1;

ET0=1;

ET1=1;

sec=0;

min=0;

hour=12;

flashbit=0;

scanled=0;

time=0;

mode=0;

dischg();

while(1)

{

flash();//闪烁

// led=1;

if((P3&0x0f)!=0x0f){

key=P3&0x0f;

while((P3&0x0f)!=0x0f);

led=0;

delay(10);

key|=0xf0;

switch(~key)

{

case 0x01: //p31选择调时、分、秒

TR0=0;

flashbit+=1;

if(flashbit>3){flashbit=0;TR0=1;}

break;

case 0x02: //p32调数

if(flashbit==0)break;

if(flashbit==1)

{

hour++;

if(hour>23)hour=0;

}

if(flashbit==2)

{

min++;

if(min>59)min=0;

}

if(flashbit==3)

{

sec++;

if(sec>59)sec=0;

}

break;

case 0x04: //选择正/倒

TR0=0;

mode++;

mode&=0x01;

if(mode==0){sec=0;min=0;hour=0;}

dischg();

break;

case 0x08: //启动/暂停

TR0=~TR0;

break;

default:break;

}

}

}

}

自己写了一个时钟程序,用来模拟时间类型软件的破解,先从基础的运行时间开始,程序运行界面如图:十秒后程序自动退出

十秒后程序自动退出

破解思路:查看程序导入表函数(有N多个程序可以查看,以PETOOLS为例),如图所示:输入表目录

只找到一个和时间有关的函数GetSystemTimeAsFileTime。我们可以通过od自带的api断点,去断下GetSystemTimeAsFileTime这个函数,

Enter进入,在系统领空下段,运行程序,会断在这个函数的系统领空,之后ctrl+F9执行到返回到,call GetSystemTimeAsFileTime的调用,再ctrl+F9执行到返回,来到如下关键代码处:

可见通过上面call函数clock的调用,返回值去和10比较,来判断程序运行的时间,修改跳转或者修改A的值即可实现破解。

以上就是关于单片机电子时钟直接设置定时时间,并实时显示剩余时间全部的内容,包括:单片机电子时钟直接设置定时时间,并实时显示剩余时间、我想知道AT89C51单片机电子时钟一个可以任意设定时间的程序、S7-200设备每天特定时间定时启停怎么实现等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

原文地址: http://outofmemory.cn/zz/10633867.html

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

发表评论

登录后才能评论

评论列表(0条)

保存