8051单片机,定时器产生方波,计数
下载源码和proteus原理图资源:https://download.csdn.net/download/u011146203/88493835?spm=1001.2014.3001.5503
要求:
①以例9-4仿真实现,以某种物理现象观察方波。(示波器,光,声…)
②用C语言改写程序,重新仿真。
③改变占空比,按键可调。
④做farmer,对🐂计数。(怎么模拟牛?–按键模拟0
加显示器)
(1)
用9-4的例子产生方波,并观察

代码如下:
MOV TMOD,#01
HERE: MOV TL0,#0F2H
MOV TH0,#0FFH
CPL P1.5
ACALL HERE
;
DELAY:
SETB TR0
AGAIN:
JNB TF0,AGAIN
CLR TR0
CLR TF0
RET
其中,需要用到定时器/计数器,此时也需要去配置几个特定的寄存器:
关于定时器有几点概念如下:
8051有两个定时器:定时器0和定时器1。
定时器0的16位寄存器分为高字节访问和低字节访问。低字节寄存器称为TLO(定时器0的低字节),而高字节寄存器称为THO(定时器0的高字节)。
定时器1同上:
TMOD(定时模式)寄存器
相关参数如下:
STC89C52的T0和T1均有四种工作模式:
模式0:13位定时器/计数器
模式1:16位定时器/计数器(常用)
模式2:8位自动重装模式
模式3:两个8位计数器;
其中最常用的工作模式1框图如下:
C/T(时钟/定时器)
TMOD寄存器中的此位用于判断定时器是作为延时发生器还是作为事件计数器使用。若C/T=0,则用作延时发生器。延时的时钟源是8051的晶振频率。
配置情况:
TMOD:0000 0001 ;
选用定时器0,选用模式1,同时GATE=0,C/T=0。此时运行的模式框图如下:
简单进行解释:
晶振每次产生十二个周期,会给TH以及TL中进位,当TH,TL为FFFF时,TF溢出由0变1.
通过此过程不断进行反转,即可获得一个占空比为50%的脉冲。
2.用C语言改写程序,重新仿真
用stc产生通过12M的晶振产生1毫秒的延时
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
程序如下:
#include <REGX52.H>
void Timer0Init(void);
sbit mybit = P1^5;
void main(void)
{
while(1)
{
mybit = ~mybit;
Timer0Init();
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
TMOD = 0x01; //设置定时器模式
TL0 = 0xFD; //设置定时初始值
TH0 = 0x4B; //设置定时初始值
TR0 = 1;
while(TF0 == 0); //当溢出时将其加入TF可以使TF=1时跳出死循环
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
改变占空比,按键可调
改变占空比可以通过按键实现,我们思路会同上一个模式转变走马灯的大思路,通过设定两个执行的模式,让按键按下的时候识别到,进行两个模式之间的切换。
#include <REGX52.H>
void Timer0Init(void);
void Delay(unsigned int xms);
void mode0();
void mode1();
void display( mode);
sbit mybit = P1^5;
sbit KEY_MODE = P2^1;
sbit KEY_UP = P2^4;
unsigned char mode=0;
unsigned char key_value;
unsigned char key_scan()
{
P2=0xff; //1111 1111
key_value=0;
if(KEY_MODE == 0){
Delay(20);
while(!KEY_MODE);
Delay(20);
key_value=1;
}
/* else if(KEY_UP == 0)
{
Delay(20);
while(!KEY_UP);
Delay(20);
key_value=2;
}
*/
return key_value;
}
void main(void)
{
while (1)
{
key_value=key_scan();
switch(key_value)
{
case 0:
display(mode);
break;
case 1:
mode++;
display(mode);
if(mode>1)
{
mode=0;
}
display(mode);
break;
/*case 2:
mode++;
display(mode);
if(mode>2)
{
mode=0;
}
display(mode);
break;
*/
default: break;
}
}
}
void Timer0Init(void)
{
TMOD = 0x01;
TL0 = 0xFD;
TH0 = 0x4B;
TR0 = 1;
while(TF0 == 0);
TF0 = 0;
TR0 = 0;
}
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void mode0()
{
mybit = ~mybit;
Timer0Init();
}
void mode1()
{
mybit = 1;
Timer0Init();
mybit = 0;
Timer0Init();
Timer0Init();
Timer0Init();
}
void display( mode)
{
switch(mode)
{
case 0:mode0();break;
case 1:mode1();break;
default:mode0();break;
}
}
做farmer,对🐂计数。(怎么模拟牛?–按键模拟0加显示器)
代码如下:
#include <REGX52.H>
unsigned char NixieTable[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};
unsigned char number=0;
void main(void)
{
P3_5 = 1;
TMOD = 0x60;
TH1 = 0;
while(1){
do
{
TR1 = 1;
number = TL1;
P0 = NixieTable[number];
}
while(TF1 == 0);
TR1 = 0;
TF1 = 0;
}
}
void Timer1Init(void)
{
T1 = 1;
TMOD = 0x60;
TH1 = 0;
while(1)
{
do{
TR1 = 1;
P0 = TL1;
}
while(TF1 == 0);
TF1 = 0;
TR1 = 0;
}
}
原理图: