【单片机】脉冲计数(定时/计数器实验)

一、操作目的

  • 熟悉单片机内部定时/计数器功能,掌握初始化编程方法。

二、操作内容

  • 把定时器0外部输入的脉冲进行计数,并送显示器显示。

三、程序框图

【单片机】脉冲计数(定时/计数器实验)_初始化

四、程序接线图

【单片机】脉冲计数(定时/计数器实验)_初始化_02

五、程序清单

ORG 0000H
LJMP SE15
ORG 06E0H
SE15:
MOV SP,#53H
MOV P2,#0FFH
MOV A,#81H
MOV DPTR,#0FF23H
MOVX @DPTR,A
MOV TMOD,#05H
MOV TH0,#00H ;定时计数器初始化
MOV TL0,#00H ;开计数器
SETB TR0
LO29:
MOV R2,TH0
MOV R3,TL0 ;取出TH0,TL0内容
LCALL ZOY0
MOV R0,#79H ;二转十进制
MOV A,R6
LCALL PTDS
MOV A,R5
LCALL PTDS
MOV A,R4
LCALL PTDS ;送显示缓冲区
LCALL SSEE ;显示
SJMP LO29 ;循环计数
ZOY0:
CLR A
MOV R4,A
MOV R5,A
MOV R6,A ;0送R4 R5 R6
MOV R7,#10H
LO30:
CLR C ;R2 R3左移,移出的
MOV A,R3 ;最高位送CY
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
MOV A,R6
ADDC A,R6 ;(R4 R5 R6)*2送R4 R5 R6
DA A ;十进制调整
MOV R6,A
MOV A,R5
ADDC A,R5
DA A
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
DJNZ R7,LO30 ;循环16次
RET
PTDS:
MOV R1,A ;拆送显示缓冲区
ACALL PTDS1
MOV A,R1
SWAP A
PTDS1:
ANL A,#0FH
MOV @R0,A
INC R0
RET
SSEE:
SETB RS1 ;换工作区
MOV R5,#05H
SSE2:
MOV 30H,#20H
MOV 31H,#7EH
MOV R7,#06H
SSE1:
MOV R1,#20H
MOV A,30H
CPL A
MOVX @R1,A ;字位送入
MOV R0,31H
MOV A,@R0
MOV DPTR,#DDFF
MOVC A,@A+DPTR ;取字形代码
MOV R1,#21H
MOVX @R1,A ;字形送入
MOV A,30H ;右移
RR A
MOV 30H,A
DEC 31H
MOV A,#0FFH

六、代码详解

#include <reg51.h>
#include <absacc.h>

#define uchar unsigned char

#define com8255 XBYTE[0xff23]//宏定义口地址
#define pa8255 XBYTE[0xff20]
#define pb8255 XBYTE[0xff21]
//unsigned char code mon51[3] _at_ 0x3b;//保留0X3B开始三个程序空间作全速中断用
uchar code table[10] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90 };
uchar code wei[] = { 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };

unsigned int number = 0;
unsigned int temp = 0;

void delay(unsigned int i)
{
unsigned int j, k;
for (k = 0; k < i; k++)
for (j = 0; j < 100; j++)
;
}

void main(void)
{
uchar m = 0;
com8255 = 0x80; //控制口赋值
pa8255 = 0x00; //PA初始化
pb8255 = 0x00; //PB口初始化

//设置16位,并且设置T0为计数器,T1为定时器 参考P114图7.3
TMOD = 0x15;

// 设置计数器
// 计数器置零
TH0 = 0x00;
TL0 = 0x00;

// 设置定时器T1
// 根据公式计算得出,设置时间为50ms 参考P113推导公式
TH1 = 0x3c;
TL1 = 0xb0;

//设置中断
//中断总体允许控制位
EA = 1;

//计数器T0的溢出中断允许控制位 参考P151
ET0 = 0;
//TR0是计数器T0的启动位,1代表计数器T0开始计数
TR0 = 1;

//定时器T1的溢出中断允许控制位 参考P151
ET1 = 1;
//TR1是定时器T1的启动位,1代表定时器T1开始计数
TR1 = 1;

delay(2);

//通过计数在数码管显示相应的数字
while (1)
{
pb8255 = table[(number / 1) % 10];
pa8255 = ~wei[5];

pb8255 = table[(number / 10) % 10];
pa8255 = ~wei[4];

pb8255 = table[(number / 100) % 10];
pa8255 = ~wei[3];

pb8255 = table[(number / 1000) % 10];
pa8255 = ~wei[2];

pb8255 = table[(number / 10000) % 10];
pa8255 = ~wei[1];

pb8255 = table[(number / 100000) % 10];
pa8255 = ~wei[0];
}
}

void Dealy(void) interrupt 3 using 0
{
//重置时间为50ms
TH1 = 0x3c;
TL1 = 0xb0;

//将计数器中的高8位传送到temp变量中
temp = TH0;
//将高八位转换成十进制
temp = temp * 256;
//将计数器中的低8位传送到number变量中
number = TL0;
//将低8位与高八位相加,得出现在的记的数
number = number + temp;

//将计数器清零
TH0 = 0x00;
TL0 = 0x00;

//计数器T0的溢出中断标志位,当T0从初值开始加一计数到产生溢出时,由硬件使TF0置1,直到CPU响应中断由硬件复位
TF0 = 0;
}