单片机综合控制器实验.docx
《单片机综合控制器实验.docx》由会员分享,可在线阅读,更多相关《单片机综合控制器实验.docx(25页珍藏版)》请在冰豆网上搜索。
单片机综合控制器实验
单片机综合性设计性实验报告
实验项目名称:
单片机综合控制器实验
实验室(中心):
电子实验室
实验完成时间:
09年11月25日
一.实验目的与要求
通过仿真搭建和实物搭建相结合,完成灵活可变的单片机最小系统设计,并掌握地址空
间的分配操作。
通过仿真搭建和实物搭建相结合,万用交叉口交通灯控制器系统设计,并掌握C51编程
操作。
2.实验内容
(1)以6264或6116为扩展的存储芯片,8255或8155芯片为键盘显示控制芯片,建立基本
的串行口,普通的I/O口,A/D转换,D/A转换口功能。
(2)用Proteus仿真软件搭建仿真硬件电路图。
验证编制软件。
(3)用protel99s布原理图、建PCB板图。
(4)实物器件焊接搭建。
模拟控制就是以红、绿、黄色4组12个发光二极管表示交通信号灯。
每组灯有两位数
码倒倒计时显示。
假设一个十字路口为东西南北走向。
初始状态0为东西红灯,南北红灯。
然后转状态1,
东西方向的绿灯亮,东西方向可通车,而南北方向的红灯亮,南北方向的车禁止通行。
过一
段时间转状态2,东西绿灯灭后,黄灯亮,延时几秒,南北仍然红灯。
再转状态3,南北方向
的绿灯亮,南北方向可以通车,而东西方向的红灯亮,东西方向禁止车辆通行。
过一段时间
转状态4,南北绿灯灭后亮黄灯,延时几秒,东西方向仍然红灯亮。
最后循环至状态1。
用Proteus仿真软件搭建仿真硬件电路图。
验证编制软件。
三.实验原理及实验线路
4.实验器材
表2.5.2最小系统的硬件元件清单:
单片机AT89C52瓷片电容CAP30pF晶振CRYSTAL12MHz
电解电容CAP-ELEC电阻RES按钮BUTTON
发光二极管LED-BIRG发光二极管LED-BIBY开关SWITCH
排阻RESPACK-8发光二极管LED-BIGY发光二极管LED-YELLOW
按键16个8255芯片74LS138芯片74LS373DAC0809
5.系统流程图
开始
延时等待系统准备好
系统初始化初始化
N
N
N
P32==0?
P35==0?
P31==0?
P34==0?
Y
Y
Y
Y
启动键盘扫描
启动波形发生器
启动模拟交通灯
启动AD转换
产生锯齿波
N
‘0’键按下
初始化计数变量
采样频率0.5Hz
Y
N
P32==0?
调用彩灯功能
显示当前计数变量初值
将转化的数字量转换成十进制数
N
Y
产生方波
显示按键值
1秒到了?
显示测量的结果
N
Y
P32==0?
计数变量减1
N
Y
满足下一种状态的条件?
Y
6、硬件设计框图
显示
输出
AT89C51
键盘
扫描
8255A
AD
转换
模拟
交通灯
波形
发生器
七、软件设计
#include
#include
#defineDAC0832XBYTE[0XDFFF]
#defineCOM8255XBYTE[0X7FFF]
#definePA8255XBYTE[0X7FCF]
#definePB8255XBYTE[0X7FDF]
#definePC8255XBYTE[0X7FEF]
#defineIN0XBYTE[0XBFF8]//设置AD0809的通道0的地址
#defineucharunsignedchar//宏定义
#defineuintunsignedint//宏定义
uintaa,bai,shi,ge,bb;//定义变量
doublejieguo;
unsignedchara0[4];
uchari,j,m,n;//用于循环
sbitP32=P3^2;
sbitP31=P3^1;
sbitP30=P3^0;//ADC0809转换状态
sbitP33=P3^3;//键盘中断
sbitP34=P3^4;
sbitP35=P3^5;
sbitP17=P1^7;//产生AD转换时钟的引脚
unsignedcharcount=-1;//键盘值计数
unsignedcharsta;//读取键盘状态的变量
unsignedcharkey;//功能选择键
staticunsignedcharidataad[1];//AD转换结果存储
codeunsignedchartable[20]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xff,0x00,0xff,0x00};
codeunsignedchartable0[16]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0E};
unsignedchartablea[6]={0xfe,0xfd,0xfb,0xfF};//用于键盘扫描
unsignedchartableb[4]={0XE0,0XD0,0XB0,0X70};//用于键盘扫描
codeunsignedchartablec[]={0xfe,0xfd,0xfb,0xdf,0xef,0xf7,0xf6,0xf5,
0xf3,0xd7,0xe7,0xe6,0xe5,0xe3,0xc7,0xc6,
0xc5,0xc3,0xc2,0xc1,0xc0,0xc1,0xc2,0xc4,
0xe0,0xd0,0xc8,0xc9,0xca,0xcc,0xe8,0xd8,
0xd9,0xda,0xdc,0xf8,0xf9,0xfa,0xfc,0xfd,
0xfe,0xff,0xfe,0xfd,0xfb,0xdf,0xef,0xf7,
0xf7,0xdf,0xfb,0xfd,0xfe,0xfe,0xfd,0xfb,
0xdf,0xef,0xf7,0xf7,0xef,0xdf,0xfb,0xfd,
0xfe,0xfe,0xfd,0xfb,0xdf,0xef,0xf7,0xfe,
0xfd,0xfb,0xdf,0xef,0xf7,0xfe,0xfd,0xfb,
0xdf,0xef,0xf7,0xfe,0xf7,0xfd,0xef,0xfb,
0xdf,0xde,0xd7,0xdd,0xcf,0xdb,0xda,0xd3,
0xd9,0xcb,0xca,0xc3,0xc9,0xc8,0xc1,0xc0,
0xff,0xf6,0xed,0xdb,0xf6,0xed,0xdb,0xf6,
0xed,0xdb,0xf6,0xed,0xdb,0xf6,0xed,0xdb,
0xf3,0xed,0xde,0xf3,0xed,0xde,0xf3,0xed,
0xde,0xf3,0xed,0xde,0xf3,0xed,0xde,0xfe,
0xfd,0xfa,0xdd,0xea,0xd5,0xea,0xd5,0xea,
0xd5,0xea,0xd5,0xea,0xd5,0xea,0xd5,0xea,
0xd5,0xea,0xd5,0xea,0xd5,0xff,0xc0,0xff,
0xc0,0xff,0xc0,0xff,0xc0,0xff,0xff,0xff};//用于彩灯显示
voiddelay100us(void)//------------------------延时100us
{
unsignedchara,b;
for(b=2;b>0;b--)
for(a=47;a>0;a--);
}
voiddelay6ms(void)//----------------------延时6ms键盘去抖
{
unsignedchara,b,c;
for(c=1;c>0;c--)
for(b=222;b>0;b--)
for(a=12;a>0;a--);
}
voiddelay0(unsignedintz)//----------------------------动态显示LED延时子函数
{
unsignedinti,j;
for(i=0;ifor(j=0;j<110;j++);
}
voidad0809(unsignedcharidata*x)//-------------A/D采样函数
{
unsignedcharxdata*ad_adr;
//unsignedchari;
ad_adr=&IN0;
//for(i=0;i<8;i++)
//{
*ad_adr=0;//启动转换
delay100us();//延时100us等待EOC变低
while(P32==0);//查询等待转换结束
x[0]=*ad_adr;//储存结果
//ad_adr++;//读取下一个通道
//}
}
voidint1(void)//--------------------------------------键值扫描函数
{
for(i=0;i<3;i++)
for(j=0;j<3;j++)
{
P1=tablea[i];
sta=P1&0xf0;
if(sta==tableb[j])
{
delay6ms();
if(sta==tableb[j])
count=i*3+j;
}
}
}
/**************************************************************/
/**/
/*第1个状态:
主干道亮绿灯30S、支干道亮红灯*/
/*第2个状态:
主干道绿灯闪3次转亮黄灯、支干道亮红灯3S*/
/*第3个状态:
主干道亮红灯、支干道亮绿灯25S*/
/*第4个状态:
主干道亮红灯、支干道绿灯闪3次转亮黄灯3S*/
/*返回到第1个状态*/
/**/
/***************************************************************/
/*--------------显示子函数----------------------------*/
voiddisplay(uinttemp)
{
shi=temp%100/10;//显示十位
ge=temp%10;//显示个位
PC8255=0x01;
PA8255=table[shi];//显示十位
delay0(5);
PC8255=0x02;
PA8255=table[ge];//显示个位
delay0(5);
PC8255=0x04;
PA8255=table[shi];//显示十位
delay0(5);
PC8255=0x08;
PA8255=table[ge];//显示个位
delay0(5);
}
voidinit1()//---------------------第1个状态:
主干道亮绿灯30S、支干道亮红灯
{
uinttemp;
temp=20;//变量赋初值
aa=0;
TMOD=0x01;//定时器0工作于方式1
TH0=0x4C;
TL0=0x00;//定时器赋初值
ET0=1;//开定时中断
TR0=1;//开定时器0
while
(1)
{
PB8255=0XF3;//第二个状态:
主干道亮绿灯30S、支干道亮红灯
if(aa==20)//定时20*50MS=1S
{
aa=0;//定时完成一次后清0
temp--;//变量自增
if(temp==3)//定时
{
break;
}
}
display(temp);
}
}
voidinit2()//----------------------第2个状态:
主干道绿灯闪3次转亮黄灯、支干道亮红灯3S
{
uinttemp;
temp=3;//变量赋初值
aa=0;
TMOD=0x01;//定时器0工作于方式1
TH0=0x4C;
TL0=0x00;//定时器赋初值
ET0=1;//开定时中断
TR0=1;//开定时器0
while
(1)
{
PB8255=0XF5;
if(aa==20)//定时20*50MS=1S
{
aa=0;//定时完成一次后清0
temp--;//变量自增
if((temp+1)==0)//
{
break;
}
}
display(temp);
PB8255=0XF7;
display(temp);
}
}
voidinit3()//-----------------------第3个状态:
主干道亮红灯、支干道亮绿灯25S
{uinttemp;
temp=15;//变量赋初值
aa=0;
TMOD=0x01;//定时器0工作于方式1
TH0=0x4C;
TL0=0x00;//定时器赋初值
ET0=1;//开定时中断
TR0=1;//开定时器0
while
(1)
{
PB8255=0XDE;
if(aa==20)//定时20*50MS=1S
{
aa=0;//定时完成一次后清0
temp--;//变量自增
if(temp==3)//定时100S
{
break;
}
}
display(temp);
}
}
voidinit4()//-----------------------第4个状态:
主干道亮红灯、支干道绿灯闪3次转亮黄灯3S
{
uinttemp;
temp=3;//变量赋初值
aa=0;
TMOD=0x01;//定时器0工作于方式1
TH0=0x4C;
TL0=0x00;//定时器赋初值
ET0=1;//开定时中断
TR0=1;//开定时器0
while
(1)
{
PB8255=0XFE;
if(aa==20)//定时20*50MS=1S
{
aa=0;//定时完成一次后清0
temp--;//变量自增
if((temp+1)==0)//定时100S
{
break;
}
}
display(temp);
PB8255=0XEE;
display(temp);
}
}
voidinit5()//-----------------------第五个状态:
主干道和支干道亮红灯、
{
aa=0;//恢复软件定时初值
PB8255=0XDB;
PA8255=0XFF;
delay6ms();
}
voidxint0()interrupt2//-------------------外部中断1,这里用2是INT1的优先级为0
{
init5();
}
/*-------------定时中断子函数-----------------*/
voidxtimer0()interrupt1
{
TF0=0;
TH0=0x4C;
TL0=0x00;//定时器赋初值
aa++;
}
voidchange(void)//----------------------AD数字量转换成十进制码显示
{
jieguo=ad[0];
jieguo=(jieguo/255.0)*5;
a0[0]=(int)jieguo/10.0;
a0[1]=(int)(jieguo)%10;
a0[2]=(int)(jieguo*10)%10;
a0[3]=(int)(jieguo*100)%10;
PC8255=0X01;
PA8255=table[a0[0]];
delay0(5);
PC8255=0X02;
PA8255=table0[a0[1]];
delay0(5);
PC8255=0X04;
PA8255=table[a0[2]];
delay0(5);
PC8255=0X08;
PA8255=table[a0[3]];
delay0(5);
}
/*voidTimer1Interrupt(void)interrupt3//-----------------中断产生脉冲
{
TH1=0xFF;
TL1=0xFF;
P17=~P17;
}*/
voidsend(void)///////////////////////发送数据子程序
{
unsignedchari;
for(i=0;i<4;i++)
{
TB8=P;
SBUF=a0[i];
while(TI==0);
TI=0;
while(RI==0);
RI=0;
if(SBUF==0xff)
i--;
}
}
voidstart(void)
{
for(i=0;i<20;i++)
{
PC8255=0XFF;
PA8255=table[i];
delay0(200);
}
}
voidintial(void)//------------------------初始化函数
{
delay0(1000);
//TMOD=0x01;
//TH1=0xFF;
//TL1=0xFF;
//ET1=1;
SCON=0x90;
PCON=0X80;
COM8255=0X80;
PB8255=0XFF;
EA=1;//打开外部中断
key=-1;
}
/*---------------------主函数-------------------*/
voidmain(void)
{
intial();
start();
while
(1)
{
count=-1;
PB8255=0XFF;
int1();
PC8255=0XFF;
if(count!
=-1)
PA8255=table[count];
key=-1;
if(count==0)key=0;//0键按下闪烁彩灯
if(count==1)key=1;//AD转换功能
if(count==2)key=2;//交通灯功能
if(count==3)key=3;//DA转换
while(key==3)
{
while
(1)//DA转换
{for(i=0;i<255;i++)//输出锯齿波
{
DAC0832=i;
}
if(P32==0||P35==0)break;
}
while
(1)
{
DAC0832=0X00;
delay0(1000);
DAC0832=0XFF;
delay0(1000);
if(P32==0||P35==0)break;//输出方波
}
if(P35==0)break;
}
while(key==1)
{
PB8255=0XFF;
ad0809(ad);//启动AD转换
change();
if(P32==0)send();
if(P35==0)break;
}
while(key==2)//交通灯功能
{
EX1=1;
IT1=0;//INT0为沿触发方式
if(P35==0)break;
init1();//第1个状态
if(P35==0)break;
init2();//第2个状态
if(P35==0)break;
init3();//第3个状态
if(P35==0)break;
init4();//第4个状态
EX1=0;
ET0=0;//关闭定时中断
}
while(key==0)//0键按下闪烁彩灯,其它键按下显示键值
{
for(i=0;i<168;i++)
{PB8255=tablec[i];
delay0(150);
if(P35==0)break;
}
if(P35==0)break;
}}}
八、实验总结及心得
1、通过这次实验,让我对电路设计有了全新的认识,也对课堂上的知识有了更深的理解和记忆,
2、实验中,我学会了端口地址的概念,原理以及其使用的规则,尤其是端口地址在实际电路中的应用,显得尤为重要,没有端口地址,就不可能实现对外围器件的操作。
3、然就就是软件设计知识,,这个不能在很短的时间内学会,所以要多练习和多思考,慢慢的积累,养成设计计算机语言的习惯,使其具有可读性,且逻辑设计也要合理。
4、在设计程序前都要有大概想好程序设计的步骤和语言的结构,以便于在调试的时候方便,如果在开始编程的时候不注意这些,就会使得下次调试的时候更容易上手。
5、由于这次实验是软结合硬件来实现的,在调试的时候如果能掌握一定的方法就很荣翻译将调试好的成
6、在设计好硬件的时候,可以用万用表的二极管档来测试连线的连通性。
我说说几个自己出现的错误和改正的方法。
在设计交通灯时钟时,在按下紧急红灯之后,交通灯的计数器就停止,无法恢正常,原来是在紧急中断时,定时器还在计数(我采用的软件和硬件结合的定时方式),于是计数值过大,超过了判定计数减一时的范围。
就产生了死循环。
化,也有可能是没有足够的驱动电流,然后考虑怎样才能修改错误。
比如加上拉电阻来增加驱动能力。