STC89c52定时器的使用以及相关案例

定时器

使用 STC89c52 来示例

简介

C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器或者计数器使用。
确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。
标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2 。

术语解释

  • 定时器和计数器,电路一样 。
  • 当使用定时器时,靠内部震荡电路数数。
  • 当使用计数器时,数外面的信号,读取针脚的数据。

前置知识

  • 什么是晶振 ?
  • 什么是时钟周期 ?
  • 什么是机器周期 ?

晶振

晶振 ( 晶体震荡器 ) ,又称数字电路的“心脏”,是各种电子产品里面必不可少的频率元器件。也就是 1 秒震荡多少次,也就是 “时钟频率”,使用 fosc 表示 。STC89c52 为 11.0592 MHz。

时钟周期

时钟周期也称为振荡周期,定义为时钟频率的倒数(T时 = 1 / fosc S)。时钟周期是计算机中最基本的、最小的时间单位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。更小的时钟周期就意味着更高的工作频率。

机器周期

机器周期也称为 CPU周期 。在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶
段(如取指、译码、执行等),每一阶段完成一个基本操作。完成一个基本操作所需要的时间称为
机器周期。一般情况下,一个机器周期由若干个时钟周期组成。 具体由多少个时钟周期组成需要看其对应的手册。

思考?如何求得一个机器周期的时间?

STC89c52 的一个机器周期 为 12个时钟周期。

  1. 获取对应的时钟频率
  2. 求出时钟周期
  3. 根据时钟周期求得机器周期

时钟频率为 : 11.0592 MHz = 1105926 HZ
时钟周期为 :1 / 11059200 S
机器周期为 : 12 / 110592600 S = 12 000 000
/ 11059200 us = 1.085 us

编写一个定时器

STC89c52 手册定时器部分如下(使用内部震荡电路实现)
在这里插入图片描述

在这里插入图片描述

我们可以得到如下信息:
TCON中

  1. 定时器有 2 个 (定时器0 和定时器 1,我们看定时器 0)
  2. TF0 为中断溢出标识 。由硬件置 1 ,可以由硬件或软件置 0 。
  3. TR0 为运行控制位。由软件置位和清零。TR0 为 1 时才允许 T0 计数 。
  4. IE0 和 IT0 与中断相关(这里暂时不用)

TOMD中
1. TOMD.3 定时器0,需要TR0 = 1 才开启 。
2. C / T 定时器,计数器转换 。
3. M1 已经 M0 为配置定时器模式,手册已经为我们举例。我这里使用0 1 模式全部使用 , 也就是16位,最大数为 65536。

代码编写

了解完上面的基本信息开始写代码
需求:写一个定时器,每1秒闪烁一次led 灯。

#include "reg52.h"
sbit led = P3^7 ; 
/*
	分析 
		16位最大能表示的时间为 
			计数 * 机器周期 = 65535 * 1.085us = 71105.475 us = 71.105475 ms 
			1S = 1000 ms 
			不能直接计数那么我们使用 10ms 结合数据统计来获取 1S
		1. 10ms的定时器  	
		2. 统计 100 次 决定led 开,关。

		如何去定义10ms 定时器,将需要计数次数设置为x
			x * 1.085us = 10000 us
			x = 9216 (约等于)
			65536 - 9216 = 56320 (这里就得出TL0和TH0计数器的初始值)
*/
void initTimer()
{
	 // 配置定时器模式
	 TMOD &= 0xF0 ; 
	 TMOD |= 0x01 ;
	//初始值
	 TL0 =0x00;
	 TH0 =0xDB;
	 // 运行控制位
	 TR0 = 1 ; 
	 // 溢出标志位
	 TF0 = 0 ;
}

void main()
{
	int number = 0 ; 
	initTimer();
	
	while(1){
		
		// 100次 10ms 就是 1 S
		if(number == 100){
			number = 0;
			led = !led;
		}
		
		// 溢出一次代表 10ms
		if( TF0 == 1 ){
			// 手动清零
			TF0 = 0 ; 
		    // 重置
			TL0 =0x00;
	        TH0 =0xDB;
			// 统计 
			number++;
		}
	}
}

其它使用案例

SG90 舵机使用

在这里插入图片描述
舵机的控制信号为周期是20ms的脉宽调制(PWM) 信号,其中脉冲宽度从0.5ms-2.5ms,相对应舵盘的位置为0-180度,呈线性变化。常见的舵机有 90°,180°,360°。我们这里使用 180°。

PWM周期

需要通过信号线往舵机输入PWM波,才能驱动舵机转动

PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右

以下是一个周期内高电平所占的时间:

0.5ms————0度; 2.5% 对应函数中占空比为250
1.0ms————45度; 5.0% 对应函数中占空比为500
1.5ms————90度; 7.5% 对应函数中占空比为750
2.0ms————135度; 10.0% 对应函数中占空比为1000
2.5ms————180度; 12.5% 对应函数中占空比为1250

代码实现

需求让舵机 从0°-90°循环转动

#include "reg52.h"

sbit sg90 = P1^1 ;

// 计数
int cnt= 0 ;	
// 旋转角度
int number = 1 ;

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

/*
	初始化
*/
void Timer0Init(void)		//500微秒@11.0592MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x33;		//设置定时初值
	TH0 = 0xFE;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1 ; // 开启中断
	ET0 = 1 ; // 开启中断
}

void main()
{		
	Delay1000ms();
	Timer0Init();
	while(1){
		// 旋转0°
		number = 1 ;
		Delay1000ms();
		Delay1000ms();
		// 旋转90°
		number = 3 ;
		Delay1000ms();
		Delay1000ms();
	}
}

/*
	定时中断处理
*/
void PWM() interrupt 1
{
	TF0 = 0 ;
	TL0 = 0x33;		//设置定时初值
	TH0 = 0xFE;		//设置定时初值
	if( cnt < number ){
		sg90 = 1 ;
	}
	if( cnt > number){
		sg90 = 0 ;
	}
	if( cnt >= 40 ){
		cnt = 0 ;
		sg90 = 1;
	}
	cnt++;
}

HC-SR04超声波模块

在这里插入图片描述

接口定义

  • vcc 5v
  • Trig 控制端
  • Echo 接收端
  • Gnd 接地

手册使用说明
在这里插入图片描述

超声波时序图
在这里插入图片描述

计算原理

让它发送波:给Trig端口至少10us的高电平
开始发送波:Echo信号由低电平跳转到高电平
接收返回波:Echo信号由高电平跳转回低电平
计算时间 : Echo引脚维持高电平的时间!
开始发送波,启动定时器,接收到返回波,停止计时器
计算距离 :测试距离=(高电平时间*声速(340m/s))/2

代码实现

当见检测到 10cm 内有遮挡点亮 led

#include "reg52.h" 

sbit trig = P1^5;
sbit echo = P1^6 ;
sbit led = P3^7 ; 

/*
	1. 给 trig 口至少 10us 高电平
	2. 等待 echo 高电平 ,并同时开启定时器 
	3. 等待 echo 低电平 ,并同时关闭定时器 
	4. 计算数据
	5. 距离 = time * 340m / s / 2 
*/

void Delay10us()		//@11.0592MHz
{
	unsigned char i;

	i = 2;
	while (--i);
}


void initHC()
{
	trig = 0 ;
	trig = 1 ;
	Delay10us();
	trig = 0 ;
}

void Timer0Init(void)		//1000微秒@11.0592MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x00;		//设置定时初值
}


void main()
{
	double dis = 0 ;
	double time = 0 ;
	
	Timer0Init();
	while(1){
		initHC();
		 // 监听echo 升为高电平
		while(echo == 0 ); 
		//定时器0开始计时
		TR0 = 1;		
		// 监听echo 升为低电平 
		while(echo == 1 );
		// 关闭定时器
		TR0 = 0 ; 
		// 计算距离
		time = (TH0 * 256 + TL0 ) * 1.085 ; // us
		dis = time * 0.017 ; 
		
		if(dis < 10){
				led = 0;
		}else{
				led = 1;
		}
		TL0 = 0x00;		//设置定时初值
		TH0 = 0x00;		//设置定时初值
	}
}

好啦,一些基本使用就到这里啦。希望对你有帮助。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STC89C52是一款51单片机系列的微控制器,具有高性能、高稳定性、低功耗等特点,广泛应用于各种嵌入式系统。 以下是STC89C52使用手册的简要介绍: 1.硬件结构 STC89C52包括CPU、存储器、I/O端口、定时器、串口、中断控制器等模块。其中,CPU采用MCS-51架构,主频为11.0592MHz;存储器包括8KB的Flash程序存储器和256字节的RAM数据存储器;I/O端口共有32个,可设置为输入或输出;定时器包括3个16位定时器和1个8位定时器;串口支持异步串口通信;中断控制器可处理8个外部中断和3个定时器中断。 2.编程环境 STC89C52可使用Keil C51或者SDCC等编程软件进行开发。具体的开发流程包括编写程序、编译、下载、烧录等步骤。 3.常用指令 STC89C52支持多种指令,包括数据传送指令、算术运算指令、逻辑运算指令、位操作指令、跳转指令、中断指令等。其中,常用的指令包括MOV、ADD、SUB、INC、DEC、JMP、CALL、RET等。 4.外设控制 STC89C52可通过I/O端口、定时器、串口等外设控制各种外部设备。例如,通过I/O端口可以控制LED灯、蜂鸣器等;通过定时器可以实现定时、计数等功能;通过串口可以进行数据通信。 5.应用案例 STC89C52广泛应用于各种嵌入式系统,例如智能家居、工业控制、仪器仪表、车载电子等领域。具体的应用案例包括温度控制、电机控制、数据采集、LCD显示等。 以上是STC89C52使用手册的简要介绍,具体的使用方法和应用案例需要根据实际需求进行学习和研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老痞啥都不会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值