剧透创新大赛准备(五)之程序源代码

/

  1. #include <REGX52.H>
  2. #include <stdlib.h>
  3. typedef enum{false,true}bool; //自定义布尔类型
  4. //下列八行是车道号
  5. #define eastStraight 0x00 //东直行
  6. #define eastLeft 0x01 //东左拐
  7. #define southStraight 0x02 //南直行
  8. #define southLeft 0x03 //南左拐
  9. #define westStraight 0x04 //西直行
  10. #define westLeft 0x05 //西左拐
  11. #define northStraight 0x06 //北直行
  12. #define northLeft 0x07 //北左拐
  13. sbit bes = P1^0;
  14. sbit bel = P1^1;
  15. sbit bss = P1^2;
  16. sbit bsl = P1^3;
  17. sbit bws = P1^4;
  18. sbit bwl = P1^5;
  19. sbit bns = P1^6;
  20. sbit bnl = P1^7;
  21. #define on 1
  22. #define off 0 //位开关
  23. //
  24. #define straightRed 0x08 //直行红灯
  25. #define straightYellow 0x10 //直行黄灯
  26. #define straightGreen 0x20 //直行绿灯
  27. #define leftRed 0x01 //左拐红灯
  28. #define leftYellow 0x02 //左拐黄灯
  29. #define leftGreen 0x04 //左拐绿灯
  30. #define RGBLIGHT P0 //P0口用于输出驱动红黄绿灯信号
  31. #define BLUELIGHT P1 //P1口用于输出蓝色LED,表示该车道有来车
  32. #define DIRECT P2 //P2口用于输出东南西北四个分方向的片选信号,和读入138编码器的三位编码信号
  33. //下列五行是片选信号
  34. #define EAST 0x00 //东
  35. #define SOUTH 0x10 //南
  36. #define WEST 0x20 //西
  37. #define NORTH 0x30 //北
  38. #define NoSelect 0x40 //不选择任何方向
  39. //#define StraightLight 0x38 //直行三灯
  40. //#define LeftLight 0x07 //左向三灯
  41. #define reedShield 0x07 //干簧管屏蔽码
  42. #define OFFALL 0x00 //灯全关
  43. #define ONALL 0xFF //灯全开
  44. #define RedOn 0x09 //红灯全开
  45. #define iniReed 0xFF //干簧管初值
  46. unsigned int count; //定时器计数,全局变量
  47. //定义了一个车道的数据结构,对应8条车道和传感器
  48. struct Lanes{
  49. unsigned char LaneNum; //车道号
  50. bool normal; //节点为临时插队为false,节点是正式永久节点为true;
  51. struct Lanes* next;
  52. };
  53. struct Lanes mr[40]; //预留申请动态内存所需的地址空间
  54. struct Lanes *header, *current, *temp;
  55. //下列四行是4个方向的信号灯的状态
  56. unsigned char eastStatus;
  57. unsigned char southStatus;
  58. unsigned char westStatus;
  59. unsigned char northStatus;
  60. bool forever = true;
  61. void timer0(); //定时器0的中断处理程序
  62. void timer0_init(); //定时器0的初始化
  63. void openTimer0(); //打开定时器0
  64. void closeTimer0(); //关闭定时器0
  65. void getReed(); //干簧管检测车道有来车,中断处理程序
  66. void T0_init(); //初始化中断T0
  67. void closeT0(); //关中断T0
  68. void openT0(); //开中断T0
  69. void openEA(); //打开中断总开关
  70. void initial(); //开机初始化
  71. void tuneoffAll(); //关闭所有的灯
  72. void tuneonAll(); //打开所有的灯
  73. void redAllOn(); //红灯全亮
  74. void Delay(unsigned int count); //延时时间是count×100ms
  75. unsigned char switchLight(unsigned char status , unsigned char chip , unsigned char light); //切换一个周期的信号灯(红-绿-黄-红)
  76. unsigned char changeLight(unsigned char status , unsigned char chip , unsigned char light, unsigned char rgb); //某二个颜色间的信号灯切换
  77. //第一个参数:status 代表信号灯的状态
  78. //第二个参数:chip 代表信号灯的片选信号
  79. //第三个参数:light 代表具体的信号灯
  80. //第四个参数:目前亮着的一个灯
  81. void LaneCycle_init(); //初始化0-7号车道构成一个环形链表
  82. void main()
  83. {
  84. initial();
  85. // reedSingal = current->LaneNum; //临时代替干簧管的值;
  86. while (forever)
  87. {
  88. switch (current->LaneNum)
  89. {
  90. case eastStraight: // 0x00 东直行
  91. bes = on;
  92. eastStatus = switchLight(eastStatus , EAST | reedShield, straightRed);
  93. bes = off;
  94. bws = off;
  95. break;
  96. case westStraight: // 0x04 西直行
  97. bws = on;
  98. westStatus = switchLight(eastStatus , EAST | reedShield , straightRed);
  99. bws = off;
  100. bes = off;
  101. break;
  102. case eastLeft: // 0x01 东左拐
  103. bel = on;
  104. eastStatus = switchLight(eastStatus , EAST | reedShield , leftRed);
  105. bel = off;
  106. bwl = off;
  107. break;
  108. case westLeft: // 0x05 西左拐
  109. bwl = on;
  110. westStatus = switchLight(eastStatus , EAST | reedShield, leftRed);
  111. bwl = off;
  112. bel = off;
  113. break;
  114. case southStraight: // 0x02 南直行
  115. bss = on;
  116. southStatus = switchLight(southStatus, SOUTH | reedShield , straightRed);
  117. bss = off;
  118. bns = off;
  119. break;
  120. case northStraight: // 0x06 北直行
  121. bns = on;
  122. northStatus = switchLight(southStatus, SOUTH | reedShield, straightRed);
  123. bns = off;
  124. bss = off;
  125. break;
  126. case southLeft: // 0x03 南左拐
  127. bsl = on;
  128. southStatus = switchLight(southStatus , SOUTH | reedShield, leftRed);
  129. bsl = off;
  130. bnl = off;
  131. break;
  132. case northLeft: // 0x07 北左拐
  133. bnl = on;
  134. northStatus = switchLight(southStatus , SOUTH | reedShield, leftRed);
  135. bnl = off;
  136. bsl = off;
  137. break;
  138. default:
  139. break;
  140. }
  141. if (current->normal == false)
  142. {
  143. header->next = current->next; // 把current后面的节点地址赋给header的next,
  144. free(current); //删除当前节点
  145. current =header->next; //恢复current为header下一个节点的指针
  146. }else
  147. {
  148. header = current; //header向后一步
  149. current = current->next; //current向后一步,为header下一个节点的指针
  150. }
  151. }
  152. }
  153. unsigned char switchLight(unsigned char status, unsigned char chip , unsigned char light)
  154. {
  155. //红灯灭,绿灯亮
  156. status = changeLight(status, chip , light, light);
  157. Delay(50); //延时5秒
  158. //绿灯灭,黄灯亮
  159. status = changeLight(status, chip , light, light<<2);
  160. Delay(10); //延时1秒
  161. //黄灯灭,红灯亮
  162. status = changeLight(status, chip , light, light<<1);
  163. DIRECT = NoSelect | reedShield; //关闭片选信号
  164. return status; //返回灯的状态
  165. }
  166. unsigned char changeLight(unsigned char status , unsigned char chip , unsigned char light, unsigned char rgb)
  167. {
  168. unsigned char red = light; //红灯
  169. unsigned char yellow = light << 1; //黄灯是红灯左移1位
  170. unsigned char green = light << 2; //绿灯是红灯左移2位
  171. unsigned char i;
  172. //红灯灭,绿灯亮,循环第二次是对对面方向做相应的信号改变
  173. for (i = 0 ; i <= 1 ; i++)
  174. {
  175. chip |= reedShield;
  176. DIRECT = chip;
  177. closeT0(); //在切换灯的瞬间关闭中断
  178. switch(rgb)
  179. {
  180. case straightRed: //直行红灯亮
  181. status = (status | green) & ~red; //红灯灭,绿灯亮,
  182. break;
  183. case straightYellow://直行黄灯亮
  184. status = (status | red) & ~yellow; //黄灯灭,红灯亮,
  185. break;
  186. case straightGreen: //直行绿灯亮
  187. status = (status | yellow) & ~green; //绿灯灭,黄灯亮,
  188. break;
  189. case leftRed: //左拐红灯亮
  190. status = (status | green) & ~red; //红灯灭,绿灯亮,
  191. break;
  192. case leftYellow: //左拐黄灯亮
  193. status = (status | red) & ~yellow; //黄灯灭,红灯亮,
  194. break;
  195. case leftGreen: //左拐绿灯亮
  196. status = (status | yellow) & ~green; //绿灯灭,黄灯亮,
  197. break;
  198. default:
  199. break;
  200. }
  201. RGBLIGHT = status;
  202. openT0();
  203. chip += 0x20; //对面方向片选
  204. }
  205. return status;
  206. }
  207. void initial()
  208. {
  209. unsigned char i;
  210. tuneoffAll();
  211. BLUELIGHT = OFFALL; //关闭P1蓝灯
  212. timer0_init(); //定时器0初始化
  213. T0_init(); //T0初始化
  214. openEA(); //打开中断总开关
  215. for (i = 0; i < 3; i++) //所有的红绿灯闪烁三次,用来检验灯是否有故障
  216. {
  217. tuneonAll();
  218. Delay(15);
  219. tuneoffAll();
  220. Delay(15);
  221. }
  222. // tuneoffAll();
  223. // Delay(15);
  224. redAllOn(); //打开四个方向8个红灯,进入预备状态
  225. Delay(25);
  226. LaneCycle_init(); //初始化车道环形链表
  227. openT0();
  228. }
  229. void redAllOn()
  230. {
  231. DIRECT = EAST | reedShield;
  232. eastStatus = RedOn;
  233. RGBLIGHT = eastStatus;
  234. DIRECT = SOUTH | reedShield;
  235. southStatus = RedOn;
  236. RGBLIGHT = southStatus;
  237. DIRECT = WEST | reedShield;
  238. westStatus = RedOn;
  239. RGBLIGHT = westStatus;
  240. DIRECT = NORTH | reedShield;
  241. northStatus = RedOn;
  242. RGBLIGHT = northStatus;
  243. DIRECT = NoSelect | reedShield;
  244. }
  245. void tuneoffAll()
  246. {
  247. //四向信号灯全关
  248. DIRECT = EAST | reedShield;
  249. RGBLIGHT = OFFALL;
  250. DIRECT = SOUTH | reedShield;
  251. RGBLIGHT = OFFALL;
  252. DIRECT = WEST | reedShield;
  253. RGBLIGHT = OFFALL;
  254. DIRECT = NORTH | reedShield;
  255. RGBLIGHT = OFFALL;
  256. DIRECT = NoSelect | reedShield;
  257. }
  258. void tuneonAll()
  259. {
  260. //四向信号灯全开
  261. DIRECT = EAST | reedShield;
  262. RGBLIGHT = ONALL;
  263. DIRECT = SOUTH | reedShield;
  264. RGBLIGHT = ONALL;
  265. DIRECT = WEST | reedShield;
  266. RGBLIGHT = ONALL;
  267. DIRECT = NORTH | reedShield;
  268. RGBLIGHT = ONALL;
  269. DIRECT = NoSelect | reedShield;
  270. }
  271. void LaneCycle_init()
  272. {
  273. unsigned int i;
  274. init_mempool(&mr, sizeof(mr));
  275. header = (struct Lanes*) malloc(sizeof(struct Lanes));
  276. header->LaneNum = eastStraight;
  277. header->normal = true;
  278. header->next = NULL; //创建第一个节点,头节点
  279. current = header;
  280. //创建头节点之后的7个节点,这些节点都是正式节点,不能删除。
  281. for ( i = 1; i < 8; i++)
  282. {
  283. temp = (struct Lanes*) malloc(sizeof(struct Lanes));
  284. temp->LaneNum = eastStraight + i;
  285. temp->normal = true;
  286. current->next = temp;
  287. current = temp;
  288. }
  289. current->next = header; //最后第8个节点指向头结点,完成链表环初始化。
  290. temp = current;
  291. current = header; //current与header交换,current指向第一个,header指向最后一个。
  292. header = temp;
  293. }
  294. void timer0_init()
  295. {
  296. TMOD = 0x01; //定时器T0选择工作方式1
  297. TH0 = 0x3c; //设置初始值
  298. TL0 = 0xb0;
  299. ET0 = 1; //打开定时器T0中断
  300. TR0 = 0; //暂时关闭定时器T0
  301. }
  302. void timer0() interrupt 1
  303. {
  304. TH0 = 0x3c; //设置初始值(50ms)
  305. TL0 = 0xb0;
  306. count--;
  307. }
  308. void openTimer0()
  309. {
  310. TR0 = 1; //启动定时器T0
  311. }
  312. void closeTimer0()
  313. {
  314. TR0 = 0; //关闭定时器T0
  315. }
  316. void Delay(unsigned int c)
  317. {
  318. openTimer0();
  319. count = c; //count赋初值
  320. while(count); //启动定时器T0
  321. closeTimer0(); //关闭定时器T0
  322. }
  323. void T0_init()
  324. {
  325. //中断0初始化
  326. EX0 = 0; //打开中断0
  327. IT0 = 1; //中断设置为下降沿触发
  328. }
  329. void getReed() interrupt 0
  330. {
  331. unsigned char reedSingal;
  332. struct Lanes *node;
  333. closeT0(); //关中断
  334. reedSingal = ~P2 & reedShield; //读入reedShield低三位传感器数值。
  335. //因为74LS138的输入Y0对应111。取反后,对应000,与车道编码设置初衷一致,便于计算。
  336. temp = current;
  337. if(temp->LaneNum % 4 == reedSingal % 4) goto sw; //用模4的方法,可以判断两个车道是不是属于对应的一对
  338. //如果是对应的一对车道,也视同是同一条车道,只是要亮起相应的蓝灯
  339. //比如当前是1号车道,对应的车道5来车,视为是同一个节点,无需插入
  340. //节点,仅需亮起相应的蓝灯。
  341. while(temp->next->LaneNum % 4 != reedSingal % 4)
  342. {
  343. if (temp->next->normal == true)
  344. {
  345. node = (struct Lanes*) malloc(sizeof(struct Lanes)); //创建一个临时节点,
  346. node->LaneNum = reedSingal; //把reed来车信号编码赋值给LaneNum;
  347. node->normal = false; //数据结构设为false,意思为临时节点;
  348. node->next = temp->next; //把current的后一个节点地址赋值给new->next
  349. temp->next = node; //再把new地址本身赋值给current->next,完成插入操作。
  350. }else{
  351. temp = temp->next;
  352. }
  353. }
  354. //那一根车道有车相应蓝灯亮起,表示有车将经过
  355. sw: switch(reedSingal)
  356. {
  357. case eastStraight: //东直行
  358. bes = on;
  359. break;
  360. case eastLeft: //东左拐
  361. bel = on;
  362. break;
  363. case southStraight: //南直行
  364. bss = on;
  365. break;
  366. case southLeft: //南左拐
  367. bsl = on;
  368. break;
  369. case westStraight: //西直行
  370. bws = on;
  371. break;
  372. case westLeft: //西左拐
  373. bwl = on;
  374. break;
  375. case northStraight: //北直行
  376. bns = on;
  377. break;
  378. case northLeft: //北左拐
  379. bnl = on;
  380. break;
  381. default:
  382. break;
  383. }
  384. openT0(); //开中断
  385. return;
  386. }
  387. void closeT0()
  388. {
  389. EX0=0; //关中断
  390. }
  391. void openT0()
  392. {
  393. EX0=1; //开中断
  394. }
  395. void openEA()
  396. {
  397. EA = 1; //打开中断总开关
  398. }

Reproduced please indicate the author and the source, and error a link to this page.
text link: weiyi.sh/post/72

Say something...