实验5.1 采用定时器控制从P1.0输出1000Hz音频信号。
这次实验主要是为了让我们巩固定时器和计数器的相关知识,比如TMOD,TH0,TL0,TH1,TL1,IE,TR0,TR1
定时/计数器有四种工作方式
1、方式0:
TMOD中M1M0为00的时候即为方式0,方式0是13位定时/计数方式,THx 提供高八位,TLx 提供低五位,TLx 的高三位是没有用的,最大计数是213 次方(8192个脉冲)晶振是12MHz时,最多定时8.192ms,6MHz时翻倍。
当C/T¯¯¯=0 时,工作于定时方式,以振荡源的12分频信号作为计数脉冲,12分频信号也就是一个机器周期。
当C/T¯¯¯=1 时,工作于计数方式,对外部脉冲输入端T0 或T1 输入的脉冲计数。
此方式需要手动重装初值。
2、方式1:
当TMOD中M1M0=01时,定时/计数器工作在方式1。
方式1与方式0基本相同,唯一的却别在于寄存器的位数是16位的,有THx 和TLx 各提供8位计数器初值,最大计数数值是216 (65536个脉冲),是几种方式之中计数值最大的一种。
3、方式2:
当TMOD中M1M0=10时,定时/计数器工作再方式2。
方式2是8位可自动重装的定时/计数方式,最大计数值为28 (256个脉冲)
在这种方式下,THx 和TLx 两个寄存器中,THx 专用于8位计数初值并保持不变,TLx 进行8位加1计数。当TLx 计数溢出时,除产生溢出中断请求外,还自动将THx 中不变的初值重装载到TLx 中。
4、方式3:
方式3只适用于定时/计数器0(T0)。当定时/计数器工作在方式3时,THx 和TLx 成为两个独立的计数器。这是TLx 可作为定时/计数器,占用T0在TCON和TMOD寄存器中的控制位和标志位;而THx 只能作为定时器使用,占用T1的资源TR1和TF1。在这种情况下,T1仍可用于方式0,1,2,但不能使用中断方式。
只有将T1用做串行口的波特率发生器时,T0才工作在方式3,以便早增加一个定时/计数器。
方式3 用的非常少,我没怎么用过。
这个题目要产生1000Hz的信号,所以周期是1ms,所以每500us就应该取反一次,所以定时器应该定时500us。
汇编程序:
ORG 0000H
LJMP START
ORG 000BH
JMP TIMER0
ORG 0040H
START:
MOV TMOD,#01H
MOV TH0,#0FEH
MOV TL0,#0CH
SETB P1.0
SETB EA
SETB ET0
SETB TR0
SJMP $
TIMER0:
CPL P1.0
MOV TH0,#0FEH
MOV TL0,#0CH
RETI
END
C语言程序:
#include<reg51.h> timer0()interrupt 1{ TH0=0xfe;
TL0=0x0c;
P10=~P10; //我在reg52.h中已经定义了P10,所以这里可以直接用
}
main(){
TMOD=0x01;
TH0=0xfe;
TL0=0x0c;
P10=0;
EA=1;
ET0=1;
TR0=1;
while(1){
}
}
实验5.2 采用定时器控制从P1.0和P1.1分别输出周期为2ms和50us的方波。
汇编代码:这里采用的是软件计数,也就是先定时25us取反一次,同时用R0计数,当25us取反40次之后也就是1ms,P1.1取反一次,同时R0赋值为40。当然也可以用T1计数,我后面会有这个的代码
ORG 0000H
LJMP START
ORG 000BH
JMP TIMER0
ORG 0040H
START:
MOV TMOD,#02H
MOV TH0,#0E7H
MOV TL0,#0E7H
MOV R0,#40
SETB P1.0
SETB P1.1
SETB EA
SETB ET0
SETB TR0
SJMP $
TIMER0:
CPL P1.0
DJNZ R0,BACK
CPL P1.1
MOV R0,#40
BACK:
RETI
END
采用两个定时/计数器,一个计时器计时25us,一个计数器计数20次,因为计数器是每个下降沿计数一次,然后一个周期才有一个下降沿,所以只用计数20次。
ORG 0000H
LJMP START
ORG 000BH
JMP TIMER0
ORG 001BH
JMP TIMER1
ORG 0040H
START:
MOV TMOD,#62H ;T1T0都用上
MOV TH0,#0E7H
MOV TL0,#0E7H
MOV TH1,#0ECH
MOV TL1,#0ECH
SETB P1.0
SETB P1.1
SETB EA
SETB ET0
SETB ET1
SETB TR0
SETB TR1
SJMP $
TIMER0:
CPL P1.0
RETI
TIMER1:
CPL P1.1
RETI
END
C语言程序: 软件计数
#include<reg51.h>
uchar a=40; //我在reg51.h中定义了#define uchar unsigned char
timer0()interrupt 1{
a--;
P10=~P10;
if(a==0){
a=40;
P11=~P11;
}
}
main(){
TMOD=0x02;
TH0=0xe7;
TL0=0xe7;
P10=0;
EA=1;
ET0=1;
TR0=1;
while(1){
}
}
计数器计数
#include<reg51.h>
timer0()interrupt 1{ P10=~P10; }
timer1()interrupt 3{ P11=~P11; }
main(){ TMOD=0x62; TH0=0xe7; TL0=0xe7; TH1=0xec; TL1=0xec; P10=0; P11=1; EA=1; ET0=1; ET1=1; TR0=1; TR1=1; while(1){ }
}