📄 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单片机特殊功能寄存器定义 */
#include <rtx51tny.h> /* RTX-51 tiny 功能函数定义 */
#include <stdio.h> /* 标准 I/O 头文件 */
#include <ctype.h> /* 字符函数头文件 */
#include <string.h> /* 字符串及存储器函数头文件 */
extern getline (char idata *, char); /* 外部函数: 行输入 */
extern serial_init (); /* 外部函数: 串行口初始化 */
#define INIT 0 /* 任务0: 初始化 */
#define COMMAND 1 /* 任务1: 命令 */
#define CLOCK 2 /* 任务2: 时钟 */
#define BLINKING 3 /* 任务3: 闪烁 */
#define LIGHTS 4 /* 任务4: 信号 */
#define KEYREAD 5 /* 任务5: 读键 */
#define GET_ESC 6 /* 任务6: ESC键退出 */
struct time {
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 }; /* 存储结束时间值 */
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]; /* 存储输入命令行 */
/*****************************************************************************/
/* 任务0:初始化 */
/*****************************************************************************/
init () _task_ INIT { /* 程序从这里开始运行 */
serial_init (); /* 初始化串行口 */
os_create_task (CLOCK); /* 开始时钟任务 */
os_create_task (COMMAND); /* 开始命令任务 */
os_create_task (LIGHTS); /* 开始信号任务 */
os_create_task (KEYREAD); /* 开始读键任务 */
os_delete_task (INIT); /* 停止初始化任务 */
}
bit display_time = 0; /* flag: signal cmd state display_time */
/*****************************************************************************/
/* 任务2:时钟 */
/*****************************************************************************/
clock () _task_ CLOCK {
while (1) { /* 时钟为无限循环 */
if (++ctime.sec == 60) { /* 计算秒值 */
ctime.sec = 0;
if (++ctime.min == 60) { /* 计算分值 */
ctime.min = 0;
if (++ctime.hour == 24) { /* 计算小时值 */
ctime.hour = 0;
}
}
}
if (display_time) { /* 如果命令状态为延时 */
os_send_signal (COMMAND); /* 向任务1发送信号 */
}
os_wait (K_IVL, 100, 0); /* 等待时间间隔:1秒 */
}
}
struct time rtime; /* 暂存输入时间 */
/*****************************************************************************/
/* 读取时间: 将行输入转换为时间值并存储 */
/*****************************************************************************/
bit readtime (char idata *buffer) {
unsigned char args;
rtime.sec = 0; /* 预置秒值为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 键输入标志 */
/*****************************************************************************/
/* 任务 6:检查是否 ESC 键输入 */
/*****************************************************************************/
get_escape () _task_ GET_ESC {
while (1) { /* 无限循环 */
if (_getkey () == ESC) escape = 1; /* 如果ESC 键输入,设置标志 */
if (escape) { /* 如果有ESC 键标志,发送信号 */
os_send_signal (COMMAND); /* 到任务1 */
}
}
}
/******************************************************************************/
/* Task 1 'command': command processor */
/******************************************************************************/
command () _task_ COMMAND {
unsigned char i;
printf (menu); /* 显示命令菜单 */
while (1) {
printf ("\nCommand: "); /* 显示提示符 */
getline (&inline, sizeof (inline)); /* 获得命令行输入 */
for (i = 0; inline[i] != 0; i++) { /* 转换为大写 */
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); /* 在显示循环中检查ESC 键 */
escape = 0; /* 清除 ESC 标志 */
display_time = 1; /* 置位显示时间标志 */
os_clear_signal (COMMAND); /* 清零悬挂标志 */
while (!escape) { /* 无 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; /* 清零显示时间标志 */
printf ("\n\n");
break;
case 'T': /* 设置时间命令 */
if (readtime (&inline[i+1])) { /* 读取输入时间 */
ctime.hour = rtime.hour; /* 并存储于 ctime 中 */
ctime.min = rtime.min;
ctime.sec = rtime.sec;
}
break;
case 'E': /* 设置结束时间命令 */
if (readtime (&inline[i+1])) { /* 读取输入时间 */
end.hour = rtime.hour; /* 并存储于 end 中 */
end.min = rtime.min;
end.sec = rtime.sec;
}
break;
case 'S': /* 设置开始时间命令 */
if (readtime (&inline[i+1])) { /* 读取输入时间 */
start.hour = rtime.hour; /* 并存储于start 中 */
start.min = rtime.min;
start.sec = rtime.sec;
}
break;
default: /* 错误处理 */
printf (menu); /* 显示命令菜单 */
break;
}
}
}
/*****************************************************************************/
/* 信号函数: 检查时钟时间是否在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); /* 信号结束,开始闪烁 */
}
/*****************************************************************************/
/* 任务 3 闪烁: 如果当前时间位于 start 和 end之外 即开始本任务 */
/*****************************************************************************/
blinking () _task_ BLINKING { /* 闪烁黄灯 */
red = 0; /* 熄灭所有灯 */
yellow = 0;
green = 0;
stop = 0;
walk = 0;
while (1) {
yellow = 1; /* 黄灯亮 */
os_wait (K_TMO, 30, 0); /* 等待 timeout: 30 个脉冲脉冲 */
yellow = 0; /* 黄灯灭 */
os_wait (K_TMO, 30, 0); /* 等待 timeout: 30 个脉冲脉冲 */
if (signalon ()) { /* 如果闪烁时间到 */
os_create_task (LIGHTS); /* 开始任务4 */
os_delete_task (BLINKING); /* 并停止任务3:闪烁 */
}
}
}
/*****************************************************************************/
/* 任务 4 信号: 如果当前时间位于 start 和 end 之间则开始本任务 */
/*****************************************************************************/
lights () _task_ LIGHTS {
red = 1; /* 点亮红灯和 stop 灯 */
yellow = 0;
green = 0;
stop = 1;
walk = 0;
while (1) {
os_wait (K_TMO, 30, 0); /* 等待timeout: 30个时钟脉冲 */
if (!signalon ()) { /* 如果信号时间到 */
os_create_task (BLINKING); /* 开始任务3:闪烁 */
os_delete_task (LIGHTS); /* 停止任务4:信号 */
}
yellow = 1;
os_wait (K_TMO, 30, 0); /* 等待timeout: 30个时钟脉冲 */
red = 0; /* 为汽车点亮绿灯 */
yellow = 0;
green = 1;
os_clear_signal (LIGHTS);
os_wait (K_TMO, 30, 0); /* 等待timeout: 30个时钟脉冲 */
os_wait (K_TMO + K_SIG, 250, 0); /* 等待 timeout 和 信号 */
yellow = 1;
green = 0;
os_wait (K_TMO, 30, 0); /* 等待timeout: 30个时钟脉冲 */
red = 1; /* 为汽车点亮红灯 */
yellow = 0;
os_wait (K_TMO, 30, 0); /* 等待timeout: 30个时钟脉冲 */
stop = 0; /* 为行人点亮绿灯 */
walk = 1;
os_wait (K_TMO, 100, 0); /* 等待timeout: 100个时钟脉冲 */
stop = 1; /* 为行人点亮红灯 */
walk = 0;
}
}
/*****************************************************************************/
/* 任务 5 按键输入: 处理行人按键输入 */
/*****************************************************************************/
keyread () _task_ KEYREAD {
while (1) {
if (key) { /* 若有键按下 */
os_send_signal (LIGHTS); /* 向任务4发送信号 */
}
os_wait (K_TMO, 2, 0); /* 等待timeout: 2 个时钟脉冲 */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -