电子时钟程序

电子时钟程序,第1张

//=======主函数==================================

ORG 0000H

LJMP MAIN

ORG000BH

LJMP T00

//ORG001BH

//LJMP T11

ORG 0030H

//=======程序初始化=============================

MAIN:

MOV TMOD,#11H

MOV TH0,#3CH

MOV TL0,#0B0H

MOV TH1,#0F0H

MOV TL1,#0B0H

SETB EA

SETB ET0

// SETB ET1

SETB TR0

// SETB TR1

CLR P3.4

MOV R7,#00H 秒值

MOV 30H,#00H 秒个位

MOV 31H,#00H 秒十位值

MOV 32H,#00H 分个位

MOV 33H,#00H 分十位

MOV 34H,#00H 时个位

MOV 35H,#00H 时十位

MOV 44H,#00H 秒表毫秒十位

MOV 45H,#00H 秒表秒毫秒百位

MOV 46H,#00H 秒表秒个位

MOV 47H,#00H 秒表秒十位

MOV 48H,#00H 秒表分个位

MOV 49H,#00H 秒表分十位

MOV P2,#0F0H P2口按键初始化

MOV 40H,#01H 数码管休眠值 /流水灯/秒表开关数

MOV 41H,#08H 流水灯循环值

MOV 42H,#00H 秒表暂停

// ACALL T11

//-----------------------------------------------

MAIN1:

MOV P0,#0FFH

MOV P1,#0FFH

MOV R0,40H

CJNE R0,#01H,ACL1

ACALL MAIN2时钟显示

ACL1:CJNE R0,#02H,ACL2

ACALL MAIN3秒表

ACL2:CJNE R0,#03H,ACL3

ACALL LED流水灯

ACL3:ACALL KEY 按键扫描

// ACALL BAO定时报警

LJMP MAIN1

//=======报警子程序============================

BAO:MOV R4,33H

CJNE R4,#03H,YY1

CLR P3.2

ACALL KEY

LJMP YY2

YY1:CJNE R4,#05H,YY2

SETB P3.2

ACALL KEY

YY2:RET

//======时钟扫描子程序=======================

MAIN2:

MOV A,30H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.0

ACALL DELAY

MOV A,31H

MOV DPTR,#TAB

MOVC A,@A+ DPTR

MOV P0,A

CLR P1.1

SETB P1.0

ACALL DELAY

MOV A,32H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.2

SETB P1.1

ACALL DELAY

MOV A,33H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.3

SETB P1.2

ACALL DELAY

MOV A,34H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.4

SETB P1.3

ACALL DELAY

MOV A,35H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.5

SETB P1.4

ACALL DELAY

MOV P0,#7FH

MOV P1,#0EBH

ACALL DELAY

MOV P1,#0FFH

RET

//========秒表扫描子程序=========================

MAIN3:

MOV A,44H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.0

ACALL DELAY

MOV A,45H

MOV DPTR,#TAB

MOVC A,@A+ DPTR

MOV P0,A

CLR P1.1

SETB P1.0

ACALL DELAY

MOV A,46H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.2

SETB P1.1

ACALL DELAY

MOV A,47H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.3

SETB P1.2

ACALL DELAY

MOV A,48H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.4

SETB P1.3

ACALL DELAY

MOV A,49H

MOV DPTR,#TAB

MOVC A,@A+DPTR

MOV P0,A

CLR P1.5

SETB P1.4

ACALL DELAY

MOV P0,#7FH

MOV P1,#0EBH

ACALL DELAY

MOV P1,#0FFH

RET

//=======定时器T0中断服务========================

T00:MOV TH0,#0D8H

MOV TL0,#0F0H

INC R7

CJNE R7,#64H,AA

MOV R7,#00H

//-------时钟跑值--------------------------------

TK1:INC 30H 每秒钟秒个位增一

MOV R6,30H

CJNE R6,#0AH,AA

MOV 30H,#00H

TK2:INC 31H

MOV R6,31H

CJNE R6,#06H,AA

MOV 31H,#00H

TK3:INC 32H

MOVR6,32H

CJNE R6,#0AH,AA

MOV32H,#00H

TK4:INC33H

MOVR6,33H

CJNE R6,#06H,AA

MOV33H,#00H

TK5:INC34H

MOVR5,34H

MOVR6,35H

CJNE R5,#04H,TK6

CJNE R6,#02H,TK6

MOV34H,#00H

MOV35H,#00H

TK6:CJNE R5,#0AH,AA

MOV34H,#00H

INC35H

//-------秒表跑值----------------------

AA:

MOV R5,42H

CJNE R5,#01H,TK7

INC 44H

TK7:MOV R5,44H

CJNE R5,#0AH,AA1

MOV 44H,#00H

INC 45H

MOV R5,45H

CJNE R5,#0AH,AA1

MOV 45H,#00H

INC 46H

MOV R5,46H

CJNE R5,#0AH,AA1

MOV 46H,#00H

INC 47H

MOV R5,47H

CJNE R5,#06H,AA1

MOV 47H,#00H

INC 48H

MOV R5,48H

CJNE R5,#0AH,AA1

MOV 48H,#00H

INC 49H

MOV R5,49H

CJNE R5,#06H,AA1

MOV 49H,#00H

AA1:RETI

//====定时器T1中断服务子程序====================

//T11:MOV TH1,#0F0H

// MOV TL1,#0B0H

// RETI

//******定时时间调整子程序*************************//

TBAO:

MOV 50H,#00H

MOV 51H,#00H

MOV 52H,#00H

MOV 53H,#00H

MOV 54H,#00H

MOV 55H,#00H

MOV R3,50H

DJNZ 30H,RET1

RET1: RET

//======键盘扫描子程序==========================

KEY:MOV P2,#0F0H

MOV R3,P2

CJNE R3,#0F0H,KE0

LJMP KK13

KE0:CJNE R3,#0E0H,KE1 P2.4行

MOV P2,#0EFH

JB P2.3,KK1 //用作调定时时间 K13 秒个位增一

ACALL DELAY1

ACALL TK1

KK1:JB P2.2,KK2 K14 秒十增一

ACALL DELAY1

ACALL TK2

KK2:JB P2.1,KK3 K15 分个位增一

ACALL DELAY1

ACALL TK3

KK3:JB P2.0,KE1 K16 分十位增一

ACALL DELAY1

ACALL TK4

KE1:MOV P2,#0DFH P2.5行

JB P2.3,KK4 K9 时个位增一

ACALL DELAY1

ACALL TK5

KK4:JB P2.2,KK5 K10 时十位增一

ACALL DELAY1

INC 35H

MOV R3,35H

CJNE R3,#03H,HH0

MOV 35H,#00H

LJMP KK5

HH0:CJNE R3,#02H,HH1

LJMP KK5

HH1:CJNE R3,#01H,HH2

LJMP KK5

HH2:MOV 35H,#00H

KK5:JB P2.1,KK6

ACALL DELAY1 K11开/关蜂鸣器

CPL P3.2

KK6:JB P2.0,KE2 K12 秒表暂停

MOV 42H,#00H

KE2:MOV P2,#0BFH P.6行

JB P2.3,KK7K5 时钟暂停/取消暂停

ACALL DELAY1

CPL ET0

KK7:JB P2.2,KK8 K6 显示/休眠/流水灯

ACALL DELAY2

INC 40H

MOV R3,40H

CJNE R3,#04H,KK8

MOV 40H,#01H

KK8:JB P2.1,KK9

// ACALL DELAY3 K7 秒表清0

MOV 44H,#00H

MOV 45H,#00H

MOV 46H,#00H

MOV 47H,#00H

MOV 48H,#00H

MOV 49H,#00H

KK9:JB P2.0,KE3 K8 秒表开始跑

MOV 42H,#01H

KE3:MOV P2,#7FH P2.7行

JB P2.3,KK10 K1 秒十位减一

ACALL DELAY1

MOV R3,31H

CJNE R3,#00H,JA1

LJMP KK10

JA1:DEC 31H

KK10:JB P2.2,KK11K2分个位减一

ACALL DELAY1

MOV R3,32H

CJNE R3,#00H,JA2

LJMP KK11

JA2: DEC 32H

KK11:JB P2.1,KK12 K3 分十位减一

ACALL DELAY1

MOV R3,33H

CJNE R3,#00H,JA3

LJMP KK12

JA3:DEC 33H

KK12:JB P2.0,KK13 K4 时个位减一

ACALL DELAY1

MOV R3,34H

CJNE R3,#00H,JA4

LJMP KK13

JA4:DEC 34H

KK13:RET

//=====流水灯子程序===========================

LED: MOV A,#0feH

MOV 41H,#08H

MOV P0,#0FFH

LED1:

MOV P1,A

MOV R3,#100

D0: ACALL DELAY

DJNZ R3,D0

MOV R3,41H

DJNZ R3,AAA

LJMP BB

AAA:RL A

MOV 41H,R3

ACALL KEY

LJMP LED1

BB:

MOV 41H,#07H

CC: MOV P1,A

MOV R3,#30

D1: ACALL DELAY

DJNZ R3,D1

MOV R3,41H

DJNZ R3,DD

LJMP LED0

DD:RR A

MOV 41H,R3

ACALL KEY

LJMP CC

LED0:RET

//=====延时子程序==============================

DELAY:MOV R1,#250

DEL1:NOP

NOP

NOP

NOP

DJNZ R1,DEL1

RET

//====调用时钟显示作延时========================

DELAY1:MOV R2,#20

DELA3: ACALL MAIN2

DJNZ R2,DELA3

RET

//====调用秒表显示作延时========================

DELAY3:MOV R2,#20

DELA5:ACALL MAIN3

DJNZ R2,DELA5

RET

//====调用延时子程序作延时======================

DELAY2:MOV R2,#100

DELA4:ACALL DELAY

DJNZ R2,DELA4

RET

//======共阳数码管段码表=================================

TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,87H

END

1.这是用windows api写的程序。所以要求是纯c的话就没有办法了

2.其中定时用了两种方法。一种是用取消息。另一种是延时队列。这里只使用了取消息的方法。延时队列由于我机器上是vc6.0,CreateTimerQueue在本人机器上无法使用,需要新的sdk,所以没有加以验证,但取消息的方式是可行的。

3.稍稍验证了下,基本满足要求。

-------------------------------------------

程序如下:

// DigitalClock.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include <windows.h>

#include <winbase.h>

typedef struct _st_time{

int hour

int min

int sec

}ST_TIME

ST_TIME g_Time // The struct contain the hour,min and sec.

HANDLE g_hStdout //

WORD g_cxCenter, g_cyCenter // Center of the screen.

HANDLE g_DoneEvent// The program could be over.

BOOL g_ThreadTerminated // The Thread should be terminated.

#define SECOND_CIRCLE 60

#define MINUTE_CIRCLE 60

#define HOUR_CIRCLE 24

void TimeIncreaseSecond(ST_TIME &st)

{

st.sec ++

if (st.sec >= SECOND_CIRCLE)

{

st.sec -= SECOND_CIRCLE

st.min++

if (st.min >= MINUTE_CIRCLE)

{

st.min -= MINUTE_CIRCLE

st.hour++

if (st.hour >= HOUR_CIRCLE)

{

st.hour -= HOUR_CIRCLE

}

}

}

}

void PrintTimeToScreen(HANDLE hStdout, short cxCenter, short cyCenter, ST_TIME st)

{

char buf[64] = {0}

COORD crdPos

// make it format to output.

sprintf (buf, "%02d:%02d:%02d", st.hour, st.min, st.sec)

crdPos.X = cxCenter - 4

crdPos.Y = cyCenter

SetConsoleCursorPosition(hStdout, crdPos)

printf(buf)

}

#ifdef USE_TIMERQUEUE

// if we use the timer queue function.

// Its procdure is in this.

void CALLBACK TimerRoutine (LPVOID lpParam, BOOL TimerOrWaitFired)

{

if (lpParam == NULL)

{

printf ("NULL parameters.\n")

}

else

{

ST_TIME *st = (ST_TIME *)lpParam

TimeIncreaseSecond(st)

PrintTimeToScreen(g_hStdout, g_cxCenter, g_cyCenter, *st)

}

}

#else

DWORD WINAPI TimerThreadProc(LPVOID lpParam)

{

#define ID_TIMER_SECOND 1

MSG msg

BOOL ret

ST_TIME *st = (ST_TIME *)lpParam

SetTimer(NULL, ID_TIMER_SECOND, 1000, NULL)

PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)

while (!g_ThreadTerminated &&(ret = GetMessage (&msg, NULL, 0, 0)) != 0)

{

if (ret == -1)

{

//process fatal event.

}

else if (msg.message == WM_TIMER)

{

TimeIncreaseSecond(*st)

PrintTimeToScreen(g_hStdout, g_cxCenter, g_cyCenter, *st)

}

else

{

TranslateMessage (&msg)

DispatchMessage (&msg)

}

}

return 1

}

#endif

// If the ctrl+break combined key pressed. call this function.

// It set the g_DoneEvent. this terminate the program.

BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)

{

switch (fdwCtrlType)

{

case CTRL_BREAK_EVENT:

// Terminate the program.

printf ("Terminate.\n")

SetEvent(g_DoneEvent)

return TRUE

default:

return FALSE

}

}

BOOL InitApplication()

{

// Get the stdin and stdout handle.

HANDLE hStdIn

hStdIn = GetStdHandle(STD_INPUT_HANDLE)

if (hStdIn == INVALID_HANDLE_VALUE)

return FALSE

g_hStdout = GetStdHandle(STD_OUTPUT_HANDLE)

// Set the mode, make the input echo.

DWORD fOldMode

GetConsoleMode(hStdIn, &fOldMode)

fOldMode |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT

SetConsoleMode(hStdIn, fOldMode)

// Set the window buffer.

// make a line 40 columns.

CONSOLE_SCREEN_BUFFER_INFO csbiInfo

GetConsoleScreenBufferInfo(g_hStdout, &csbiInfo)

csbiInfo.srWindow.Right = 40

// get the center point.

g_cxCenter = csbiInfo.srWindow.Right / 2

g_cyCenter = csbiInfo.srWindow.Bottom / 2

// Set the window.

SetConsoleWindowInfo(g_hStdout, TRUE, &csbiInfo.srWindow)

return TRUE

}

BOOL PrintTheInitalStateAndGetInput(HANDLE hStdout, WORD cxCenter, WORD cyCenter, ST_TIME &time)

{

#define GAPS_LEFT_COLON (-2)

#define GAPS_RIGHT_COLON (1)

#define GAPS_LEFT_UNDERLINE_START (-4)

#define GAPS_MIDDLE_UNDERLINE_START (-1)

#define GAPS_RIGHT_UNDERLINE_START (2)

// __:__:__

// So the left ":" center -2

// so the right ":" center + 1

// so the left "_" center - 4

// so the lfet "_" center - 1

// so the right "_" center + 2

COORD crdPos

crdPos.X = cxCenter + GAPS_LEFT_COLON

crdPos.Y = cyCenter

SetConsoleCursorPosition(hStdout, crdPos)

printf (":")

crdPos.X = cxCenter + GAPS_RIGHT_COLON

SetConsoleCursorPosition(hStdout, crdPos)

printf (":")

crdPos.X = cxCenter + GAPS_LEFT_UNDERLINE_START

SetConsoleCursorPosition(hStdout, crdPos)

scanf ("%d", &time.hour)

crdPos.X = cxCenter + GAPS_MIDDLE_UNDERLINE_START

SetConsoleCursorPosition(hStdout, crdPos)

scanf ("%d", &time.min)

crdPos.X = cxCenter + GAPS_RIGHT_UNDERLINE_START

SetConsoleCursorPosition(hStdout, crdPos)

scanf ("%d", &time.sec)

if (time.hour <0 || time.hour >HOUR_CIRCLE ||

time.min <0 || time.min >MINUTE_CIRCLE ||

time.sec <0 || time.sec >SECOND_CIRCLE)

return FALSE

return TRUE

}

int main(int argc, char* argv[])

{

InitApplication()

PrintTheInitalStateAndGetInput(g_hStdout, g_cxCenter, g_cyCenter, g_Time)

// create a event to tell the program to terminate.

g_DoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL)

#ifdef USE_TIMERQUEUE

HANDLE hTimerQueue, hTimer

hTimerQueue = CreateTimerQueue()

if (!CreateTimerQueueTimer(&hTimer,

hTimerQueue, TimerRoutine, &g_Time, 1000, 0, 0))

{

printf("CreateTimerQueueTimer failed (%d)\\n", GetLastError())

return 3

}

#else

// create the thread.

HANDLE hThreadTimer

DWORD dwThreadId

g_ThreadTerminated = FALSE

hThreadTimer = CreateThread(NULL, 0,

TimerThreadProc, &g_Time, 0, &dwThreadId)

if (hThreadTimer == NULL)

{

}

#endif

SetConsoleCtrlHandler(CtrlHandler, TRUE)

if (WaitForSingleObject(g_DoneEvent, INFINITE) != WAIT_OBJECT_0)

printf("WaitForSingleObject failed (%d)\\n", GetLastError())

#ifdef USE_TIMERQUEUE

if (!DeleteTimerQueue(hTimerQueue))

printf("DeleteTimerQueue failed(%d) \\n", GetLastError())

#else

g_ThreadTerminated = TRUE

if (WaitForSingleObject(hThreadTimer, INFINITE) != WAIT_OBJECT_0)

printf("WaitForSingleObject failed (%d)\\n", GetLastError())

#endif

return 0

}

--------------------------------------------

下面是纯c的。

有几个问题:

1.textmode函数在turboc中没有办法使用,不知道是什么问题,而borland c就可以。

2.无论怎么设置,自己的ctrlbreak函数在上述两个环境中都不能被调用,非常遗憾。所以不能够优雅的退出。只能按两次ctrlbreak。

下面是程序。

------------------------------------------

#include <stdio.h>

#include <stdlib.h>

#include <stdio.h>

#include <conio.h>

#include <dos.h>

#define ABORT 0

int jump_out_loop = -1

int jump_out(void)

{

jump_out_loop = 1

printf("Abort ..\n")

return ABORT

}

int main(void)

{

struct text_info ti

int center_x, center_y

int hour, min, sec

char str_out[64] = {0}

clrscr()

/*textmode(BW40)*/

/*textmode在turbo c下设置会出问题*/

gettextinfo(&ti)

center_x = ti.winright / 2

center_y = ti.winbottom / 2

gotoxy(center_x - 4, center_y)

cprintf(" : : ")

gotoxy(center_x - 4, center_y)

cscanf("%d", &hour)

gotoxy(center_x - 1, center_y)

cscanf("%d", &min)

gotoxy(center_x + 2, center_y)

cscanf("%d", &sec)

/* check input valid or not */

{}

setcbrk(1)

ctrlbrk(jump_out)

/*jump_out没有起到作用,实在不好意思.*/

/*

if (getcbrk())

printf("crtl break is on\n")

else

printf("is off\n")

*/

while (1)

{

delay(1000)

sec++

if (sec >= 60)

{

sec -= 60

min++

if (min >= 60)

{

min -= 60

hour++

if (hour >= 24)

{

hour -= 24

}

}

}

sprintf(str_out, "%02d:%02d:%02d", hour, min, sec)

gotoxy(center_x - 4, center_y)

cprintf(str_out)

}

/* getch()*/

return 0

}


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存