用C语言编写AT89C51单片机程序,设计一个智能数字钟。

用C语言编写AT89C51单片机程序,设计一个智能数字钟。,第1张

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

sbit QB1=P1^0

sbit QB2=P1^1 //数码管段选

sbit QB3=P1^2

sbit QB4=P1^3

sbit QB5=P1^4

sbit QB6=P1^5

sbit fm=P1^6//蜂鸣器

sbit s1=P2^4//s5按键,切换显示

sbit s2=P2^3//s2按键,设置调时

sbit s3=P2^2//s3按键,加1

sbit s4=P2^1//s4按键,减1

sbit led1=P0^0

sbit led2=P0^1

sbit led3=P0^2

uchar count

uchar sec,minu,hour,day,week,mon

uchar n_sec,n_minu,n_hour

uint year

uchar set_2=1,set_1=1

uchar hs,hg,mis,mig,ss,sg

uchar nhs,nhg,nms,nmg,nss=0,nsg=0

uchar ms,mg,ds,dg,w

uchar code table[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,

0X90,0X88,0X83,0XC6,0XA1,0X8E,0X86,0xbf}//0~F,-,共阳

//uchar code tableyi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,

//0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40}//0-F,-,共阴

uchar code table_d[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,

0x87,0xff,0xef}//0~9数组,带小数点

uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}//闰年

uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}//非闰年

void delay(uint)//延时函数

void timer0()//走时中断函数

void jishi()//计时函数

void key_change()//切换显示按键函数

void key_set()//设置时间按键函数

void disp(uchar,uchar,uchar,uchar,uchar,uchar)//显示函数

void zd_clock()//整点报时函数

void nz_clock()//闹钟函数

uchar incone(uchar)//加1函数

uchar decone(uchar)//减1函数

void set_time()//设置时间函数

void set_clock()//设置闹钟函数

void set_mdw()//设置月日星期函数

void main() //主函数

{

EA=1

ET0=1

TR0=1

TMOD=0x01

TH0=0x4c//50ms初值 晶振11.0592

TL0=0x00

hour=23minu=59sec=49//赋初值:11点59分0秒

n_hour=12n_minu=56n_sec=0//闹钟赋初值12点1分0秒

year=2008mon=5day=14week=3//年月日星期赋初值2008年5月11日星期天;祝天下所有母亲节日快乐

while(1)

{

hs=hour/10//时分秒HH.MM.SS

hg=hour%10

mis=minu/10

mig=minu%10

ss=sec/10

sg=sec%10

ms=mon/10//月日-星期MM.DD.-W

mg=mon%10

ds=day/10

dg=day%10

w=week

nhs=n_hour/10//闹钟定时HH.MM.SS

nhg=n_hour%10

nms=n_minu/10

nmg=n_minu%10

nss=n_sec/10

nsg=n_sec%10

key_change()//s4按键扫描

key_set()//s2按键扫描

set_time()//设置时间

set_mdw()//设置月日星期

set_clock()//设置闹钟

if(set_1==1) //正常走时显示

{

disp(hs,hg,mis,mig,ss,sg)

}

if(set_1==2) //设置时间,LED1闪亮

{

disp(hs,hg,mis,mig,ss,sg)

if(sec%2==0)

{led2=1led3=1led1=~led1}

// else

// {led1=1}

}

if(set_1==3) //正常显示月日-星期

{

disp(ms,mg,ds,dg,16,w)

}

if(set_1==4) //设置月日-星期,LED2闪亮

{

disp(ms,mg,ds,dg,16,w)

if(sec%2==0)

{led1=1led3=1led2=~led2}

// else

// {led2=1}

}

if(set_1==5) //正常显示定时

{

disp(nhs,nhg,nms,nmg,nss,nsg)

}

if(set_1==6) //设置闹钟定时,LED3闪亮

{

disp(nhs,nhg,nms,nmg,nss,nsg)

if(sec%2==0)

{led1=1led2=1led3=~led3}

// else

// {led3=1}

}

zd_clock()//整点报时

nz_clock()//闹钟

}

}

void timer0() interrupt 1 //50ms中断函数

{

TMOD=0x01

TH0=0x4c//50ms初值 晶振11.0592

TL0=0x00

count++

if(count==20)

{

count=0

sec++

jishi()//调计时函数

}

}

void jishi() //计时函数

{

if(sec==60)

{

sec=0

minu++

if(minu==60)

{

minu=0

hour++

if(hour==24)

{ hour=0

day++

week++

if(week==8)

{week=0}

if(year%4==0&&year%100!=0||year%400==0) //闰年

{

if(day==table1[mon]+1)

{

day=0

mon++

if(mon==13)

{mon=0year++}

}

}

else //非闰年

{

if(day==table2[mon]+1)

{

day=0

mon++

if(mon==13)

{mon=0year++}

}

}

}

}

}

}

void key_change() //s1按键扫描

{

if(s1==0)

{

delay(200)

if(s1==0)

{

set_1++

while(!s1)

if(set_1==7)

{set_1=1}

}

}

}

void key_set() //s2按键扫描

{

if(s2==0)

{

delay(10)

if(s2==0)

{

set_2++

while(!s2)

if(set_2==4)

{set_2=1}

}

}

}

void disp(uchar a1,uchar a2,uchar a3,uchar a4,uchar a5,uchar a6) //显示函数

{

QB1=1

QB2=0

QB3=0

QB4=0

QB5=0

QB6=0

P3=table[a1]//段码送P0口

delay(10)//延时一小会

QB1=0

QB2=1

QB3=0

QB4=0

QB5=0

QB6=0

P3=table[a2]//第2个数码管显示,带小数点

delay(10)

QB1=0

QB2=0

QB3=1

QB4=0

QB5=0

QB6=0

P3=table[a3]//第3个数码管显示

delay(10)

QB1=0

QB2=0

QB3=0

QB4=1

QB5=0

QB6=0

P3=table[a4]//第4个数码管显示,带小数点

delay(10)

QB1=0

QB2=0

QB3=0

QB4=0

QB5=1

QB6=0

//第5个数码管显示

P3=table[a5]

delay(10)

QB1=0

QB2=0

QB3=0

QB4=0

QB5=0

QB6=1

P3=table[a6]//第6个数码管显示

delay(10)

QB1=0

QB2=0

QB3=0

QB4=0

QB5=0

QB6=0

}

void zd_clock() //整点报时函数

{

if(minu==59&&(sec==53||sec==55||sec==57))

{

fm=0

delay(5)

fm=1

delay(5)

}

fm=0

if(minu==59&&sec==59)

{

fm=0

delay(5)

fm=1

delay(5)

fm=0

}

}

void nz_clock() //闹钟函数

{

if(hour==n_hour&&minu==n_minu&&sec==n_sec)

//if((sec%2==0)&&sec<30)

{

fm=0

delay(1)

fm=1

delay(1)

}

}

void set_time() //设置时间函数

{

if(set_1==2)

{

if(set_2==1)

{

hour=incone(hour)

if(hour==24)

{hour=0}

// if(hour<0)

// {hour=23}

hour=decone(hour)

}

if(set_2==2)

{

minu=incone(minu)

if(minu==60)

{minu=0}

// if(minu<0)

// {minu=59}

minu=decone(minu)

}

}

}

void set_mdw() //设置月日星期函数

{

if(set_1==4)

{

if(set_2==1)

{

mon=incone(mon)

if(mon==13)

{mon=1}

mon=decone(mon)

// if(mon==0)

// {mon=12}

}

if(set_2==2)

{

day=incone(day)

if(day==32)

{day=0}

day=decone(day)

// if(day==0)

// {day=0}

}

if(set_2==3)

{

week=incone(week)

if(week==8)

{week=0}

week=decone(week)

// if(week==0)

// {week=7}

}

}

}

void set_clock() //设置闹钟函数

{

if(set_1==6)

{

if(set_2==1)

{

n_hour=incone(n_hour)

if(n_hour==24)

{n_hour=0}

n_hour=decone(n_hour)

if(n_hour==0)

{n_hour=0}

}

if(set_2==2)

{

n_minu=incone(n_minu)

if(n_minu==60)

{n_minu=0}

n_minu=decone(n_minu)

if(n_minu==0)

{n_minu=0}

}

}

}

uchar incone(uchar n) //加1函数

{

if(s3==0)

{ delay(200)

if(s3==0)

{

n++

while(!s3)

}

}

return(n)

}

uchar decone(uchar m) //减1函数

{

if(s4==0)

{

delay(200)

if(s4==0)

{

m--

while(!s4)

if(m<0)

{m=0}

}

}

return(m)

}

void delay(uint k) //延时函数

{

uint i,j

for(i=ki>0i--)

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

}

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

}


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

原文地址:https://54852.com/yw/11816361.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存