?? traffic.c
字號:
/*****************************************************************************/
/* TRAFFIC.C: 使用C51編譯器的交通信號燈控制器 */
/*****************************************************************************/
code char menu[] =
"\n"
"+***** TRAFFIC LIGHT CONTROLLER using C51 and RTX-51 tiny *****+\n"
"| This program is a simple Traffic Light Controller. Between |\n"
"| start time and end time the system controls a traffic light |\n"
"| with pedestrian self-service. Outside of this time range |\n"
"| the yellow caution lamp is blinking. |\n"
"+ command -+ syntax -----+ function ---------------------------+\n"
"| Display | D | display times |\n"
"| Time | T hh:mm:ss | set clock time |\n"
"| Start | S hh:mm:ss | set start time |\n"
"| End | E hh:mm:ss | set end time |\n"
"+----------+-------------+-------------------------------------+\n";
#include <reg52.h> /* 8052單片機(jī)特殊功能寄存器定義 */
#include <rtx51tny.h> /* RTX-51 tiny 功能函數(shù)定義 */
#include <stdio.h> /* 標(biāo)準(zhǔn) I/O 頭文件 */
#include <ctype.h> /* 字符函數(shù)頭文件 */
#include <string.h> /* 字符串及存儲器函數(shù)頭文件 */
extern getline (char idata *, char); /* 外部函數(shù): 行輸入 */
extern serial_init (); /* 外部函數(shù): 串行口初始化 */
#define INIT 0 /* 任務(wù)0: 初始化 */
#define COMMAND 1 /* 任務(wù)1: 命令 */
#define CLOCK 2 /* 任務(wù)2: 時鐘 */
#define BLINKING 3 /* 任務(wù)3: 閃爍 */
#define LIGHTS 4 /* 任務(wù)4: 信號 */
#define KEYREAD 5 /* 任務(wù)5: 讀鍵 */
#define GET_ESC 6 /* 任務(wù)6: ESC鍵退出 */
struct time { /* 定義時間紀(jì)錄結(jié)構(gòu) */
unsigned char hour; /* 小時 */
unsigned char min; /* 分 */
unsigned char sec; /* 秒 */
};
struct time ctime = { 12, 0, 0 }; /* 存儲時鐘的時間值 */
struct time start = { 7, 30, 0 }; /* 存儲開始時間值 */
struct time end = { 18, 30, 0 }; /* 存儲結(jié)束時間值 */
sbit red = P1^2; /* I/O 腳: 紅燈輸出 */
sbit yellow = P1^1; /* I/O 腳: 黃燈輸出 */
sbit green = P1^0; /* I/O 腳: 綠燈輸出 */
sbit stop = P1^3; /* I/O 腳: stop燈輸出 */
sbit walk = P1^4; /* I/O 腳: walk燈輸出 */
sbit key = P1^5; /* I/O 腳: 自助按鍵輸入 */
idata char inline[16]; /* 存儲輸入命令行 */
/*****************************************************************************/
/* 任務(wù)0:初始化 */
/*****************************************************************************/
init () _task_ INIT { /* 程序從這里開始運行 */
serial_init (); /* 初始化串行口 */
os_create_task (CLOCK); /* 啟動時鐘任務(wù) */
os_create_task (COMMAND); /* 啟動命令任務(wù) */
os_create_task (LIGHTS); /* 啟動信號任務(wù) */
os_create_task (KEYREAD); /* 啟動讀鍵任務(wù) */
os_delete_task (INIT); /* 停止初始化任務(wù) */
}
bit display_time = 0; /* 標(biāo)志:信號命令狀態(tài)顯示時間 */
/*****************************************************************************/
/* 任務(wù)2:時鐘 */
/*****************************************************************************/
clock () _task_ CLOCK {
while (1) { /* 時鐘為無限循環(huán) */
if (++ctime.sec == 60) { /* 計算秒值 */
ctime.sec = 0;
if (++ctime.min == 60) { /* 計算分值 */
ctime.min = 0;
if (++ctime.hour == 24) { /* 計算小時值 */
ctime.hour = 0;
}
}
}
if (display_time) { /* 如果命令狀態(tài)為延時 */
os_send_signal (COMMAND); /* 向任務(wù)1發(fā)送信號 */
}
os_wait (K_IVL, 100, 0); /* 等待時間間隔:1秒 */
}
}
struct time rtime; /* 暫存輸入時間 */
/*****************************************************************************/
/* 讀取時間: 將行輸入轉(zhuǎn)換為時間值并存儲 */
/*****************************************************************************/
bit readtime (char idata *buffer) {
unsigned char args;
rtime.sec = 0; /* 預(yù)置秒值為0 */
args = sscanf (buffer, "%bd:%bd:%bd", /* 掃描行輸入 */
&rtime.hour, /* 得到小時、分、秒值 */
&rtime.min,
&rtime.sec);
if (rtime.hour > 23 || rtime.min > 59 || /* 檢查輸入值是否有效 */
rtime.sec > 59 || args < 2 || args == EOF) {
printf ("\n*** ERROR: INVALID TIME FORMAT\n");
return (0);
}
return (1);
}
#define ESC 0x1B /* 定義ESC 鍵代碼 */
bit escape; /* ESC 鍵輸入標(biāo)志 */
/*****************************************************************************/
/* 任務(wù) 6:檢查是否 ESC 鍵輸入 */
/*****************************************************************************/
get_escape () _task_ GET_ESC {
while (1) { /* 無限循環(huán) */
if (_getkey () == ESC) escape = 1; /* 如果ESC 鍵輸入,設(shè)置標(biāo)志 */
if (escape) { /* 如果有ESC 鍵標(biāo)志,發(fā)送信號 */
os_send_signal (COMMAND); /* 到任務(wù)1 */
}
}
}
/******************************************************************************/
/* Task 1 :命令處理器
/******************************************************************************/
command () _task_ COMMAND {
unsigned char i;
printf (menu); /* 顯示命令菜單 */
while (1) {
printf ("\nCommand: "); /* 顯示提示符 */
getline (&inline, sizeof (inline)); /* 獲得命令行輸入 */
for (i = 0; inline[i] != 0; i++) { /* 轉(zhuǎn)換為大寫 */
inline[i] = toupper(inline[i]);
}
for (i = 0; inline[i] == ' '; i++); /* 跳過空格 */
switch (inline[i]) { /* 命令功能處理 */
case 'D': /* 顯示時間命令 */
printf ("Start Time: %02bd:%02bd:%02bd "
"End Time: %02bd:%02bd:%02bd\n",
start.hour, start.min, start.sec,
end.hour, end.min, end.sec);
printf (" type ESC to abort\r");
os_create_task (GET_ESC); /* 在顯示循環(huán)中檢查ESC 鍵 */
escape = 0; /* 清除 ESC 標(biāo)志 */
display_time = 1; /* 置位顯示時間標(biāo)志 */
os_clear_signal (COMMAND); /* 清零懸掛標(biāo)志 */
while (!escape) { /* 當(dāng)無 ESC 鍵輸入時 */
printf ("Clock Time: %02bd:%02bd:%02bd\r", /* 顯示時間 */
ctime.hour, ctime.min, ctime.sec);
os_wait (K_SIG, 0, 0); /* 等待時間變化或 ESC 鍵輸入*/
}
os_delete_task (GET_ESC); /* 不再檢查ESC 鍵 */
display_time = 0; /* 清零顯示時間標(biāo)志 */
printf ("\n\n");
break;
case 'T': /* 設(shè)置時間命令 */
if (readtime (&inline[i+1])) { /* 讀取輸入時間 */
ctime.hour = rtime.hour; /* 并存儲于 ctime 中 */
ctime.min = rtime.min;
ctime.sec = rtime.sec;
}
break;
case 'E': /* 設(shè)置結(jié)束時間命令 */
if (readtime (&inline[i+1])) { /* 讀取輸入時間 */
end.hour = rtime.hour; /* 并存儲于end 中 */
end.min = rtime.min;
end.sec = rtime.sec;
}
break;
case 'S': /* 設(shè)置開始時間命令 */
if (readtime (&inline[i+1])) { /* 讀取輸入時間 */
start.hour = rtime.hour; /* 并存儲start中 */
start.min = rtime.min;
start.sec = rtime.sec;
}
break;
default: /* 錯誤處理 */
printf (menu); /* 顯示命令菜單 */
break;
}
}
}
/*****************************************************************************/
/* 信號函數(shù): 檢查時鐘時間是否在start與end 之間 */
/*****************************************************************************/
bit signalon () {
if (memcmp (&start, &end, sizeof (struct time)) < 0) {
if (memcmp (&start, &ctime, sizeof (struct time)) < 0 &&
memcmp (&ctime, &end, sizeof (struct time)) < 0) return (1);
}
else {
if (memcmp (&end, &ctime, sizeof (start)) > 0 &&
memcmp (&ctime, &start, sizeof (start)) > 0) return (1);
}
return (0); /* 信號結(jié)束,開始閃爍 */
}
/*****************************************************************************/
/* 任務(wù) 3 閃爍: 如果當(dāng)前時間位于 start 和 end之外則啟動本任務(wù) */
/*****************************************************************************/
blinking () _task_ BLINKING { /* 閃爍黃燈 */
red = 0; /* 熄滅所有燈 */
yellow = 0;
green = 0;
stop = 0;
walk = 0;
while (1) {
yellow = 1; /* 黃燈亮 */
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
yellow = 0; /* 黃燈滅 */
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
if (signalon ()) { /* 如果閃爍時間到 */
os_create_task (LIGHTS); /* 啟動任務(wù)4:點亮燈 */
os_delete_task (BLINKING); /* 并停止任務(wù)3:停止閃爍 */
}
}
}
/*****************************************************************************/
/* 任務(wù) 4 信號: 如果當(dāng)前時間位于 start 和 end 之間則啟動本任務(wù) */
/*****************************************************************************/
lights () _task_ LIGHTS {
red = 1; /* 點亮紅燈和 stop 燈 */
yellow = 0;
green = 0;
stop = 1;
walk = 0;
while (1) {
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
if (!signalon ()) { /* 如果信號時間到 */
os_create_task (BLINKING); /* 啟動任務(wù)3:開始閃爍 */
os_delete_task (LIGHTS); /* 停止任務(wù)4:停止亮燈 */
}
yellow = 1;
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
red = 0; /* 為汽車點亮綠燈 */
yellow = 0;
green = 1;
os_clear_signal (LIGHTS);
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
os_wait (K_TMO + K_SIG, 250, 0); /* 等待超時和信號 */
yellow = 1;
green = 0;
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
red = 1; /* 為汽車點亮紅燈 */
yellow = 0;
os_wait (K_TMO, 30, 0); /* 等待超時: 30個時鐘節(jié)拍 */
stop = 0; /* 為行人點亮綠燈 */
walk = 1;
os_wait (K_TMO, 100, 0); /* 等待超時: 100個時鐘節(jié)拍 */
stop = 1; /* 為行人點亮紅燈 */
walk = 0;
}
}
/*****************************************************************************/
/* 任務(wù) 5 按鍵輸入: 處理行人按鍵輸入 */
/*****************************************************************************/
keyread () _task_ KEYREAD {
while (1) {
if (key) { /* 若有鍵按下 */
os_send_signal (LIGHTS); /* 向任務(wù)4發(fā)送信號 */
}
os_wait (K_TMO, 2, 0); /* 等待超時: 2個時鐘節(jié)拍 */
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -