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

📄 traffic.c

📁 51单片机开发与应用技术详解(珍藏版)PPT及源码
💻 C
字号:
#include <reg52.h>                    		//头文件
#include <rtx51tny.h> 
#include <stdio.h> 
#include <ctype.h> 
#include <string.h> 

code char sysmenu[] = 					//系统命令菜单
   "\n"
   "+*** TRAFFIC LIGHT CONTROLLER using AT89S52 and RTX-51 Tiny ***+\n"
   "+ 命令 ----+ 格式 -------+ 功能 -------------------------------+\n"
   "| Display  | D           | 显示时间                            |\n"
   "| Time     | T hh:mm:ss  | 设置时钟时间                        |\n"
   "| start_time    | S hh:mm:ss  | 设置起始时间                        |\n"
   "| end_time      | E hh:mm:ss  | 设置结束时间                        |\n"
   "+----------+-------------+-------------------------------------+\n";

idata    char inline[16];             		//存储输入命令行

#define uchar unsigned char				//宏定义

extern getline (char idata *, char);  			//外部函数声明:,用于行输入
extern init_serial ();                		//外部函数:声明,用于初始化串行口

#define INIT      0                   		//任务0:  初始化系统
#define COMMAND   1                   	//任务1:  命令处理
#define CLK     2                   		//任务2:  时钟控制
#define BLINKING  3                   	//任务3:  黄色灯闪烁
#define LIGHTS    4                   	//任务4:  交通灯工作
#define buttonREAD   5                   	//任务5:  读取行人按钮
#define GET_ESC   6                   	//任务6:  退出

#define ESC  0x1B                        //定义ESC 键代码

struct time  {                        		//定义时间结构
  uchar hour;                 			//小时
  uchar min;                  			//分
  uchar sec;                  			//秒
};

struct time clk_time = { 0,  0,  0 };   		//存储时钟的时间值
struct time start_time = {  6, 30,  0 };   		//开始时间
struct time end_time   = { 20, 30,  0 };   	//结束时间

struct time ztime;                    		//输入时间暂存

bit   escape;                              //ESC 键输入标志
bit display_time = 0;                //标志:信号命令状态显示时间 

sbit  green  = P2^0;                  		//绿灯
sbit  yellow = P2^1;                  		//黄灯
sbit  red    = P2^2;                  		//红灯
sbit  stop   = P2^3;                  		//行人停止灯
sbit  walk   = P2^4;                  		//行人通过灯
sbit  button    = P2^5;                  	//行人按钮



init () _task_ INIT  						//任务0,程序起始处
{
  init_serial ();                     		//初始化单片机串行口
  os_create_task (CLK);             		//启动任务2
  os_create_task (COMMAND);           	//启动任务1
  os_create_task (LIGHTS);            		//启动任务4
  os_create_task (buttonREAD);           	//启动任务5
  os_delete_task (INIT);              		//停止任务0
}




void clock ()  _task_ CLK  					//任务2
{
  while (1)  
{ 
if (++clk_time.sec == 60)  				//计算秒值
{         
      clk_time.sec = 0;
      if (++clk_time.min == 60)  			//计算分钟值
{       
        clk_time.min = 0;
        if (++clk_time.hour == 24)  		//计算小时值
{    
          clk_time.hour = 0;
        }
      }
    }
if (display_time) 					//显示时间
{              
      os_send_signal (COMMAND);       	//向任务1发送信号
    }
    os_wait (K_IVL, 100, 0);          		//等待1秒
  }
}



bit readtime (char idata *buffer)  			//读取时间函数
{
  uchar args;                         

  ztime.sec = 0;                           //初始化
  args = sscanf (buffer, "%bd:%bd:%bd",     //扫描输入,并保存至变量
                 &ztime.hour,
                 &ztime.min,
                 &ztime.sec);
  
  if (ztime.hour > 23  ||  ztime.min > 59  ||  //检查输入时间值是否有效
      ztime.sec > 59   ||  args < 2        ||  args == EOF)  
{
    printf ("\nINVALID TIME FORMAT!\n");	//输出错误信息
    return (0);
  }
  return (1);
}

command () _task_ COMMAND  			//任务1
{
  uchar i;

  printf (sysmenu);                         	//系统命令菜单
  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_time.hour, start_time.min, start_time.sec,
                 end_time.hour,   end_time.min,   end_time.sec);
        printf ("Input ESC to abort\r");

        os_create_task (GET_ESC);         //在显示任务中检查ESC 键
        display_time = 1;                   //显示时间标志置1
        escape = 0;                       	//清除 ESC 标志
        os_clear_signal (COMMAND); 

        while (!escape)  				//如果没有输入ESC
{ 
          printf ("Time: %02bd:%02bd:%02bd\r", 
                   clk_time.hour, clk_time.min, clk_time.sec);
          os_wait (K_SIG, 0, 0);            	//等待
        }

        os_delete_task (GET_ESC);         //删除任务
        display_time = 0;                   //显示时间标志置0
        printf ("\n\n");					//输出换行符
        break;

      case 'T':                             //设置时间命令
        if (readtime (&inline[i+1]))  			//获取输入时间
{
          clk_time.hour = ztime.hour;
          clk_time.min  = ztime.min;
          clk_time.sec  = ztime.sec;
        }
        break;

      case 'S':                             //设置开始时间命令
        if (readtime (&inline[i+1]))  			//获取输入时间
{        	
          start_time.hour = ztime.hour; 
          start_time.min  = ztime.min;
          start_time.sec  = ztime.sec;
        }
        break;

      case 'E':                             //设置结束时间命令
        if (readtime (&inline[i+1]))  			//获取输入时间
{        	
          end_time.hour = ztime.hour; 
          end_time.min  = ztime.min;
          end_time.sec  = ztime.sec;
        }
        break;

      default:                            	//无效指令
        printf("Error!");
        printf (sysmenu);                   //显示系统命令菜单
        break;
    }   
  }
}


bit signalon ()   						//检查系统时钟是否处在开始时间和结束时间之间
{
  if (memcmp (&start_time, &end_time, sizeof (struct time)) < 0)  
{
    if (memcmp (&start_time, &clk_time, sizeof (struct time)) < 0  &&
        memcmp (&clk_time, &end_time,   sizeof (struct time)) < 0)  
return (1);						//红绿灯处于活跃状态
  }
  else  
{ 
    if (memcmp (&end_time,   &clk_time, sizeof (start_time)) > 0  &&
        memcmp (&clk_time, &start_time, sizeof (start_time)) > 0)  
return (1);
  }
  return (0);                            	//信号结束,开始闪烁黄灯
}


void blinking () _task_ BLINKING  				//任务3
{ 
  red    = 0;                              //熄灭红灯
  yellow = 0;							//熄灭黄灯
  green  = 0;							//熄灭绿灯
  stop   = 0;							//熄灭行人红灯
  walk   = 0;							//熄灭行人绿灯

  while (1)  							//闪烁循环
{                                
    yellow = 1;                            //点亮黄灯
    os_wait (K_TMO, 30, 0);                //等待超时
    yellow = 0;                            //熄灭黄灯
    os_wait (K_TMO, 30, 0);                //等待超时
if (signalon ())  						//如果闪烁时间段结束
{                        
      os_create_task (LIGHTS);             //启动任务4
      os_delete_task (BLINKING);           //停止任务3
    }
  }
}


void lights () _task_ LIGHTS  					//任务4
{                     
  red    = 1;                              //点亮红灯
  yellow = 0;							//熄灭黄灯
  green  = 0;							//熄灭绿灯
  stop   = 1;							//点亮行人红灯
  walk   = 0;							//熄灭行人绿灯

  while (1)  							//主循环
{                              
    os_wait (K_TMO, 30, 0);                	//等待超时
if (!signalon ())  					//如果系统时间处在活跃时间之外
{                       
      os_create_task (BLINKING);           //启动任务3
      os_delete_task (LIGHTS);             //停止任务4
    }
    yellow = 1;
os_wait (K_TMO, 30, 0);                	//等待超时

    red    = 0;                            
    yellow = 0; 						//为主干道点亮绿灯
green  = 1;

    os_clear_signal (LIGHTS);
    os_wait (K_TMO, 30, 0);                //等待超时
os_wait (K_TMO + K_SIG, 300, 0);       //等待超时和信号

    yellow = 1;
    green  = 0;
    os_wait (K_TMO, 30, 0);                //等待超时
    red    = 1;                           //为主干道点亮红灯
yellow = 0;

    os_wait (K_TMO, 30, 0);                //等待超时
    stop   = 0;                           //为行人点亮绿灯,放行
walk   = 1;

    os_wait (K_TMO, 100, 0);               //等待超时
    stop   = 1;                           //为行人点亮红灯
    walk   = 0;
  }
}


void buttonread () _task_ buttonREAD  		//任务5
{
  while (1)  
{                                 
if (button)  							//若行人按钮按下
{                                
      os_send_signal (LIGHTS);                 //向任务4发送信号
    }
    os_wait (K_TMO, 3, 0);                      //等待超时
  }
}

void get_escape () _task_ GET_ESC  			//任务6
{
  while (1)  
{
if (_getkey () == ESC)  					//如果ESC 键输入,置escape标志
escape = 1;        	
if (escape)  							//如果有escape标志,向任务1发送信号
{                             
      os_send_signal (COMMAND);
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -