单片机实验报告

单片机原理及应用

实验报告

姓    名:    王 翀     学号631206040204

班    级:  通信工程 专业 20##级  2班  

指导教师:           许  强             

实验项目名称:    键盘、数码管显示综合实验             

实验日期:   12.21                 实验成绩:            

实验评定标准:

一、实验目的

通过实验,掌握单片机在输入输出口线不够用时,怎样扩展接口的方法来支持8位LED显示和16键盘集成实现。熟悉8155、8279等芯片性能;掌握其编程方法。掌握键盘子程序调试方法,掌握按一个键并将键值显示出来的编程方法,这是诊断硬件、测试硬件、产品开

发、软件编程必须掌握的方法。

二、实验器材

实作实验的器材:

组合最小系统板、14 脚插座板、20 脚插座板、六位数显板,开发系统一台或固化器一台、+5V 电源一台。

三、实验内容

通过8155芯片的扩展功能,建立描述线与数据线同步功能。

①  编写并调试出一个键盘实验子程序。

② 用子程序调用方法,调用显示子程序,将按一个键的键值(0-F),在数码管上显示出来。

扩展部分为:实现模拟控制十字路口交通灯功能。

四、实验步骤

1)仿真实验过程:

打开Keil程序,执行菜单命令“Project”-“New Project”创建“键盘数码管显示综合实验”项目,并选择单片机型号为AT89C52.BUS。

执行菜单命令“File”-“New”创建文件,输入源程序,保存为“键盘数码管显示综合实验.A51或键盘数码管显示综合实验.c”。在“Project”栏的File项目管理窗口中右击文件组,选择“Add Files to Group ‘Source Group1’”将源程序“键盘数码管显示综合实

验.A51或键盘数码管显示综合实验.c”添加到项目中。执行菜单命令“Project”-“Options for Target ‘Target 1’”,在弹出的对话框中选择“Output”选项卡,选中“Greate HEX File”。执行菜单命令“Project”-“Build Target”,编译源程序。如果编译成功,则在“OutputWindow”窗口中显示没有错误,并创建了“键盘数码管显示综合实验.HEX”文件。

在proteus仿真平台上建立参考图系统,并将程序上载到虚拟芯片上调试及运行。

数码管显示部分实验代码:


 ORG 0000H

START: LJMP MAIN

         ORG 0030H

MAIN: MOV SP,#60H

         MOV 7AH,#00

         MOV 7BH,#01

         MOV 7CH,#02

         MOV 7DH,#03

         MOV 7EH,#04

         MOV 7FH,#05

         MOV DPTR,#7300H ;8155命令口地址

         MOV A,#89H ;置8155PA、PB口为输出,PC口为输入

         MOVX @DPTR,A

LOOP: LCALL DISP                                                                   

         LCALL KEY

         MOV A,R4

         CJNE A,#88H,DSP

         SJMP LOOP

DSP: MOV 7AH,A ;键值送入显示缓冲区单元7AH

         MOV 7BH,#010H

         MOV 7CH,#010H

         MOV 7DH,#010H

         MOV 7EH,#010H

         MOV 7FH,#010H

         SJMP LOOP

         ;按键识别子程序

KEY: MOV R4,#00H ;0→键号寄存器R4

         MOV R2,#01H ;扫描模式01H→R2

KEY1: MOV DPTR,#7100H

         MOV A,R2

         MOVX @DPTR,A ;扫描模式→8155PB口

         //INC DPTR

          mov  dptr,#7200H;

         MOVX A,@DPTR ;读8155PC口

         JB ACC.0,KEY2 ;0列无键闭合,转判1列

         MOV A,#00H ;0列有键闭合,0→A

         AJMP KEY5

KEY2: JB ACC.1,KEY3 ;1列无键闭合,转判2列

         MOV A,#01H ;1列有键闭合,列线号01H→A

         AJMP KEY5

KEY3: JB ACC.2,KEY4 ;2列无键闭合,转判3列

         MOV A,#02H ;2列有键闭合,02H→A

         AJMP KEY5

KEY4: JB ACC.3,NEXT ;3列无键闭合,转判下一行

         MOV A,#03H ;3列有键闭合,03H→A

KEY5: ADD A,R4 ;列线号+(R4)作为键值→A

         MOV R4,A ;键值→R4

         RET ;返回

NEXT: MOV A,R4;

         ADD A,#04 ;键号寄存器加4

         MOV R4,A

         MOV A,R2

         JB ACC.3,NEXT1 ;判别是否已扫描到最后一行

         RL A ;扫描模式左移一位

         MOV R2,A

         AJMP KEY1 ;重新开始扫描下一行

NEXT1: MOV R4,#88H ;扫描到最后一行仍无按键置无键闭合标志

         RET

         ;数码管显示组程序

DISP: MOV R0,#7AH ;置显示缓冲器指针初值

         MOV R3,#01H ;置扫描模式初值

DISPB1: MOV DPTR,#7100H ;8155 PB口地址

         MOV A,#0h ;熄灭所有LED

         MOVX @DPTR,A

         MOV DPTR,#7000H ;8155 PA口地址

         MOV A, @R0 ;取显示数据

         ADD A,#014H ;加偏移量

         MOVC A, @A+PC ;查表取段码

         MOVX @DPTR,A ;段码→8155 PA口

         MOV A,R3

         MOV DPTR,#7100H ;8155 PB口地址

         MOVX @DPTR,A ;扫描模式→8155 PB口

         ACALL DELAY ;延时

         INC R0

         MOV A,R3

         JB ACC.6,DISPB2 ;判6位LED显示完否

         RL A ;扫描模式左移1位

         MOV R3,A

         AJMP DISPB1

DISPB2: MOV R3,#01H

         RET

SEGPT2: Db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h ;段码表

         db 7fh,6fh,77h,7ch,39h,5eh,79h,71h

         db 00h,02h,08h,00h,59h,0fh,76h

         ;延时子程序

DELAY: MOV R4,#0FFH

DELAY1: DJNZ R4,DELAY1

         RET

         END


其实验电路图:

结果显示:

十字路口交通灯流程示意图:

十字路口交通灯控制 C 程序:

       十字路口交通灯控制 C 程序

******************************************************/


#define  uchar    unsigned char

#define  uint unsigned int

#include <reg52.h>

/*****定义控制位**********************/

sbit    Time_Show_LED2=P2^5;//Time_Show_LED2控制位

sbit    Time_Show_LED1=P2^4;//Time_Show_LED1控制位

sbit EW_LED2=P2^3; //EW_LED2控制位

sbit EW_LED1=P2^2; //EW_LED1控制位

sbit SN_LED2=P2^1; //SN_LED2控制位

sbit SN_LED1=P2^0; //SN_LED1控制位

sbit    SN_Yellow=P1^6;//SN黄灯

sbit    EW_Yellow=P1^2;//EW黄灯

sbit    EW_Red=P1^3;//EW红灯

sbit    SN_Red=P1^7;//SN红灯

sbit    EW_ManGreen=P3^0;//EW人行道绿灯

sbit    SN_ManGreen=P3^1;//SN人行道绿灯

sbit    Special_LED=P2^6;//交通正常指示灯

sbit    Busy_LED=P2^7;//交通繁忙指示灯

sbit    Nomor_Button=P3^5;//交通正常按键

sbit    Busy_Btton=P3^6;//交通繁忙按键

sbit    Special_Btton=P3^7;//交通特殊按键 

sbit    Add_Button=P3^3;//时间加

sbit    Reduces_Button=P3^4;//时间减

bit     Flag_SN_Yellow; //SN黄灯标志位

bit     Flag_EW_Yellow;//EW黄灯标志位

char Time_EW;//东西方向倒计时单元

char Time_SN;//南北方向倒计时单元

uchar EW=60,SN=40,EWL=19,SNL=19; //程序初始化赋值,正常模式

uchar EW1=60,SN1=40,EWL1=19,SNL1=19;//用于存放修改值的变量

uchar code table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//1~~~~9段选码

uchar code S[8]={0X28,0X48,0X18,0X48,0X82,0X84,0X81,0X84};//

交通信号灯控制代码

/**********************延时子程序************************/

void Delay(uchar   a)

     {

uchar    i;

i=a;

         while(i--){;}}

void Display(void)

     {

         char h,l;

         h=Time_EW/10;

         l=Time_EW%10;

         P0=table[l];

         EW_LED2=1;

         Delay(2);

         EW_LED2=0;

         P0=table[h];

         EW_LED1=1;

         Delay(2);

         EW_LED1=0;

         h=Time_SN/10;

         l=Time_SN%10;

         P0=table[l];

         SN_LED2=1;

          Delay(2);

         SN_LED2=0;

         P0=table[h];

         SN_LED1=1;

         Delay(2);

         SN_LED1=0;

         h= EW1/10;

         l= EW1%10;

         P0=table[l];

         Time_Show_LED1=1;

         Delay(2);

        Time_Show_LED1=0;

         P0=table[h];

         Time_Show_LED2=1;

         Delay(2);

         Time_Show_LED2=0;

}

/**********************外部0中断服务程序************************/

void EXINT0(void)interrupt 0 using 1

     {

         EX0=0; //关中断

if(Add_Button==0) //时间加

       {

            EW1+=5;

            SN1+=5;

              if(EW1>=100)

                 {

                   EW1=99;

                   SN1=79;

               }

            }

if(Reduces_Button==0) //时间减

       {

            EW1-=5;

            SN1-=5;

            if(EW1<=40)

              {

                   EW1=40;

                 SN1=20;

               }

                  

             }

if(Nomor_Button==0)//测试按键是否按下,按下为正常状态

        {

            EW1=60;

            SN1=40;

              EWL1=19;

              SNL1=19;

              Busy_LED=0;//关繁忙信号灯

              Special_LED =0;//关特殊信号灯

            }

if(Busy_Btton==0) //测试按键是否按下,按下为繁忙状态

        {

             EW1=45;

            SN1=30;

              EWL1=14;

              SNL1=14;

              Special_LED=0;//关特殊信号灯

              Busy_LED=1;//开繁忙信号灯

        

        }

if(Special_Btton==0)//测试按键是否按下,按下为特殊状态{

             EW1=75;

            SN1=55;

              EWL1=19;

              SNL1=19;

              Busy_LED=0;//关繁忙信号灯

             Special_LED =1;//开特殊信号灯

                 

         }                      

         EX0=1;//开中断

     }

     void timer0(void)interrupt 1 using 1

{

     static uchar count;

     TH0=(65536-50000)/256;

     TL0=(65536-50000)%256;

     count++;

     if(count==10)

     {

       if(Flag_SN_Yellow==1) //测试南北黄灯标志位

       {SN_Yellow=~SN_Yellow;}

       if(Flag_EW_Yellow==1)  //测试东西黄灯标志位

       {EW_Yellow=~EW_Yellow;}

     }

     if(count==20)

     {

     Time_EW--;

     Time_SN--;

     if(Flag_SN_Yellow==1)//测试南北黄灯标志位

         {SN_Yellow=~SN_Yellow;}

     if(Flag_EW_Yellow==1)//测试东西黄灯标志位

         {EW_Yellow=~EW_Yellow;}

     count=0;

     }}

/*******************************************/

void main(void)

{

     Busy_LED=0;

     Special_LED=0;

     IT0=1;   //INT0负跳变触发 

    TMOD=0x01;//定时器工作于方式1

     TH0=(65536-50000)/256;//定时器赋初值

     TL0=(65536-50000)%256;

     EA=1; //CPU开中断总允许

     ET0=1;//开定时中断

     EX0=1;//开外部INTO中断

    TR0=1;//启动定时

     while(1)

{                  /*******S0状态**********/

                   EW_ManGreen=0;     //EW人行道禁

                 SN_ManGreen=1;//SN人行道通行

                Flag_EW_Yellow=0;       //EW关黄灯显示

                   Time_EW=EW;  

                   Time_SN=SN;       

                   while(Time_SN>=5)

                  {P1=S[0]; //SN通行,EW红灯

                  Display();}

                   /*******S1状态**********/

                  P1=0x00;

                   while(Time_SN>=0)

                 {Flag_SN_Yellow=1;                              EW_Red=1;    

                   Display();

                   }

                   /*******S2状态**********/

                  Flag_SN_Yellow=0; //SN关黄灯显

                   Time_SN=SNL;

                   while(Time_SN>=5)

                   {P1=S[2];//SN左拐绿灯亮,EW红

                    Display();}

                /*******S3状态**********/

                   P1=0x00;

                   while(Time_SN>=0)

                 {Flag_SN_Yellow=1;  //SN开黄灯信

                  EW_Red=1;      //SN黄灯亮,等待

                  Display();}

                 /***********赋值**********/

                   EW=EW1;

                   SN=SN1;

                   EWL=EWL1;

                   SNL=SNL1;

                   /*******S4状态**********/

                   EW_ManGreen=~EW_ManGreen;//EW

                 SN_ManGreen=~SN_ManGreen;//SN人行

                   Flag_SN_Yellow=0;  //SN关黄灯

                   Time_EW=SN;

                   Time_SN=EW;

                  while(Time_EW>=5)

                  {P1=S[4]; //EW通行,SN红灯

                    Display();}

                   /*******S5状态**********/

                   P1=0X00;

                   while(Time_EW>=0)

                 {Flag_EW_Yellow=1;//EW开黄灯信号

                  SN_Red=1;//EW黄灯亮,等待左拐信

                  Display();}

                   /*******S6状态**********/

                   Flag_EW_Yellow=0;     

                   Time_EW=EWL;

                   while(Time_EW>=5)

                   {P1=S[6];//EW左拐绿灯亮,SN红                 Display();}

                   /*******S7状态**********/

                   P1=0X00;

                   while(Time_EW>=0)

                 {Flag_EW_Yellow=1; //EN开黄灯信                SN_Red=1;//EW黄灯亮,等待停止信               Display();}

                    /***********赋值**********/

                  EW=EW1;

                   SN=SN1;

                   EWL=EWL1;

                   SNL=SNL1;

              }

}

模拟十字路口交通灯实验结果:

 

我们用“自动控制”控制交通灯的方法。将事先编制好的程序输入单片机,利用单片机的定时、查询、中断功能;能够根据十字路口两个方向上车辆动态状况,采用查询的方式,根据具体情况,自动给予时间通行,其中利用中断方式来处理特殊情况。这样既方便驾驶员、路人,同时还可以紧急处理一些紧急实况。同样具有红、黄、绿灯的显示功能,为驾驶员、路人“照明”。

南北方向(主干道)车道和东西方向(支干道)车道两条交叉道路上的车辆交替运行,主干道每次通行时间都设为40秒、支干道每次通行间为60秒,时间可设置修改。在绿灯转为红灯时,要求黄灯先亮5秒钟,才能变换运行车道;黄灯亮时,要求每秒闪亮一次。东西方向、南北方向车道除了有红、黄、绿灯指示外,每一种灯亮的时间都用显示器进行显示(采用计时的方法)。一道有车而另一道无车,交通灯控制系统能立即让有车道放行。 有紧急车辆要求通过时,系统要能禁止普通车辆通行,A、B道均为红灯,紧急车由开关控制模拟。

CS-51单片机资源在实际的应用设计中,往往会出现系统资源或者是外部接口不够的情况,此时,我们可以通过一些特殊的芯片与单片机相互连接实现更多的系统功能。此次实验相对于前几个实验电路图比较复杂,在连接电路图时用上了总线的连接。由于该实验的程序是用汇编语言编写的,其程序代码比较多,我们本来对汇编语言编写程序就不是很熟悉,所以在实际操作中还是很慢很困难,最后通过一系列的询问和参考别人代码得到解决问题的方法。

总的来说,这次实验使我们对单片机有了不一样的认识,对它的操作有了更多的了解,这会使我们以后进行单片机操作时更加熟悉。

相关推荐