|
首先说一下背景吧 :
最近在帮别人做一些小东西,是用51做的,主要给他们提供单片机课设的思路。 且由于时间问题,我也没有将程序进行优化,只是拿来分享一下,大家可以参考。 有思路之后可以稍微花点时间去优化一下代码,是代码更简洁。
马丁·福勒 的一句名言与君共勉:
任何一个傻瓜都会写能够让机器理解的代码,只有好的程序员才能写出人类可以理解的代码。—Martin Fowler
ok, 废话不多说,下面是设计要求及制作过程,proteus仿真以及代码流程的介绍
1) 题目及设计要求
题目:交通灯控制器
要求:
1、红灯和绿灯相互转换时经过黄灯,黄灯闪烁三次(6秒);
2、主干道方向通行30秒,辅干道方向通行20秒,单独左转信号15秒;先直行信号,后左转信号。
3、设手动、自动、特殊情况三种方式。
4、特殊情况时所有路口红灯都亮,给120、110等通行。
5、自动时显示各种状态倒计时。
2) C51编程以及电路仿真软件
编程
51单片机的C语言编程一般都是keil3或者keil4,我一直以来用的keil3,这次使用的keil4,其实都一样的。
(注:关于keil3/4/5的资料和安装教程,在我的另一篇博客讲过了,可以参考一下 点击蓝字-->>
keil4打开的界面如下:
( PS:: 不过这次做这些东西的过程中,keil4经常自己卡死,害得我只能任务管理器关闭它,超级烦,不知道什么原因,有了解的可以评论一下告诉我,感激不尽 .............但是老版本的keil3却很稳定)
仿真:
proteus仿真软件
我用的7版本的
proteus打开界面如下:
这个界面里面的电路图与这个交通灯无关,是我以前做的一个,只是给大家演示
3)解决思路
硬件部分:
交通灯显示部分分为6个部分
- [ 1] 首先:主干道通行30秒 其中单独左转15秒 黄灯6秒
1)主干道--------绿灯 辅干道--------红灯 0-15s // 单独直行
2)主干道--------蓝灯 辅干道--------红灯 15-24s // 单独左转
3)主干道--------黄灯 辅干道--------红灯 24-30s // 黄灯减速
---------------------------------------------------------------------------------------------------------------------------------------
- [ 2] 辅干道通行20秒 单独左转15秒 黄灯6秒
4)主干道--------红灯 辅干道--------绿灯 0-5s
5)主干道--------红灯 辅干道--------蓝灯 5-14s
6)主干道--------红灯 辅干道--------黄灯 14-20s
模拟交通的灯的几个led灯的显示在程序中就是按照上面的流程显示的,由 1)--->2)--->.....--->6)--->1)->..... 一直循环
仿真电路图各个部分展示:
(1)单片机 & 复位电路 & 晶振
(2)交通灯部分
上图标注了每个灯对应的引脚 以及每个灯的颜色
分别在上面和右面放置了一排 用来表示道路的方向
D1-D4指示的是主干道 D5-D8指示的是辅干道
(3)数码管显示部分
这部分是和交通灯部分一起的 为了方便看到我写的标注,我把交通灯抹去了,抹去的部分就是上面交通灯的部分
(该芯片使用方法这里不多说,网上很多资料。。。本质就是一个锁存器)
软件部分
首先代码流程图如下,对这个画图软件不是很熟,画的很垃圾,不过大致能体现出来
4)部分代码展示及解释
# include <reg52.h>
# define uchar unsigned char
# define uint unsigned int
sbit wela = P2^7; // 数码管位选
sbit dula = P2^6; // 数码管段选
- // 按键位定义
- sbit key_auto = P3^0; // 自动
- sbit key_step = P3^1; // 手动
- sbit key_emerg = P3^2; // 紧急情况 110/120通过
复制代码- // 四位八段共阴极数码管数字显示编码
- uchar code table[]={
- //"0" "1" "2" "3"
- 0x3f,0x06,0x5b,0x4f,
- //"4" "5" "6" "7"
- 0x66,0x6d,0x7d,0x07,
- //"8" "9" "A" "B"
- 0x7f,0x6f,0x77,0x7c,
- //"C" "D" "E" "F"
- 0x39,0x5e,0x79,0x71
- };
复制代码- // 交通灯编码 自动模式时,交通灯亮灯顺序 我编成了一个数组,方便使用
- uchar code light[]={
- // 主G辅R 主G辅R 主Y辅R
- 0xdb, 0xde, 0xd7,
- // 主R辅G 主R辅B 主R辅R
- 0xbd, 0xed, 0x7d,
- };
复制代码- // 定时器0中断服务函数 用于计算时间过了几秒
- void timer0() interrupt 1
- {
- TH0=0x4c; // 定时器装初值 50ms(11.05926MHz TH0=0x4c TL0=0x00)
- TL0=0x00; // (12MHz 的初值是 TH0=0x3c TL0=0xb0)
- cnt++;
- if(cnt == 20)
- {
- cnt = 0;
- sec++; // 记录1秒
- }
- }
复制代码- // 按键扫描函数
- void key_scan()
- {
- //判断那个按键盘下
-
- /********************** 自动模式 *********************/
- ///如果是自动模式,就让交通灯正常运行 并显示倒计时
- // Display_C_time(15-sec); // 主干道倒计时显示
- // Display_R_time(30-sec); // 辅干道倒计时显示
- // P1 = light[0]; // 交通灯编码显示
- // 具体代码省略、、、、、、、、、、
-
- /********************** 手动模式 *********************/
- //手动模式就让交通等步进变换
- if(key_step == 0)
- {
- delay_ms(5);
- if(key_step == 0)
- {
- if(light_num == 6)
- {
- light_num = 0;
- }
- P1 = light[light_num];
- light_num++;
- while(!key_step); // 松手检测
- }
- }
-
- /********************** 紧急模式 *********************/
- // 紧急模式 用于120/110紧急通行
- // 让主干道和辅干道都是红灯即可
- // 具体代码省略、、、、、、、、、、、
-
- }
复制代码 // 最后在主函数里面初始化,然后循环扫描按键
- void main()
- {
- system_Init(); // 系统初始化 里面是对定时器中断以及数码管进行初始化
- while(1)
- {
- key_scan();
- }
- }
复制代码
5)整体效果演示
因为这个是帮别人设计的,所以完整源码和仿真工程文件不贴出。 如果需要完整的仿真以及源码,请私聊我或者评论留下联系方式
今天所有的懒惰都会换来明天的卑微 加油吧!!!
|
评分
-
查看全部评分
|