《单片机原理与应用》 烟台大学 八次上机实验

实验一 系统认识实验

实验1 系统认识实验

1.打开KEILC
2.新建工程,Project->New Project,弹出Create New Project
创建工程文件的位置,不允许是桌面,也不允许是根目录,要创建一个自己的目录,且以英文为名,比如p1。工程文件名同样也必须是英文。按保存后,弹出选择CPU对话框
3.选择ATMEL下面的AT89C52单片机,确定
4.弹出一个对话框,问:Copy Standard ...。无条件选NO,如果选了YES,则把项目里面自动添加的STARTUP.A51文件remove
5.接下来新建一个源码,选择File下的new...
6.保存源码,选择File下面的Save,注意保存在和项目文件相同的文件夹下。保存时,如果时汇编语言源码,文件后缀一定是asm,比如p1.asm
7.开始写代码
比如:    ORG 0000H
    MOV A,#3AH
    MOV 20H,A
    MOV DPTR,#1000H
    MOVX @DPTR,A
    END
8.把源码添加进项目中,选中项目的Source Group 1按右键选择Add Files to Group...,找到刚才的源文件,添加进来。注意:在所有的8次实验中,项目下面只允许一个源文件!!!系统是支持多个源文件在一个项目中,但你们不知道该如何协调多个文件的功能区分,所以,只允许一个源文件。如果不小心添加进来,则remove。
9.使用编译按钮,把源码编译成机器码,要看到0 Errors 0 Warning。偶尔有时候会有Warning,大部分情况下Warning是没问题的,但不排除有问题,辩证得看。
10.编译通过后,可以进行仿真了,今天第一次实验,我们不用仿真器,直接在KEILC系统里做虚拟调试
按Debug按钮后出现一个黄色的箭头,指向第一行代码,左边出现了寄存器区(如果看不到,则选择View下面的Project Window打开)。如果想看存储器,则默认在右下角(如果看不到,则选择View下面的Memory Window)。
11.在Memory Window的Address处输入地址,则可以看到对于的存储器中的内容。
如果想看内部存储器,则输入:D:20h,则可以看到内部存储器20h开始的所有内存中的值。如果想修改内存中的值,则在对应的位置按右键,选择Modify...
如果想看外部存储器,则输入:X:1000h,则可以看到外部存储器1000h开始的所有内存中的值,如果想修改,同样按右键。
12.单步运行,同时监测对应寄存器和存储器中内容的变化,看看是否符合程序运行的目标。按单步运行Step Over按钮,可以一条一条指令的运行,同时看寄存器和内存的变化。不要按Run连续运行,啥也看不到

START: CLR C
	    MOV R0,#41H
MOV R1,#51H
AD1:   MOV A,@R0
	    ADD A,@R1
	    MOV @R0,A
	    DEC R0
	    DEC R1
	    MOV A,@R0
	    ADDC A,@R1
	    MOV @R0,A
	    RET

实验二 汇编语言跑马灯

实验2 汇编语言跑马灯

1. 第2个板子是主控板+电源板,左下角有一个红色按钮,是交流电源开关,这个开关,做实验时可以保持闭合状态。实验做完后关闭
2. 第2个板子的右下角有一个拨码开关,是直流开关,这个开关,在接线时,不能闭合,保持直流电源无电状态,当接好线,检查无误后,再打开这个开关
3. 第2个板子的下方中间位置就是一系列的电源提供端,有5V,有GND,还有其他电源模块,按需取用,左下方抽屉里有一些线可以用。尽量使用和电源圆角插座相同的颜色的线连接,这样容易排错。
4. 除了第2板子有电,其他板子都是没电。所以如果用到其他板子,用连接线接到其他板子,第一块板子的下方,有红色和黑色圆角插座,必须连接到第2块板子的电源5V和GND。
5. 我们用到的CPU,在仿真器里面,所以大家不要把仿真器拆下来,如果你看到拆下来了,检查一下排线红色端是不是朝上。
6. CPU上面有一些端子引线,上面标识了P0,P1,P2,P3。这四个黑色的排线插座分别对应CPU的四个端口。可以使用灰色的排线进行连接。再往上还有一些圆口插座,上面标识了P0.0~P0.7,.....。也是CPU的端口线,这个线用单股线连接
7. 第一块板子的第4个部分指示灯模块,每个圆角插座对应一个灯,黑色的插座对应着8个灯。
8. 第一块板子的第五部分,对应着8个拨码开关,每个圆角插座对应一个开关。

实验要求:
1. 用8个指示灯模块,设计一个跑马灯,先让第一个灯亮,然后让第2个灯亮,。。。。让第8个灯亮,接下来让第一个灯亮,循环往复。
        ○○○○○○○●
        ○○○○○○●○
        ○○○○○●○○
        ○○○○●○○○
        ○○○●○○○○
        ○○●○○○○○
        ○●○○○○○○
        ●○○○○○○○
2. 用一个拨码开关输入到单片机,当拨码开关往上拨时,执行循环左移,当拨码开关往下拨时,执行右移,灯亮的次反过来。
拨码开关往上拨:
        ○○○○○○○●
        ○○○○○○●○
        ○○○○○●○○
        ○○○○●○○○
        ○○○●○○○○
        ○○●○○○○○
        ○●○○○○○○
        ●○○○○○○○
拨码开关往下拨
        ●○○○○○○○
        ○●○○○○○○
        ○○●○○○○○
        ○○○●○○○○
        ○○○○●○○○
        ○○○○○●○○
        ○○○○○○●○
        ○○○○○○○●

涉及到技术:
1. 如何把程序下载,连接蓝色的线到计算机USB口,另外一端接到仿真器。在设备管理器的端口处出现一个新的COM。一般是COM3
2. 把工程里的target1的OPTION里的DEBUG切换到USE KEIL-MONITOR51,然后在后面的SETTING处,把端口切换到刚才新出现的端口,比如COM3,波特率切换到115200,而不是11520
3. 此时再按DEBUG按钮,程序会自动下载到仿真器的CPU里。
4. 如何驱动指示灯,假如LED的8个灯接到P0口
   这个灯是低电平亮
    MOV A, #0FEH; FE(11111110)是最低位为0.所以对应的P0.0口灯会亮
    MOV P0, A

    MOV A, #0FDH; FD(11111101)是次低位为0.所以对应的P0.1口灯会亮
    MOV P0, A

5. 如何接受按键的状态,假设拨码开关接在P1.0上
    ;第一种读法,只读一位
    MOV C, P1.0;读接在P1.0口的一个状态
    JC LED1

    ;第二种读法,读P1口上的全部8位
    MOV A, P1;读接在P1口的八个状态

6. 如何延时
    两重循环,做延时
主程序
    CALL DELAY;


子程序
DELAY:
    MOV R5, #200
DELAY2:    MOV R6, #200
DELAY1:    DJNZ R6, DELAY1
    DJNZ R5, DELAY2
    RET

MOV A,#0FEH		;LED低电平点亮
START:
	MOV P0,A			;将A代表的8位数据,点亮相应LED
	CALL DELAY
	
	MOV C,P1.0			;P1.0是位操作,写入进位位C
	JC LED1				;进位为1,则跳转到LED1
	
	RL A					;左移一位
	JMP START
LED1:
	RR A					;右移一位
	JMP START
  
DELAY:
	MOV R3,#200
DELAY2: MOV R4,#200
DELAY1: DJNZ R4, DELAY1
	DJNZ R3, DELAY2
	RET
END

单片机连线图 

实验三 C语言的复杂跑马灯 

实验3  C语言的复杂跑马灯

1. 创建一个C语言工程
2. 创建一个源码。用.c作为后缀,源码里必须有一个死循环。因为我们的单片机运行,是要一直跑的,不是跑一会就结束,是要永远跑的,所以必须要有一个死循环,代码永远跑。
    #include <reg52.h>

    main()
    {
        while(1)
        {
        
        }
    }
3. 实现一个能用拨码开关控制的复杂跑马灯
    (1)拨码开关1往上时,实现最普通的左移跑马灯
        ○○○○○○○●
        ○○○○○○●○
        ○○○○○●○○
        ○○○○●○○○
        ○○○●○○○○
        ○○●○○○○○
        ○●○○○○○○
        ●○○○○○○○
    (2)拨码开关2往上时,实现
        ●○○○○○○●
        ○●○○○○●○
        ○○●○○●○○
        ○○○●●○○○
        ○○●○○●○○
        ○●○○○○●○
        ●○○○○○○●
    (3)拨码开关3往上时,实现八个灯闪烁
        ●●●●●●●●
        ○○○○○○○○
        ●●●●●●●●
        ○○○○○○○○

涉及的操作

#include <reg52.h>
sbit key1 = P1^0;//拨码开关1
sbit key2 = P1^1;//拨码开关2
sbit key3 = P1^2;//拨码开关3

void delay()
{
    unsigned char i,j;
    for(i = 0; i < 200; i++)
        for(j = 0; j < 200; j++)
            ;
}

main()
{
    unsigned char led,key;
    while(1)
    {
        //控制灯的显示
        led = 0x7e;//01111110
        P0 = led; //最高和最低位灯亮,其他不亮
    
        //第一种按键读取方式,一次读八个输入
        key = P1;
        //判断八个输入中的每一个
        if(key&0x01) //拨码开关1,最低位按键判断
        {
        }
        if(key&0x02) //拨码开关2,次低位按键判断
        {
        }    
        if(key&0x04) //拨码开关3,次次低位按键判断
        {
        }

        //第二种按键读取方式,一次判断一个按键
        if(key1) //拨码开关1,最低位按键判断
        {
        }
        if(key2) //拨码开关2,次低位按键判断
        {
        }    
        if(key3) //拨码开关3,次次低位按键判断
        {
        }
        delay();
    }
}

#include <REGX52.H>
sbit key1 = P1^0; // 拨码开关1
sbit key2 = P1^1; // 拨码开关2
sbit key3 = P1^2; // 拨码开关3
unsigned char LED1[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
unsigned char LED2[] = {0x7e, 0xbd, 0xdb, 0xe7, 0xdb, 0xbd, 0x7e};

void delay()
{
    unsigned char i, j;
    for (i = 0; i < 200; i++)
        for (j = 0; j < 200; j++)
            ;
}

void main()
{
    unsigned char led, key, i;

    while (1)
    {									//实现循环左移
        if (key1)
        {
            for (i = 0; i < 8; i++)
            {
                led = LED1[i];
                P0 = led;
                delay();
                key = P1;
            }
        }

        if (key2)
        {								//实现双向循环
            for (i = 0; i < 7; i++)
            {
                led = LED2[i];
                P0 = led;
                delay();
                key = P1;
            }
        }

        if (key3)
        {
            led = 0xff;				 // 11111111, LED全灭
            P0 = led;
            delay();
            key = P1;
            led = 0x00; 			// 00000000, LED全亮
            P0 = led;
            delay();
            key = P1;
        }
    }
}

单片机连线图 

实验四 C语言的抢答器

 实验4  C语言的抢答器

1. 创建一个C语言工程
2. 创建一个源码。用.c作为后缀,源码里必须有一个死循环。因为我们的单片机运行,是要一直跑的,不是跑一会就结束,是要永远跑的,所以必须要有一个死循环,代码永远跑。
    #include <reg52.h>

    main()
    {
        while(1)
        {
        
        }
    }
3. 实现一个能用点动开关控制的抢答器,同时按下多个点动开关,找出最先按下的那个开关,并显示在8段数码管上,注意要保持住最先按下键对应的显示结果,不受后面其他人多次点按的影响。
4.读按键
    同时读8个点动开关
    unsigned char key;
    key = ~P1;//实验平台的开关,按下是0,此处对P1的输入取反,按下是1,方便判断
    
    //判断按键的第一种写法
    if(key&0x01){
    }
    else if(key&0x02){
    }
    
    //判断按键的第二种写法
    switch(key)
    {
        case 0x01:
            break;
        case 0x02:
            break;
        .....
    }

5. 显示8段数码管
    P0 = seg8

    ---a---
    |      |
    |      |
    f      b
    |      |
    |      |
    ---g---
    |      |
    |      |
    e      c
    |      |
    |      |
    ---d---   _dp

    _gfedcba

为了显示1,要点亮b和c,则送给P0口显示的应该是00000110,seg8=06H
为了显示2,要点亮a,b,d,e和g,则送给P0口显示的应该是01011011,seg8=5BH

#include <reg52.h>

unsigned char seg8[] = {0x06,0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f};

void main()
{
    unsigned char x = 1;
    while (1)
    {
        unsigned char key;
        key = ~P1;

        if (x)
        {
            if (key & 0x01)
            {
                P0 = seg8[0];
				x = 0;
            }
            else if (key & 0x02)
            {
                P0 = seg8[1];
				x = 0;
            }
            else if (key & 0x04)
            {
                P0 = seg8[2];
				x = 0;
            }
            else if (key & 0x08)
            {
                P0 = seg8[3];
				x = 0;
            }
            else if (key & 0x10)
            {
                P0 = seg8[4];
				x = 0;
            }
            else if (key & 0x20)
            {
                P0 = seg8[5];
				x = 0;
            }
            else if (key & 0x40)
            {
                P0 = seg8[6];
				x = 0;
            }
            else if (key & 0x80)
            {
                P0 = seg8[7];
				x = 0;
            }
        }
    }
}

 单片机连线图 

实验五 汇编语言中断

实验5  汇编语言外部中断

1. 创建一个汇编语言的工程。源码后缀asm
2. 中断代码的框架
    ORG 0000H;上电后的程序启动地址
    JMP START

    ORG 0003H;外部中断0的入口地址
    JMP EINT0

    ORG 0013H;外部中断1的入口地址
    JMP EINT1

START: ;此处写主程序


    ;主程序中至少包含一个无限循环


EINT0: ;此处写外部中断0的代码
    
    ;在中断服务程序里,禁止直接跳转到主程序
    ;必须通过RETI返回被中断的位置
    RETI

EINT1: ;此处写外部中断1的代码
    
    ;在中断服务程序里,禁止直接跳转到主程序
    ;必须通过RETI返回被中断的位置

    RETI


3. 如何初始化中断
    SETB IT0;定义外部中断0为边沿触发
    SETB EX0;使能外部中断0
    SETB IT1;定义外部中断1为边沿触发
    SETB EX1;使能外部中断1
    SETB EA;使能总中断

4. 本次实验的任务
在主程序(网上的代码,跑马灯都是写在中断里的)做一个左移跑马灯和一个右移跑马灯,但不跑,用外部中断0和中断1控制是否跑动,当触发外部中断0时,做左移八次的跑马灯。当触发外部中断1时,做右移八次的跑马灯。

5. 怎么触发中断?
外部中断0接P3.2口,外部中断1接P3.3口
使用按键模块中的两个按键,接到P3.2和P3.3口,则按下按键时,会在端口上产生下降沿。则会导致单片机内部触发中断

ORG 0000H;上电后的程序启动地址
	JMP START
	ORG 0003H;外部中断0的入口地址
	JMP EINT0
	ORG 0013H;外部中断1的入口地址
	JMP EINT1
START: ;此处写主程序
	SETB IT0;定义外部中断0为边沿触发
	SETB EX0;使能外部中断0
	SETB IT1;定义外部中断1为边沿触发
	SETB EX1;使能外部中断1
	SETB EA;使能总中断
	;主程序中至少包含一个无限循环
	MOV A, #0FEH
	CJNE R7,#0H,LEFT
	
LEFT:
	CJNE R7,#10H,RIGHT	
	RL A
	MOV P0, A
	CALL DELAY
	RL A
	MOV P0, A
	CALL DELAY
	RL A
	MOV P0, A
	RL A
	MOV P0, A
	CALL DELAY
	RL A
	MOV P0, A
	CALL DELAY
	RL A
	MOV P0, A
	CALL DELAY
	RL A
	MOV P0, A
	CALL DELAY
RL A
	MOV P0, A
	CALL DELAY

	MOV R7,#40H
	JMP START

RIGHT:
	CJNE R7,#20H,START	
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	RR A
	MOV P0, A
	CALL DELAY
	MOV R7,#40H
	JMP START

EINT0: ;此处写外部中断0的代码
	MOV R7,#10H
	RETI

EINT1: ;此处写外部中断1的代码
	MOV R7,#20H
	RETI

DELAY:
	MOV R3,#200
DELAY2: MOV R4,#200
DELAY1: DJNZ R4,DELAY1
	DJNZ R3,DELAY2
RET
END

 单片机连线图 

实验六 C语言的中断

实验6  C语言外部中断

1. 创建一个C语言的工程。源码后缀c

2. C语言的中断代码框架
    #include "reg52.h"
    
    void int0() interrupt 0        //INT0中断
    {
    }
    
    void int1() interrupt 2        //INT1中断
    {
    }
    
    void main()
    {
        while(1)
        {
        }
    }

3. C语言初始化中断
    IT0 = 1;
    EX0 = 1;            //中断0
    IT1 = 1;
    EX1 = 1;            //中断1
    EA = 1;

4. 程序需求
(1) 必须在主程序中实现左移跑马灯和8段数码管上0~9循环计数,而不是在中断中实现
(2) 用两个按键触发中断(接到P3.2/P3.3),当中断0触发时,执行左移循环跑马灯,当中断1触发时,执行在8段数码管上的0~9循环计数

#include "reg52.h"
unsigned char x=0;
unsigned char SEG[]={0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char LED[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void delay()
{
	unsigned char i,j;
	for(i = 0; i < 200; i++)
		for(j = 0; j < 200; j++)
			;
}
void int0() interrupt 0		//INT0中断
{
	x=1;
}
void int1() interrupt 2		//INT1中断
{
	x=2;
}
	
void main()
{
	IT0 = 1;
	EX0 = 1;			//中断0
	IT1 = 1;
	EX1 = 1;			//中断1
	EA = 1;
	while(1)
	{
		unsigned char i;
	//判断按键的第一种写法
	    if(x==1)
        {
            for (i=0;i<8;i++)
		    {
		         P0=LED[i];			//查表法
		         delay();
            }
		    x=0;
    	}
	    else if(x==2)
        {
		    for(i=0;i<9;i++)
	        {
	            P2=SEG[i];		
                delay();
            }
	            x=0;
	    }
	}
}

 单片机连线图 

实验七 汇编语言定时器

实验7  汇编语言定时器

1. 创建一个汇编语言的工程。源码后缀asm
2. 中断代码的框架
    ORG 0000H;上电后的程序启动地址
    JMP START

    ORG 000BH;定时器0中断的入口地址
    JMP TIME0

    ORG 001BH;定时器1中断的入口地址
    JMP TIME1

START:    ;此处写主程序


TIME0: ;此处写定时器0中断的代码
    

    RETI

TIME1: ;此处写定时器1中断的代码
    

    RETI

3. 如何初始化定时器
    ;初始化定时器参数
    本系统的主频12MHZ
    上课时,案例是方式0,我在课堂上修改成了方式1
    涉及到TMOD:GATE C/T M1 MO
    计算 TH0 TL0 TH1 TL1
    自己搞定
    
    ;初始化定时器0中断
    SETB TR0;启动定时器0
    SETB ET0;使能定时器0中断
    
    ;初始化定时器1中断
    SETB TR1;启动定时器1
    SETB ET1;使能定时器1中断
    
    SETB EA;使能总中断

4. 今天的任务

(1)做方波信号发生器,用定时器在一个IO口上产生1HZ方波(CPU主频是12MHZ,用16位定时器是无法产生0.5秒延时的,需要再配合计数器),把IO口接在指示灯上,肉眼能看到1HZ闪烁

(2)利用定时器的0.5秒延时,控制跑马灯的延时,产生每隔0.5秒灯左移的效果

ORG 0000H
	AJMP START
	ORG 000BH;定时器0中断的入口地址
	AJMP TIME0
	ORG 001BH
	AJMP TIME1

START:	
	MOV A,#0FEH		;LED低电平点亮
	MOV SP,#60H
	MOV TMOD,#11H

	MOV R0,#10H
	MOV TH1,#09H
	MOV TL1,#0DCH

	MOV R1,#10H
	MOV TH0,#09H
	MOV TL0,#0DCH

	SETB TR0;启动定时器0
	SETB ET0;使能定时器0中断
	SETB TR1
	SETB ET1
	SETB EA	

MAIN:	AJMP MAIN
TIME0: 
	DJNZ R1,NEXT0
	MOV P0,A
	RL A
	MOV R1,#10H
	MOV TH0,#09H
	MOV TL0,#0DCH
NEXT0:	RETI
	
TIME1: 
	DJNZ R0,NEXT1
	CPL P2.0
	MOV R0,#10H
MOV TH1,#09H
	MOV TL1,#0DCH
NEXT1:	RETI
END

 单片机连线图 

实验八 C语言的定时器

实验8  C语言定时器

1. 创建一个C语言的工程。源码后缀c

2. C语言的中断代码框架
    #include "reg52.h"
    
    void int0() interrupt 1        //定时器0中断
    {
    }


    void main()
    {
        while(1)
        {
        }
    }

3. C语言定时器初始化   

    TR0 = 1;//启动定时器0
    ET0 = 1;//使能定时器0中断
    EA = 1;//使能总中断
 

4. 程序需求

(1)做方波信号发生器,用定时器在一个IO口上产生1HZ方波(CPU主频是12MHZ,用16位定时器是无法产生0.5秒延时的,需要再配合计数器),把IO口接在指示灯上,肉眼能看到1HZ闪烁

(2)利用定时器的0.5秒延时,控制跑马灯的延时,产生每隔0.5秒灯左移的效果

#include "reg52.h"
sbit p11=P3^1;
sbit p22=P3^0;
unsigned A=0x01;
unsigned char c=0;
unsigned char x,y=0;
void time0() interrupt 1 //定时器0中断
{
    TH0=0x3C;
    TL0=0XB0;
    c++;
    if(c==10)
    {
        c=0;
        if(x==1)
        {
            P1=~A;
            A=A<<1;
            if(A==0)
            {
                A=0x01;
            }
        }
        if(y==1)
        {
            P1=~A;
            A=A>>1;
            if(A==0)
            {
                A=0X80;
            }
        }
    }
}
void main()
{
    P1=~A;
    TMOD=0x01;
    TH0=0x3C;
    TL0=0xB0;
    TR0 = 1;//启动定时器0
    ET0 = 1;//使能定时器0中断
    EA = 1;//使能总中断

    while(1)
    {
        if(p11==0)
        {
            x=1;
            y=0;
        }
        if(p22==0)
        {
            x=0;
            y=1;
        }
    }
}

 单片机连线图 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值