聪明文档网

聪明文档网

最新最全的文档下载
当前位置: 首页> C51单片机定时器及数码管控制实验报告

C51单片机定时器及数码管控制实验报告

时间:2020-03-15 15:52:36    下载该word文档

昆明理工大学信息工程与自动化学院学生实验报告

201 201学年 1 学期

课程名称:单片机技术

开课实验室: 年 月

一、 实验目的

1. 掌握定时器 T0、T1 的方式选择和编程方法,了解中断服务程序的设计方法, 学会实时程序的调试技巧。

2. 掌握 LED 数码管动态显示程序设计方法。

二、 实验原理

1.89C51 单片机有五个中断源(89C52 有六个),分别是外部中断请求 0、外部中 断请求 1、定时器/计数器 0 溢出中断请求、定时器/计数器 0 溢出中断请求及串 行口中断请求。每个中断源都对应一个中断请求位,它们设置在特殊功能寄存器 TCON 和 SCON 中。当中断源请求中断时,相应标志分别由 TCON 和 SCON 的相应位 来锁寄。五个中断源有二个中断优先级,每个中断源可以编程为高优先级或低优 先级中断,可以实现二级中断服务程序嵌套。在同一优先级别中,靠内部的查询 逻辑来确定响应顺序。不同的中断源有不同的中断矢量地址。

中断的控制用四个特殊功能寄存器 IE、IP、TCON (用六位)和 SCON(用二位), 分别用于控制中断的类型、中断的开/关和各种中断源的优先级别。 中断程序由中断控制程序(主程序)和中断服务程序两部分组成:

1)中断控制程序用于实现对中断的控制;

2)中断服务程序用于完成中断源所要求的中断处理的各种操作。

C51 的中断函数必须通过 interrupt m 进行修饰。在 C51 程序设计中,当函数定 义时用了 interrupt m 修饰符,系统编译时把对应函数转化为中断函数,自动加 上程序头段和尾段,并按 MCS-51 系统中断的处理方式自动把它安排在程序存储 器中的相应位置。

在该修饰符中,m 的取值为 0~31,对应的中断情况如下:

0——外部中断 0

1——定时/计数器 T0

2——外部中断 1

3——定时/计数器 T1

4——串行口中断

5——定时/计数器 T2

其它值预留。

89C51 单片机内设置了两个可编程的 16 位定时器 T0 和 T1,通过编程,可以 设定为定时器和外部计数方式。T1 还可以作为其串行口的波特率发生器。

2. 定时器 T0 由特殊功能寄存器 TL0 和 TH0 构成,定时器 T1 由 TH1 和 TL1 构成, 特殊功能寄存器 TMOD 控制定时器的工作方式,TCON 控制其运行。定时器的中断 由中断允许寄存器 IE,中断优先权寄存器 IP 中的相应位进行控制。定时器 T0 的中断入口地址为 000BH,T1 的中断入口地址为 001BH。

定时器的编程包括:

1) 置工作方式。

2) 置计数初值。

3) 中断设置。

4) 启动定时器。

定时器/计数器由四种工作方式,所用的计数位数不同,因此,定时计数常

数也就不同。

3.单片机的拉电流比较小(100~200uA),灌电流比较大(最大是 25mA,一般不 能超过 10mA),不能直接驱动数码管,需要扩流电路。可以用三级管来驱动,但 是 51 单片机只有 32 个 I/O 口,可能需要外接多种器件, I/O 口是不够用的。 故可选用 74HC573 锁存器来解决这个问题,开发板上数码管的硬件设计电路图, 如图 1 所示。

TX-1C 实验开发板用两个 74HC573 锁存器(输出电流较大,接口简单),通 过 P0 口控制六个数码管的段选及位选,其中 P2.6 控制锁存器 U1(DULA),P2.7 控制锁存器 U2(WELA)。单片机控制锁存器的锁存端,进而控制锁存器的输出, 这种分时控制的方法可方便地控制任意数码管显示任意数字。

图 1 LED 数码管电路原理图

三、 实验内容

利用动态扫描和定时器 1 在数码管上显示出从 765432 开始以 1/10 秒的速 度往下递减直至 765398 并保持显示此数,与此同时利用定时器 0 以 500MS 速度 进行流水灯从上至下移动,当数码管上数减到停止时,实验板上流水灯也停止 然后全部开始闪烁,3 秒后(用 T0 定时)流水灯全部关闭、数码管上显示出 “HELLO”。到此保持住。

计算初值公式

定时模式 1 th0=(216-定时时间) / 256 tl0=(216-定时时间) % 256

四、 实验步骤

1、 按实验要求在 KeilC 中创建项目,编辑、编译程序。

2、 将编译生成的目标码文件(后缀为.Hex)下载到实验板电路中。

3、 在实验板中运行程序,观察实验运行结果并记录。

五、 实验结果

开始时数码管的数字是765432,随后是765429,流水灯显示的是第一个灯,实验结果如下图所示:

当数码管显示765406时,流水灯显示是第六个灯,实现现象如下图所示:

当数码管显示765398时,流水灯显示的是第七个灯,由于LED灯变化快,难以捕捉到此时刻,以下图片是随后LED闪烁,数码管保持765398的现象:

最后流水灯全部关闭,数码管显示HELLO字样的现象:

六、 心得体会

通过这次实验,巩固了流水灯的操作,在此之上,加深了八段数码管的动态显示的理解,对定时器中断的理解和运用,虽然在实验的的过程中遇到了各种各样的问题,但是在老师和同学们的帮助下,我失算顺利的完成了这次实验,为后续的学习打下了坚实的基础

七、 思考

1.若用定时器 1 方式 2,程序如何修?

答:对定时器/计数器的工作方式进行修改,即:TMOD = 0x21;//00100001

2.若显示从“99”开始递减,程序如何修改?

答:只需选择第一个和第二个数码管即可,当递减到0时停止,或者继改回数字99,程序的其他部分基本不变。

八、 源代码

#include

#include

#define uchar unsigned char

#define uint unsigned int

sbit led1 = P1^0;

sbit dula = P2^6;

sbit wela = P2^7;

uchar code table[]={ //建一张table数组,元素是0~F字样

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

uchar code Hello[]={ //建一张HELLO数组,元素是H,E,L,L,O字样

0x76,0x79,0x38,0x38,0x3f};

void init();//main()函数初始化的函数的声名

void delayms(uint); //延时函数声名

void display(uchar,uchar,uchar);//数码管显示函数声名

void disHello(); //HELLO显示函数声名

uchar num1,num2,bai,shi,ge; //定义全局变量

int count,temp;

void main()

{

init();

while(1)

{

if(num1==10)//定时器每次计时50ms,当计满500ms时,LED灯流动

{

num1=0;

P1 = _crol_(P1,1); //循环左移

}

if(num2==2)//当计满0.1s时,数码管的值减1

{

num2 = 0;

count--;

if(count==398)//当数码管减到765398时,保持该数,8LED灯闪//

{

TR1 = 0;

TR0 = 0;

bai = count/100;//获得398的个、十、百位

shi = count/10%10;

ge = count%10;

display(bai,shi,ge); //显示数码管的六位数

P1 = 0x00; //8LED闪烁的初始状态

num1 = 0; //重新启动定时器T0时,num1重新初始化为0

TR0 = 1;

while(1)

{

if(num1%10==0) //8LED每隔500ms闪烁

P1 = ~P1; //LED灯取反

if(num1 == 60) //当计满3s时,关闭LED灯,在数码管上显//HELLO

{

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

P1 = 0xff; //关闭LED

disHello(); //显示HELLO

}

else

display(bai,shi,ge); //当没计满3s时,继续显示之前的6位数

}

}

bai = count/100;

shi = count/10%10;

ge = count%10;

}

display(bai,shi,ge);

}

}

void init() //main()函数的初始化

{

TMOD = 0x11; //定时器T0,T1的工作方式都是1

TH0 = (65536-45872)/256; //T0计数寄存器的初始化

TL0 = (65536-45872)%256;

TH1 = (65536-45872)/256;//T1计数寄存器的初始化

TL1 = (65536-45872)%256;

P1 = 0xfe; //LED的初始化

count = 432; //计数器的初始化,因为只有后三位变化

EA = 1; //打开总中断

ET0 = 1; //打开计时器T0

TR0 = 1; //打开计时器T1

ET1 = 1; //开启计时器T0

TR1 = 1; //开启计时器T1

}

void disHello()//HELLO显示程序

{

wela = 1;

P0 = 0xfe;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = Hello[0];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xfd;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = Hello[1];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xfb;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = Hello[2];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xf7;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = Hello[3];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xef;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = Hello[4];

dula = 0;

delayms(5);

}

void display(uchar bai,uchar shi,uchar ge) //数码管显示程序

{

wela = 1;

P0 = 0xfe;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = table[7];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xfd;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = table[6];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xfb;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = table[5];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xf7;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = table[bai];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xef;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = table[shi];

dula = 0;

delayms(5);

wela = 1;

P0 = 0xdf;

wela = 0;

P0 = 0xff;

dula = 1;

P0 = table[ge];

dula = 0;

delayms(5);

}

void delayms(uint xms)

{

uint i,j;

for(i=0;i

for(j=0;j<110;j++);

}

void T0_time() interrupt 1 //定时器T0程序

{

TH0 = (65536-45872)/256;

TL0 = (65536-45872)%256;

num1++;

}

void T1_time() interrupt 3 //定时器T1程序

{

TH1 = (65536-45872)/256;

TL1 = (65536-45872)%256;

num2++;

}

  • 29.8

    ¥45 每天只需1.0元
    1个月 推荐
  • 9.9

    ¥15
    1天
  • 59.8

    ¥90
    3个月

选择支付方式

  • 微信付款
郑重提醒:支付后,系统自动为您完成注册

请使用微信扫码支付(元)

订单号:
支付后,系统自动为您完成注册
遇到问题请联系 在线客服

常用手机号:
用于找回密码
图片验证码:
看不清?点击更换
短信验证码:
新密码:
 
绑定后可用手机号登录
请不要关闭本页面,支付完成后请点击【支付完成】按钮
遇到问题请联系 在线客服