交通信号灯自动控制模拟指示系统
设计方案
软件环境:win10(暂),visualc++6.0
1. 硬件环境:微机实验箱,各种电线,转接线。
2. 软件功能流程图(markdown 格式画的流程图,画的不是很好) 额外实现功能只
有夜间模式,设计的不太好,8255 不够用了
总共需要控制四个数码管(南北两个,东西两个)。
综上,我们可以知道硬件连接方式如下:
写,二进制计数。不过问题是 LED 灯是低电平才亮,8253 是计时结束输出
低频脉冲,我们只能把他送给 8255,来进行判断在输出给 LED6 个交通灯
大概就是让LED 灯循环:红灯→黄灯闪烁→绿灯→红灯 的过程。 总共需要控制6
个LED 小灯(红黄绿各两个)
同时:数码管显示倒计时,红灯时倒计时35s,黄灯倒计时5s,绿灯倒计时30s。
8253(8254)刚好三个输出,都接入1HZ 脉冲(系统提供),分别设置计数
1.
器0,1,2 计数值为35,5,30,且都工作在方式二,选择计数器低8 位读
2.
8255 设定 A,B 口都工作在方式0,A 口用来控制交通灯(高6 位,后两位全
部写1 就行),B 口用来向数码管写数据,显示时间,同时配合 C 口高 4 位
先暂定一个开关用来表示天黑天亮的状态。哦哦,剩下3 个刚好读取8253 的
3 个计时器的输出。
3. 我们设置一个全局变量,red,yellow,green,通过键盘输入,设置0~99s 的时
4. 我们设置一个判断,来自行设定路口的起始状态,即:要不南北红,东西绿;
5. 现在暂且还需要解决的时数码管显示的时间如何同步计时器减一。
输出进行片选数码管(刚刚好),再用 C 口低 4 位作输入,读取开关信息,
间,再写给计数器。
要不南北绿,东西红。
直接颜色参数递减就行。
硬件连接图:
老师要是觉得图画的不够体现具体思路请看看下面代码。
目前,大概根据以上,设计程序的思路就是:
。。。好像不能用汇编
// KaiguanDlg.cpp : implementation file
Emmmm,那就按例子大概写吧
#include "stdafx.h"
#include "Kaiguan.h"
#include "KaiguanDlg.h"
#include "qth9054fun.h"
......
…..
#define P8255A
地址
#define P8255B
#define P8255C
#define P8255MODE
0x20
0x21
0x22
0x23
//必须添加的头文件
//定义8255 各端口
#define P8253A
0x00
//定义8253 各端口
地址
#define P8253B
#define P8253C
#define P8253MODE
0x01
0x02
0x03
//红绿黄三个
extern int red;
小灯亮的时间
extern int yellow;
extern int green;
extern int model;
//共阴极数码管编码,虽然我记的是共阴极,但电路图上都接着电源,不好意思老
师这边忘了。
unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
CWinThread
HWND hWnd;
BOOL ISSTART=false;
*Thread_Comd;
UINT Comd(LPVOID pParam)
{
BYTE m_data;
IO8bWrite(P8255MODE,0x81);
输出,A 口输出,CH 输出
//要创建的线程
//判定PCI 卡是否正常
//新线程入口函数
//向8255 控制口发送控制字,B 口
IO8bWrite(P8253MODE,0x14);
IO8bWrite(P8253MODE,0x54);
IO8bWrite(P8253MODE,0x94);
printf("请选择按默认方式还是自行设定方式运行,默认为 0,自行为 1\n");
scanf("%d",&model);
if(model == 1){
//8253,方式2,二进制
IO8bWrite(P8255A,0B01111011); //东西红,南北绿
shumaguanLight(red,green);
}else if(option == 1){
printf("请输入红灯亮的时间:0~99\n");
scanf("%d",&red);
printf("请输入绿灯亮的时间:0~99\n");
scanf("%d",&green);
printf("请输入黄灯亮的时间:0~99\n");
scanf("%d",&yellow);
int option = 0;
printf("请输入哪方先通行,南北 0,东西 1\n");
scanf("%d",&option);
if(option == 0){
IO8bWrite(P8255A,0B1100111); //南北红,东西绿
shumaguanLight(green,red);
}
IO8bWrite(P8253A,red);
//IO8bWrite(P8253B,yellow);
IO8bWrite(P8253C,green);
}
else if(model == 0){
red = 35;
yellow = 5;
green = 30;
IO8bWrite(P8253A,red);
//IO8bWrite(P8253B,yellow);
IO8bWrite(P8253C,green);
shumaguanLight(red,green);
//红灯计时器启动
//黄灯计时器启动
//绿灯计时器启动
//红灯计时器启动
//黄灯计时器启动
//绿灯计时器启动
//应该是低电平吧,希望不要有太大的误差
IO8bWrite(P8255A,0B01111011); //东西红,南北绿
}//这里代码写复杂了好像耦合性也有点高,但为了可读性就这样吧。
//这里就只以默认模式为例了
while(ISSTART) {
int witchisRed = option //用来判断上一个状态那边是红灯
int key = 0;
while(ture){
m_data=IO8bRead(P8255C);
//开关状态
低4 位,从左到右
//从C 口读取8255 数据,C
m_data = mdata && 0B00001111; //依次是开关,红灯计数器,黄,绿
if(m_data == 0B00000110 && model == 0 && witchisRed == 0 ||
(key == 1 && m_data == 0B00000XXXX)){
//南北绿灯计数时间到,开关没打开 || 之前开关打开了,现在开
关关闭了
}
IO8bWrite(P8255A,0B01110111);
IO8bWrite(P8253B,yellow);
shumaguanLight(red,yellow);
//东西红,南北黄
//黄灯计时器启动
if((m_data == 0B00000001 || 0B00000101) && model == 0 &&
witchisRed == 0){
//南北黄计数时间到,开关没打开
IO8bWrite(P8255A,0B11001111);
IO8bWrite(P8253C,green);
IO8bWrite(P8253A,red);
//东西绿,南北红
//绿灯计时器启动
//红灯计时器
启动
shumaguanLight(green,red);
witchisRed = 1;
}
{
if(m_data == 0B00000110 && model == 0 && witchisRed == 1)
//东西绿计数时间到,开关没打开
IO8bWrite(P8255A,0B10101111);
IO8bWrite(P8253B,yellow);
shumaguanLight(yellow,red);
//东西黄,南北红
//绿灯计时器启动
}
if((m_data == 0B00000001 || 0B00000101) && model == 0 &&
witchisRed == 1){
//东西黄计数时间到,开关没打开
IO8bWrite(P8255A,0B01111011);
IO8bWrite(P8253C,green);
IO8bWrite(P8253A,red);
//东西红,南北绿
//绿灯计时器启动
//红灯计时器
启动
}
shumaguanLight(red,green);
witchisRed = 0;
//开关打开时。这里省略移位读取开关位的过程
if(m_data == 0B00001xxx){
IO8bWrite(P8255A,0B10110111);
shumaguanLight(yellow,yellow);
key = 1;
//都为黄灯
}
}
}
//向数码管写时间,即abcdefgh
void shumaguanLight(int color1, int color2){
//color1 是东西, color2 是南北
//取高位和低位
int h1 = color1/10;
int l1 = color1%10;
int h2 = color2/10;
int l2 = color2%10;
int t[] = {l1,h1,l2,h2};
int pianxuan = 1; //用于片选
for(int i=0;i<4;i= (i+1)%4){
IO8bWrite(P8253C,pianxuan<
break;
}
}
return 0;
}
/*
这里想要通过q 退出程序,但不会写。我是想着通过中断服务函数,或是另外创建一
个线程读取到q 就关闭整个程序。
if( is q or Q)
exit(0);
*/
BOOL CKaiguanDlg::OnInitDialog()
{
CDialog::OnInitDialog();
…..
……
……
// TODO: Add extra initialization here
if (!Init9054())
{
return 0;
//PCI9054 初始化
//如果未找到PCI 卡返回0
}
Thread_Comd=AfxBeginThread(Comd,NULL,THREAD_PRIORITY_NORMAL,0,CRE
//创建新线
ATE_SUSPENDED);
程,创建后执行的入口函数为Comd
return TRUE;
}
void CKaiguanDlg::OnOK()
定”后开始运行
{
// TODO: Add extra validation here
if (!ISSTART) {
ad_Comd
// 如果找到PCI 卡 返回 1
//在对话框中点击“确
//如果找到PCI 卡,执行新线程Thre
ISSTART=true;
Thread_Comd->ResumeThread();
CDialog::OnOK();
}
//
}
void CKaiguanDlg::OnCancel()
消”后结束
{
// TODO: Add extra cleanup here
ISSTART=false;
Cleanup();
CDialog::OnCancel();
}
导出后有点丑。。。
//在对话框点击“取
//取消进程,返回Windows