51单片机中定时器、中断、PWM实例分析。

51单片机中定时器、中断、PWM实例分析。,第1张

1、配置一个1s的定时器

#include "reg52.h"

sbit led=P3^6;
int cnd=0;

void main()
{
	TMOD=0x01;//配置定时器0工作在16位计时模式	
	led=1;
	TL0=0x0000;
	TH0=0xDC00;//设置10微妙一个计数周期
	TF0=0;//初始化爆表位为0
	TR0=1;//开始计时
	while(1)
	{
		if(TF0==1)
		{
			cnd++;//爆表一次次数加一
			TF0=0;
			TL0=0x00;
			TH0=0xDC;
				if(cnd==100)//爆表100次是1秒
				{
					cnd=0;
					led=!led;
				}
		}
	}
}

2、下面我们再来一个中断小实验(有点多线程的意思),我们设置的是对定时器的中断。


#include 
#include //延时函数头文件

sbit led1=P3^6;
sbit led2=P3^7;
int cnd=0;

void Delay777ms()		//@11.0592MHz
						//注意这里延时助手,指令集要选Y1
{
	unsigned char i, j, k;

	i = 6;
	j = 114;
	k = 30;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}




void Time0Init()
{
	TMOD=0x01;//配置定时器0工作在16位计时模式	
	led1=1;
	TL0=0x0000;
	TH0=0xDC00;//设置10微妙一个计数周期,2的16次方是65536,数一次是1.085us,10ms需要9216次,换算下来从65536-9216开始计时
	TF0=0;//初始化爆表位为0
	TR0=1;//开始计时
	ET0=1;//打开定时器0中断
	EA=1;//打开总中断

}
void main()
{
	Time0Init();//给定时器初始化,计数爆表时跳到爆表函数这执行
	while(1)
	{
		led2=1;
		Delay777ms();	//@11.0592MHz
		led2=0;
		Delay777ms();	
	}
	
}

void Time0Handler(void)  interrupt 1//爆表时由机器硬件制1(TF0=1)同时请求该位中断,即系统自动跳到该函数;计时溢出则中断
																			//按照我们的使用习惯,中断函数一般放在此处,main后面
{
	cnd++;//爆表一次次数加一,爆表一次是10ms(计算而来),
	TF0=0;//重新赋值
	TL0=0x00;
	TH0=0xDC;
		if(cnd==100)//爆表100次是1秒
		{
			cnd=0;
			led1=!led1;
		}
}

这里的实验现象是:led1每间隔一秒闪烁一次,led2每隔666ms闪烁一次,二者互不影响,有点双线程的意思。



3、用PWM来控制舵机。


#include 
#include //延时函数头文件

sbit SG90=P1^0;
int cnd=0;
int jd;


void Delay2000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Time0Init()//用于初始化单片机
{
	TMOD=0x01;//配置定时器0工作在16位计时模式	
	TL0 = 0x33;		//设置定时初值
	TH0 = 0xFE;		//设置定时初值,设置10微妙一个计数周期,2的16次方是65536,数一次是1.085us,10ms需要9216次,换算下来从65536-9216开始计时
	TF0=0;//初始化爆表位为0
	TR0=1;//开始计时
	ET0=1;//打开定时器0中断
	EA=1;//打开总中断

}
void main()
{
	Time0Init();//给定时器初始化,计数爆表时跳到爆表函数这执行
	SG90=1;//舵机初始电平给高位
	while(1)
	{
		jd=4;
		cnd=0;
		Delay2000ms();//每次中断条件不满足均会回到此处执行
		jd=1;
		cnd=0;
		Delay2000ms();
		
	}
}

void Time0Handler(void)  interrupt 1//爆表时由机器硬件制1(TF0=1)同时请求该位中断,即系统自动跳到该函数
																			//按照我们的使用习惯,中断函数一般放在此处,main后面,0.5ms中断一次
{
	cnd++;//爆表一次次数加一,爆表一次是0.5ms(计算而来),
	TF0=0;//重新赋值
	TL0=0x33;
	TH0=0xFE;
		if(cnd<jd)//1—这是画了一个占空0.5ms的方波
		{
			SG90=1;
		}
		else 
		{
			SG90=0;
		}	
		if(cnd==40)
		{
			cnd=0;
			SG90=1;
			TF0=0;
			TL0=0x33;
			TH0=0xFE;
		}
}

这里我们分析下程序:在51环境下,只能通过PWM控制舵机转角和停留时间,通过长置1延时置0是改变不了角度的。


这里我们的jd只是控制占空比。


延时两秒是控制舵机到顶峰停留时间。



一般,要控制确定时间要用计数器,定时器,时钟周期是晶振频率的倒数,一个机器周期是12个时钟周期,跳一下是时钟周期,1.085us,一个机器周期最多有65536个时钟周期,也就是71ms左右。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/569487.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存