剧透创新大赛准备(五)之程序源代码
#include <REGX52.H>
#include <stdlib.h>
typedef enum{false,true}bool; //自定义布尔类型
//下列八行是车道号
#define eastStraight 0x00 //东直行
#define eastLeft 0x01 //东左拐
#define southStraight 0x02 //南直行
#define southLeft 0x03 //南左拐
#define westStraight 0x04 //西直行
#define westLeft 0x05 //西左拐
#define northStraight 0x06 //北直行
#define northLeft 0x07 //北左拐
sbit bes = P1^0;
sbit bel = P1^1;
sbit bss = P1^2;
sbit bsl = P1^3;
sbit bws = P1^4;
sbit bwl = P1^5;
sbit bns = P1^6;
sbit bnl = P1^7;
#define on 1
#define off 0 //位开关
//
#define straightRed 0x08 //直行红灯
#define straightYellow 0x10 //直行黄灯
#define straightGreen 0x20 //直行绿灯
#define leftRed 0x01 //左拐红灯
#define leftYellow 0x02 //左拐黄灯
#define leftGreen 0x04 //左拐绿灯
#define RGBLIGHT P0 //P0口用于输出驱动红黄绿灯信号
#define BLUELIGHT P1 //P1口用于输出蓝色LED,表示该车道有来车
#define DIRECT P2 //P2口用于输出东南西北四个分方向的片选信号,和读入138编码器的三位编码信号
//下列五行是片选信号
#define EAST 0x00 //东
#define SOUTH 0x10 //南
#define WEST 0x20 //西
#define NORTH 0x30 //北
#define NoSelect 0x40 //不选择任何方向
//#define StraightLight 0x38 //直行三灯
//#define LeftLight 0x07 //左向三灯
#define reedShield 0x07 //干簧管屏蔽码
#define OFFALL 0x00 //灯全关
#define ONALL 0xFF //灯全开
#define RedOn 0x09 //红灯全开
#define iniReed 0xFF //干簧管初值
unsigned int count; //定时器计数,全局变量
//定义了一个车道的数据结构,对应8条车道和传感器
struct Lanes{
unsigned char LaneNum; //车道号
bool normal; //节点为临时插队为false,节点是正式永久节点为true;
struct Lanes* next;
};
struct Lanes mr[40]; //预留申请动态内存所需的地址空间
struct Lanes *header, *current, *temp;
//下列四行是4个方向的信号灯的状态
unsigned char eastStatus;
unsigned char southStatus;
unsigned char westStatus;
unsigned char northStatus;
bool forever = true;
void timer0(); //定时器0的中断处理程序
void timer0_init(); //定时器0的初始化
void openTimer0(); //打开定时器0
void closeTimer0(); //关闭定时器0
void getReed(); //干簧管检测车道有来车,中断处理程序
void T0_init(); //初始化中断T0
void closeT0(); //关中断T0
void openT0(); //开中断T0
void openEA(); //打开中断总开关
void initial(); //开机初始化
void tuneoffAll(); //关闭所有的灯
void tuneonAll(); //打开所有的灯
void redAllOn(); //红灯全亮
void Delay(unsigned int count); //延时时间是count×100ms
unsigned char switchLight(unsigned char status , unsigned char chip , unsigned char light); //切换一个周期的信号灯(红-绿-黄-红)
unsigned char changeLight(unsigned char status , unsigned char chip , unsigned char light, unsigned char rgb); //某二个颜色间的信号灯切换
//第一个参数:status 代表信号灯的状态
//第二个参数:chip 代表信号灯的片选信号
//第三个参数:light 代表具体的信号灯
//第四个参数:目前亮着的一个灯
void LaneCycle_init(); //初始化0-7号车道构成一个环形链表
void main()
{
initial();
// reedSingal = current->LaneNum; //临时代替干簧管的值;
while (forever)
{
switch (current->LaneNum)
{
case eastStraight: // 0x00 东直行
bes = on;
eastStatus = switchLight(eastStatus , EAST | reedShield, straightRed);
bes = off;
bws = off;
break;
case westStraight: // 0x04 西直行
bws = on;
westStatus = switchLight(eastStatus , EAST | reedShield , straightRed);
bws = off;
bes = off;
break;
case eastLeft: // 0x01 东左拐
bel = on;
eastStatus = switchLight(eastStatus , EAST | reedShield , leftRed);
bel = off;
bwl = off;
break;
case westLeft: // 0x05 西左拐
bwl = on;
westStatus = switchLight(eastStatus , EAST | reedShield, leftRed);
bwl = off;
bel = off;
break;
case southStraight: // 0x02 南直行
bss = on;
southStatus = switchLight(southStatus, SOUTH | reedShield , straightRed);
bss = off;
bns = off;
break;
case northStraight: // 0x06 北直行
bns = on;
northStatus = switchLight(southStatus, SOUTH | reedShield, straightRed);
bns = off;
bss = off;
break;
case southLeft: // 0x03 南左拐
bsl = on;
southStatus = switchLight(southStatus , SOUTH | reedShield, leftRed);
bsl = off;
bnl = off;
break;
case northLeft: // 0x07 北左拐
bnl = on;
northStatus = switchLight(southStatus , SOUTH | reedShield, leftRed);
bnl = off;
bsl = off;
break;
default:
break;
}
if (current->normal == false)
{
header->next = current->next; // 把current后面的节点地址赋给header的next,
free(current); //删除当前节点
current =header->next; //恢复current为header下一个节点的指针
}else
{
header = current; //header向后一步
current = current->next; //current向后一步,为header下一个节点的指针
}
}
}
unsigned char switchLight(unsigned char status, unsigned char chip , unsigned char light)
{
//红灯灭,绿灯亮
status = changeLight(status, chip , light, light);
Delay(50); //延时5秒
//绿灯灭,黄灯亮
status = changeLight(status, chip , light, light<<2);
Delay(10); //延时1秒
//黄灯灭,红灯亮
status = changeLight(status, chip , light, light<<1);
DIRECT = NoSelect | reedShield; //关闭片选信号
return status; //返回灯的状态
}
unsigned char changeLight(unsigned char status , unsigned char chip , unsigned char light, unsigned char rgb)
{
unsigned char red = light; //红灯
unsigned char yellow = light << 1; //黄灯是红灯左移1位
unsigned char green = light << 2; //绿灯是红灯左移2位
unsigned char i;
//红灯灭,绿灯亮,循环第二次是对对面方向做相应的信号改变
for (i = 0 ; i <= 1 ; i++)
{
chip |= reedShield;
DIRECT = chip;
closeT0(); //在切换灯的瞬间关闭中断
switch(rgb)
{
case straightRed: //直行红灯亮
status = (status | green) & ~red; //红灯灭,绿灯亮,
break;
case straightYellow://直行黄灯亮
status = (status | red) & ~yellow; //黄灯灭,红灯亮,
break;
case straightGreen: //直行绿灯亮
status = (status | yellow) & ~green; //绿灯灭,黄灯亮,
break;
case leftRed: //左拐红灯亮
status = (status | green) & ~red; //红灯灭,绿灯亮,
break;
case leftYellow: //左拐黄灯亮
status = (status | red) & ~yellow; //黄灯灭,红灯亮,
break;
case leftGreen: //左拐绿灯亮
status = (status | yellow) & ~green; //绿灯灭,黄灯亮,
break;
default:
break;
}
RGBLIGHT = status;
openT0();
chip += 0x20; //对面方向片选
}
return status;
}
void initial()
{
unsigned char i;
tuneoffAll();
BLUELIGHT = OFFALL; //关闭P1蓝灯
timer0_init(); //定时器0初始化
T0_init(); //T0初始化
openEA(); //打开中断总开关
for (i = 0; i < 3; i++) //所有的红绿灯闪烁三次,用来检验灯是否有故障
{
tuneonAll();
Delay(15);
tuneoffAll();
Delay(15);
}
// tuneoffAll();
// Delay(15);
redAllOn(); //打开四个方向8个红灯,进入预备状态
Delay(25);
LaneCycle_init(); //初始化车道环形链表
openT0();
}
void redAllOn()
{
DIRECT = EAST | reedShield;
eastStatus = RedOn;
RGBLIGHT = eastStatus;
DIRECT = SOUTH | reedShield;
southStatus = RedOn;
RGBLIGHT = southStatus;
DIRECT = WEST | reedShield;
westStatus = RedOn;
RGBLIGHT = westStatus;
DIRECT = NORTH | reedShield;
northStatus = RedOn;
RGBLIGHT = northStatus;
DIRECT = NoSelect | reedShield;
}
void tuneoffAll()
{
//四向信号灯全关
DIRECT = EAST | reedShield;
RGBLIGHT = OFFALL;
DIRECT = SOUTH | reedShield;
RGBLIGHT = OFFALL;
DIRECT = WEST | reedShield;
RGBLIGHT = OFFALL;
DIRECT = NORTH | reedShield;
RGBLIGHT = OFFALL;
DIRECT = NoSelect | reedShield;
}
void tuneonAll()
{
//四向信号灯全开
DIRECT = EAST | reedShield;
RGBLIGHT = ONALL;
DIRECT = SOUTH | reedShield;
RGBLIGHT = ONALL;
DIRECT = WEST | reedShield;
RGBLIGHT = ONALL;
DIRECT = NORTH | reedShield;
RGBLIGHT = ONALL;
DIRECT = NoSelect | reedShield;
}
void LaneCycle_init()
{
unsigned int i;
init_mempool(&mr, sizeof(mr));
header = (struct Lanes*) malloc(sizeof(struct Lanes));
header->LaneNum = eastStraight;
header->normal = true;
header->next = NULL; //创建第一个节点,头节点
current = header;
//创建头节点之后的7个节点,这些节点都是正式节点,不能删除。
for ( i = 1; i < 8; i++)
{
temp = (struct Lanes*) malloc(sizeof(struct Lanes));
temp->LaneNum = eastStraight + i;
temp->normal = true;
current->next = temp;
current = temp;
}
current->next = header; //最后第8个节点指向头结点,完成链表环初始化。
temp = current;
current = header; //current与header交换,current指向第一个,header指向最后一个。
header = temp;
}
void timer0_init()
{
TMOD = 0x01; //定时器T0选择工作方式1
TH0 = 0x3c; //设置初始值
TL0 = 0xb0;
ET0 = 1; //打开定时器T0中断
TR0 = 0; //暂时关闭定时器T0
}
void timer0() interrupt 1
{
TH0 = 0x3c; //设置初始值(50ms)
TL0 = 0xb0;
count--;
}
void openTimer0()
{
TR0 = 1; //启动定时器T0
}
void closeTimer0()
{
TR0 = 0; //关闭定时器T0
}
void Delay(unsigned int c)
{
openTimer0();
count = c; //count赋初值
while(count); //启动定时器T0
closeTimer0(); //关闭定时器T0
}
void T0_init()
{
//中断0初始化
EX0 = 0; //打开中断0
IT0 = 1; //中断设置为下降沿触发
}
void getReed() interrupt 0
{
unsigned char reedSingal;
struct Lanes *node;
closeT0(); //关中断
reedSingal = ~P2 & reedShield; //读入reedShield低三位传感器数值。
//因为74LS138的输入Y0对应111。取反后,对应000,与车道编码设置初衷一致,便于计算。
temp = current;
if(temp->LaneNum % 4 == reedSingal % 4) goto sw; //用模4的方法,可以判断两个车道是不是属于对应的一对
//如果是对应的一对车道,也视同是同一条车道,只是要亮起相应的蓝灯
//比如当前是1号车道,对应的车道5来车,视为是同一个节点,无需插入
//节点,仅需亮起相应的蓝灯。
while(temp->next->LaneNum % 4 != reedSingal % 4)
{
if (temp->next->normal == true)
{
node = (struct Lanes*) malloc(sizeof(struct Lanes)); //创建一个临时节点,
node->LaneNum = reedSingal; //把reed来车信号编码赋值给LaneNum;
node->normal = false; //数据结构设为false,意思为临时节点;
node->next = temp->next; //把current的后一个节点地址赋值给new->next
temp->next = node; //再把new地址本身赋值给current->next,完成插入操作。
}else{
temp = temp->next;
}
}
//那一根车道有车相应蓝灯亮起,表示有车将经过
sw: switch(reedSingal)
{
case eastStraight: //东直行
bes = on;
break;
case eastLeft: //东左拐
bel = on;
break;
case southStraight: //南直行
bss = on;
break;
case southLeft: //南左拐
bsl = on;
break;
case westStraight: //西直行
bws = on;
break;
case westLeft: //西左拐
bwl = on;
break;
case northStraight: //北直行
bns = on;
break;
case northLeft: //北左拐
bnl = on;
break;
default:
break;
}
openT0(); //开中断
return;
}
void closeT0()
{
EX0=0; //关中断
}
void openT0()
{
EX0=1; //开中断
}
void openEA()
{
EA = 1; //打开中断总开关
}
转载请注明作者和出处,并添加本页链接。
原文链接: 139.196.92.124/post/72
评论列表
http://imrdsoacha.gov.co/silvitra-120mg-qrms
johnanz 在 2022-04-19 10:06:07.0
http://imrdsoacha.gov.co/silvitra-120mg-qrms
johnansaz 在 2022-04-19 11:45:02.0