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

📄 traffic.c

📁 零基础单片机C语言设计全套教程
💻 C
字号:
#include <reg52.h>                    		//头文件
#include <stdio.h> 
#include <ctype.h> 
#include <math.h>
#include <string.h> 
#include <rtx51tny.h> 

code char MenuOption[] = 					//系统命令菜单
   "\n"
   "+*** C51 道路交通灯多任务控制系统 ***+\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 ();                		//外部函数:声明,用于初始化串行口
bit readtime (char idata *buffer)  ;			//读取时间函数
bit timeon ();   							//检查系统时钟是否处在开始时间和结束时间之间

#define INIT_TASK      		0            	//任务0:  初始化系统
#define COMMAND_TASK   	1             //任务1:  命令处理
#define CLK_TASK     		2             //任务2:  时钟控制
#define BLINKING_TASK  	3             //任务3:  黄色灯闪烁
#define LIGHTS_TASK    	4             //任务4:  交通灯工作
#define buttonREAD_Task   	5             //任务5:  读取行人按钮
#define ESCEXIT_TASK   	6             //任务6:  退出

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

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

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

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

bit   ESCExit;                              //ESC 键输入标志
bit   rt;								//读取时间标志
bit display_time = 0;                		//信号命令状态显示时间标志

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


init () _task_ INIT_TASK  				//任务0,程序起始处
{
  init_serial ();                     		//初始化单片机串行口
  os_create_task (CLK_TASK);             	//启动任务2
  os_create_task (COMMAND_TASK);       //启动任务1
  os_create_task (LIGHTS_TASK);          //启动任务4
  os_create_task (buttonREAD_Task);       //启动任务5
  os_delete_task (INIT_TASK);              //停止任务0
}

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

  printf (MenuOption);                       //系统命令菜单
  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 ("输入ESC键退出!\r");

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

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

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

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

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

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

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

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

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



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

void blinking () _task_ BLINKING_TASK  	//任务3
{ 
  bit sl;
  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);                //等待超时
sl= timeon ();
if (sl)  							//如果闪烁时间段结束
{                        
      os_create_task (LIGHTS_TASK);      //启动任务4
      os_delete_task (BLINKING_TASK);    //停止任务3
    }
  }
}


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

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

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

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

    os_clear_signal (LIGHTS_TASK);
    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_Task  	//任务5
{
  while (1)  
{                                 
if (button)  						//若行人按钮按下
{                                
      os_send_signal (LIGHTS_TASK);      //向任务4发送信号
    }
    os_wait (K_TMO, 3, 0);                 //等待超时
  }
}

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


⌨️ 快捷键说明

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