实验四51单片机并口实验

一.实验目的:

1. 了解51单片机I/O口的电气特性和驱动能力。

2. 了解LED电路中加入限流电阻的原因。

3. 掌握定时器原理及编程。

4. 掌握并口程序的编辑、编译、调试和运行。

二.实验设备和器件

1. PC

2. PROTEUS仿真软件   

3. 实验箱

4. ISP下载器

5. 51仿真器            

三.实验内容

(1)编程实现:采用定时器0每隔1s点亮1发光二极管

① 电路图:

 

② 代码:

Ø 中断处理方式:

ORG 0000H

LJMP MAIN  

ORG 000BH

LJMP INTT0

ORG 0100H

MAIN:

MOV TMOD,#01H   //TMOD为方式寄存器,该题是定时器0,且为方式1,则TMOD=0000_0001

MOV TH0,#3CH   

MOV TL0,#0B0H  //初值的计算

MOV R2,#00H    //计数寄存器

MOV A,#0FEH    

MOV P0, A      //设置灯的初状态,第D0个灯亮

SETB EA      // 允许单片机总中断,SETB bit:位置1

SETB ET0     //允许T0溢出中断

SETB TR0     //开启定时器0

SJMP $       //必须要有死循环,表示等待定时过程,否者只有一个灯亮

INTT0:       //定时到进入中断

MOV TH0,#3CH

MOV TL0,#0B0H   //每次定时都需要重新赋初值

INC R2          //计数次数加1

CJNE R2,#0AH,NEXT   //判断计数次数是否等于10,不等跳转到NEXT

RL    A            //计数次数到10次之后,A左移

MOV   P0, A        //下一个灯亮

MOV R2,#00H        //计数清0

NEXT:

RETI

END

Ø 查询处理方式:

ORG 0000H

LJMP MAIN

ORG 0100H

MAIN:

MOV TMOD,#01H

MOV TH0,#3CH

MOV TL0,#0B0H

MOV R2,#00H

MOV A,#0FEH

MOV P0,A

SETB TR0

LOOP:

JBC TF0,NEXT1 //判断TF0是否溢出,及TF0是否为1,有则跳转到NEXT1,并把TF0清0

SJMP LOOP    //无溢出,一直查询

NEXT1:  

MOV TH0,#3CH

MOV TL0,#0B0H  //每次定时都需要重新赋初值

INC R2

CJNE R2,#0AH,NEXT

RL   A

MOV  P0, A

MOV  R2,#00H

SJMP LOOP

NEXT:

SJMP LOOP

SJMP $

END

③ 分析:

初值的计算:系统时钟为6MHz,机器周期为2,当采用工作方式1时,最大的定时时间为:,则每隔1s一个定时器不能直接实现,即用定时器T0产生周期为100ms=0.1s的定时,用一个寄存器R2对100ms计数10次,则可以产生1s的定时。

T0的定时为100ms时,初值:


十六进制数为3CB0H

(2)编程实现:上电时, 8个发光二极管全亮;按下K1时,发光二极管向左(向下)移一位;按下K2时,发光二极管向右(向上)移一位。

① 电路图:

 

② 代码:

#include <reg51.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

uint i;

sbit P1_0=P1^0;   sbit P1_1=P1^1;   //定义并口P1的第0、1位

void Time_Init() //定时器装入初值 T0定时时间为100ms,T1定时时间为50ms

{

TMOD=0x11;  

TH0=0x3c; TL0=0xb0;

TR0=0;//初始化后并不启动定时器T0,待命

TH1=0x9e;  TL1=0x58;

TR1=0;//初始化后并不启动定时器T1,待命

}

void main()

{

Time_Init(); //初始化定时器  

i=0;

P0=0x0;  //上电时, 8个发光二极管全亮

while(1)

{

if(P1_0==0)  //当P1.0有效时,及开关K1按下

{  EA=1;    TR1=0;//关闭定时器1

TR0=1;   ET0=1;//允许中断0,打开定时器0

P0=0x7f;   // 给灯赋初值,第8个灯亮

}

if(P1_1==0)  //当P1.1有效时,及开关K2按下

{  

EA=1;   

TR0=0;  //关闭定时器0

TR1=1;  ET1=1;  //允许中断1,打开定时器1

P0=0xfe;     // 给灯赋初值,第1个灯亮

}}}

void time0_int(void) interrupt 1   //中断服务程序1

{

TH0=0x3c;   TL0=0xb0;   //每次定时都需要重新赋初值

i++;       //计数加1

if(i==10)

{

i=0;

P0= _cror_(P0,1); //循环右移(向上)1位,点亮下一个灯

}}

void time1_int(void) interrupt 3

{

TH1=0x9e;TL1=0x58; //每次定时都需要重新赋初值

i++;

if(i==20)

{

i=0;

P0= _crol_(P0,1); //循环左移(向下)1位,点亮下一个灯

}}

③ 分析:

Ø 该题中最上面的灯为第一个灯,

K1---P0=0x7f---向上移

K2---P0=0xfe---向下移

Ø   该题才用的两个定时器T0、T1

T0的初值计算:

 

十六进制数为3CB0H   计数10次

T0的初值计算:

 

十六进制数为9E58H   计数10次

 

四.部分知识点及遇到的问题:

(1) 定时/计数器T0工作方式:

Ø 方式0  M1 M0=00  13 位定时/计数器

Ø 方式1  M1 M0=01  16 位定时/计数器(每次定时均需重新赋值,TF0=0

Ø 方式2  M1 M0=10   8位自动充值定时/计数器

Ø 方式3  M1 M0=11   两个9位定时/计数器

(2) 用了T1之后,T0不可以执行:定时器T1比定时器T0优先级高

(3) 开关与灯在该仿真电路中均是低电平有效

(4) 中断服务程序的格式:void 函数名(voidinterrupt  寄存器组(1、2、3、4)

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_39569242/article/details/80138820