?? mod1.c
字號:
#include <reg51.h>
#include <absacc.h>
#include <string.h>
#include <intrins.h>
#include <ctype.h>
#include <stdlib.h>
#define Uchar unsigned char
#define Uint unsigned int
#define Ulong unsigned long
/* 定義8155的I/O端口地址 */
#define P8155CW 0x7f00 /* 8155命令口地址 */
#define P8155IA 0x7f01 /* 8155的PA口地址 */
#define P8155IB 0x7f02 /* 8155的PB口地址 */
#define P8155IC 0x7f03 /* 8155的PC口地址 */
/* 定義定時器T0的時間常數值和方式控制字 */
#define V_TH0 0x9e /* 時間常數高8位 */
#define V_TL0 0x75 /* 時間常數低8位 */
#define V_TMOD 0x01 /* 定時器T0方式控制字 */
/* 定義LED顯示字符段碼 */
static struct {
Uchar ascii;
Uchar stroke;
} code led_strokes[27] =\
{{'0',0x3f}, {'1',0x06}, {'2',0x5b}, {'3',0x4f}, {'4',0x66},\
{'5',0x6d}, {'6',0x7d}, {'7',0x07}, {'8',0x7f}, {'9',0x6f},\
{'A',0x77}, {'B',0x7c}, {'C',0x39}, {'D',0x5e}, {'E',0x79},\
{'F',0x71}, {'H',0x76}, {'O',0x5c}, {'P',0x73}, {'U',0x3e},\
{'R',0x50}, {'Y',0x6e}, {'.',0x80}, {'-',0x40}, {'=',0x48},\
{0x00,0x00}, {0xff,0xff}};
/* 定義非閏年每月的天數 */
Uchar code days_month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
struct TIME { /* 定義時間結構 */
Uchar sec;
Uchar min;
Uchar hour;
};
struct DATE { /* 定義日期結構 */
Uchar year;
Uchar month;
Uchar day;
};
struct TIME time;
struct DATE date;
/* 定義一組全局變量和函數原型 */
Uchar bdata flag;
sbit time_init=flag^0;
sbit auto_flush=flag^1;
sbit message_flag=flag^2;
Uint message_time;
Uchar led_buf[8];
extern void delay(Uint);
void led_buf_auto_flush(void) reentrant;
bit leap_year(void) reentrant;
void init_sys(void);
void monitor(void);
void set_led_buf(Uchar,Uchar,Uchar);
Uchar get_strokes(Uchar);
void put_on_leds(void);
void put_off_leds(void);
bit kb_hit(void);
Uchar get_ch(void);
Uchar * get_str(Uchar *, Uint);
void ask_date(void);
bit set_date_time(void);
void error_message(void);
/**************************************************************************
* 函數原型: main();
* 功 能: 調用init_sys()函數對系統進行初始化, 調用monitor()函數對
* 用戶輸入的鍵盤命令進行解釋。
/*************************************************************************/
main() {
init_sys();
monitor();
}
/**************************************************************************
* 函數原型: void init_sys(void);
* 功 能: 對系統進行初始化并接受用戶的的初始化日期時間設置
**************************************************************************/
void init_sys(void) {
/* 8155初始化 */
XBYTE[P8155CW]=0x03; XBYTE[P8155IA]=0xff; XBYTE[P8155IB]=0xff;
/* 定時器T0初始化 */
TMOD=V_TMOD; TH0=V_TH0; TL0=V_TL0;
TR0=1; ET0=1; EA=1;
/* 標志變量初始化 */
time_init=0; auto_flush=0; message_flag=0; message_time=0;
/* 顯示8個"-"直到用戶按下"0"鍵并成功設置初始化日期時間為止 */
set_led_buf('-',0,8); /* 用"-"填充顯示緩沖區 */
while(1) {
put_on_leds(); /* 顯示緩沖區當前的內容 */
if(!get_ch()) continue; /* 如果用戶按下的不是"0"鍵 */
if(! set_date_time()) /* 如果日期時間初始化不成功 */
set_led_buf('-',0,8);
else
break;
}
}
/**************************************************************************
* 函數原型: void monitor(void);
* 功 能: 用當前的時、分、秒值自動刷新LED顯示, 并對用戶按鍵進行解釋。
* "0"鍵表示校正日期和時間, 如果校時成功則動態顯示時間, 否則
* 顯示出錯信息"ERROR"。"1"鍵表示查詢并顯示當前日期。在顯示出
* 錯信息"ERROR"期間, 按任意鍵可清除顯示, 否則10秒后自動恢復
* 動態時間顯示。
**************************************************************************/
void monitor(void) {
Uchar command;
while(1) {
put_on_leds(); /* 顯示緩沖區當前內容 */
if(message_time==0) { /* 如果日期或出錯信息顯示時間為0秒 */
message_flag=0; /* 清除錯誤信息顯示標志 */
auto_flush=1; /* 設置用當前時間自動刷新緩沖區標志*/
}
if((command=get_ch())) { /* 如果有鍵按下 */
message_flag=0; /* 清除錯誤信息顯示標志 */
message_time=0; /* 設置錯誤信息顯示時間為0秒 */
}
switch(command) { /* 對鍵盤命令進行解釋 */
case'0':if(!set_date_time()) /* 如果校時不成功 */
error_message(); /* 顯示錯誤信息"ERROR" */
break;
case'1':ask_date(); /* 查詢當前日期 */
break;
default : break;
}
}
}
/**************************************************************************
* 函數原型: void timer0(void);
* 功 能: 定時器T0中斷服務函數。每次執行時先重裝時間常數, 然后檢查日
* 期和時間是否已經初始化, 如果未初始化則立即返回, 否則每中斷
* 20次(即一秒鐘)根據信息顯示標志的設置來決定是否將日期或錯誤
* 信息顯示時間減1, 然后自動修改日期和時間結構。如果緩沖區自動
* 刷新標志為1, 則用當前時間刷新顯示緩沖區。
**************************************************************************/
void timer0(void) interrupt 1 using 2 {
static Uchar click=0; /* 中斷次數計數器變量 */
/* 重裝定時器T0時間常數 */
TH0=V_TH0; TL0=V_TL0;
if(!time_init) return; /* 如果日期時間未初始化, 返回 */
++click;
if(click>=20) { /* 間隔1秒鐘(20*50ms=1s) */
click=0;
/* 根據消息顯示標志決定是否將消息顯示時間減少1秒 */
if(message_flag && message_time) --message_time;
/* 計算并修改時間和日期 */
if(++time.sec>=60) {
time.sec=0;
if(++time.min>=60) {
time.min=0;
if(++time.hour>=24) {
time.hour=0;
if(++date.day>days_month[date.month]) {
if(date.month==2 && leap_year());
else date.day=1;
if(++date.month>12) {
date.month=1;
++date.year;
}
}
}
}
}
/* 如果已設置緩沖區自動刷新標志, 則用當前時間刷新顯示緩沖區 */
if(auto_flush) led_buf_auto_flush();
}
}
/**************************************************************************
* 函數原型: void led_buf_auto_flush(void) ;
* 功 能: 用當前時間的時、分、秒值填充顯示緩沖區。
**************************************************************************/
void led_buf_auto_flush(void) reentrant {
led_buf[0]=time.sec%10+0x30;
led_buf[1]=time.sec/10+0x30;
led_buf[2]='-';
led_buf[3]=time.min%10+0x30;
led_buf[4]=time.min/10+0x30;
led_buf[5]='-';
led_buf[6]=time.hour%10+0x30;
led_buf[7]=time.hour/10+0x30;
}
/**************************************************************************
* 函數原型: bit leap_year(void);
* 功 能: 判斷某年是否為閏年, 若是閏年則返回1, 否則返回0。
**************************************************************************/
bit leap_year(void) reentrant {
if(date.year%4==0 && date.year%100 != 0) return((bit)1);
if(date.year%400==0) return((bit)1);
return((bit)0);
}
/**************************************************************************
* 函數原型: void set_led_buf(Uchar c, Uchar pos, Uchar cnt);
* 功 能: 從顯示緩沖區的pos位置開始, 用字符c填充cnt個字節。
**************************************************************************/
void set_led_buf(Uchar c,Uchar pos, Uchar cnt) {
Uchar ledbuf_pos;
auto_flush=0; /* 在填充期間關閉LED顯示器 */
for(ledbuf_pos=pos; cnt>0; cnt--) {
led_buf[ledbuf_pos]=((islower(c)) ? (toupper(c)) : (c));
ledbuf_pos++;
if(ledbuf_pos>=8) ledbuf_pos=0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -