视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
单片机C51的计数器
2025-09-30 22:48:38 责编:小OO
文档
单片机C51的计数器

该部分的硬件电路如图所示,U1的P0口和P2口的部份引脚构成了6位LED数码管驱动电路,数码管采用共阳型,使用PNP型三极管作为片选端的驱动,所有三极管的发射极连在一起,接到正电源端,它们的基极则分别连到P2.0…P2.5,当P2.0…P2.5中某引脚输是低电平时,三极管导通,给相应的数码管供电,该位数码管点亮哪些笔段,则取决于笔段引脚是高或低电平。图中看出,所有6位数码管的笔段连在一起,通过限流电阻后接到P0口,因此,哪些笔段亮就取决于P0口的8根线的状态。

 

编写程序时,首先根据硬件连线写出LED数码管的字形码、位驱动码,然后编写程序如下:

#include "reg51.h"

#define uchar unsigned char

#define uint unsigned int

uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB}; //位驱动码

uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF}; //字形码

uchar DispBuf[6]; //显示缓冲区

void Timer1() interrupt 3

{ uchar tmp;

uchar Count; //计数器,显示程序通过它得知现正显示哪个数码管

TH1=(65536-3000)/256;

TL1=(65536-3000)%256; //重置初值

tmp=BitTab[Count]; //取位值

P2=P2|0xfc; //P2与11111100B相或

P2=P2&tmp; //P2与取出的位值相与

tmp=DispBuf[Count];//取出待显示的数

tmp=DispTab[tmp]; //取字形码

P0=tmp;

Count++;

if(Count==6)

Count=0;

}

void main()

{ uint tmp;

P1=0xff;

P0=0xff;

TMOD=0x15; //定时器0工作于计数方式1,定时器1工作于定时方式1

TH1=(65536-3000)/256;

TL1=(65536-3000)%256; //定时时间为3000个周期

TR0=1; //计数器0开始运行

TR1=1;

EA=1;

ET1=1;

for(;;)

{ tmp=TL0|(TH0<<8); //取T0中的数值

DispBuf[5]=tmp%10;

tmp/=10;

DispBuf[4]=tmp%10;

tmp/=10;

DispBuf[3]=tmp%10;

tmp/=10;

DispBuf[2]=tmp%10;

DispBuf[1]=tmp/10;

DispBuf[0]=0;

}}

  这个程序中用到了一个新的知识点,即数组,首先作一个介绍。

  数组是C51的一种构造数据类型,数组必须由具有相同数据类型的元素构成,这些数据的类型就是数组的基本类型,如:数组中的所有元素都是整型,则该数组称为整型数组,如所有元素都是字符型,则该数组称为字符型数组。

  数组必须要先定义,后使用,这里仅介绍一维数组的定义,其方式为:

  类型说明符 数组名[整型表达式]

  定义好数组后,可以通过:数组名[整型表达式]来使用数组元素。

  在定义数组时,可以对数组进行初始化,即给其赋予初值,这可用以下的一些方法实现:

  1.在定义数组时对数组的全部元素赋予初值:

  例:int a[5]={1,2,3,4,5};

 2.只对数组的部分元素初始化;

  例:int a[5]={1,2};

  上面定义的a数组共有5个元素,但只对前两个赋初值,因此a[0]和a[1]的值是1、2,而后面3个元素的值全是0。

 3.在定义数组时对数组元素的全部元素不赋初值,则数组元素值均被初始化为0

 4.可以在定义时不指明数组元素的个数,而根据赋值部分由编译器自动确定

  例:uchar BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};则相当于定义了一个BitTab[6]这样一个数组。

 5.可以为数组指定存储空间,这个例子中,未指定空间时,将数组定义在内部RAM中,可以用code关键字将数组元素定义在ROM空间中。

  uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};

  用这两种定义分别编译,可以看出使用了code关键字后系统占用的RAM数减少了,这种方式用于编程中不需要改变内容的场合,如显示数码管的字形码等是很合适的。

  6.C语言并不对越界使用数组进行检测,例如上例中数组的长度是6,其元素应该是从BitTab[0]~BitTab[5],但是如果你在程序中写上BitTab[6],编译器并不会认为这有语法错误,也不会给出警告(其他语言如BASCI等则有严格的规定,这种情况将视为语法错误),因此,编程者必须自己小心确认这是否是你需要的结果。

  程序分析:程序中将定时器T1用作数码管显示,通过interrupt 3关键字定义函数Timer1()为定时器1中断服务程序,在这个中断服务程序中,使用

TH1=(65536-3000)/256;

TL1=(65536-3000)%256;

  来重置定时器初值,这其中3000即为定时周期,这样的写法可以直观地看到定时周期数,是常用的一种写法。其余程序段分别完成取位码以选择数码管、从显示缓冲区获得待显示数值、根据该数值取段码以点亮相应笔段等任务。其中使用了一个计数器,该计数器的值从0~5对应第1到第6位的数码管。

  主程序的第一部分是做一些初始化的操作,设置定时器工作模式、开启定时器T1、开启计数器T0、开启T1中断及总中断,随后进入主循环,主循环首先用unsigned int型变量tmp取出T0中的数值,这里使用了“tmp=TL0|(TH0<<8);”这样的形式,这相当于tmp=TH0*256+TL0,但比之于后一种形式,该方式可以得到更高的效,其后就是将tmp值不断地除10取整,这样将int型数据的各位分离并送入相应的显示 .

a下载本文

显示全文
专题