⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 traffic.c

📁 This program is a simple Traffic Light Controller. Between start time and end time the system contro
💻 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 + -