当前位置: 移动技术网 > 科技>办公>配件 > 51单片机PWM输出

51单片机PWM输出

2020年07月01日  | 移动技术网科技  | 我要评论
PWM输出学期快结束了,51单片机的学习也差不多告一段落,也快要转入新的学习阶段,寒假找个时间看看32,小白哈哈哈,下面是我学习51定时器弄出来的小东西,一个PWM的输出。还请大神指点。刚开始觉得PWM输出应该不难,很容易做的,但是后面越像越多,就感觉其实做不来不难,做精确才难,刚开始想到的用一个定时器做,也就是在中断里面计数,来个中断计数加一,判断到自己想要的值就改变电平,这样做思路简单,但...

PWM输出

学期快结束了,51单片机的学习也差不多告一段落,也快要转入新的学习阶段,寒假找个时间看看32,小白哈哈哈,下面是我学习51定时器弄出来的小东西,一个PWM的输出。还请大神指点。

刚开始觉得PWM输出应该不难,很容易做的,但是后面越像越多,就感觉其实做不来不难,做精确才难,刚开始想到的用一个定时器做,也就是在中断里面计数,来个中断计数加一,判断到自己想要的值就改变电平,这样做思路简单,但有一个坏处,就是有个0.14ms的误差无法消除(可能是我太菜,没找到解决方法),后来就想到用两个定时器做了,定时器0,用来改变周期,定时器1,用来改变占空比,当定时器0来一个中断时,PWM=1,并开启定时器1,定时器1来一个中断时,PWM=0,关闭定时器,至于为什么要关闭定时器1,是因为定时器1的初值比较小,可能在定时器0还没发生中断的时候,就发生几次中断了,所以会影响PWM输出,还有发生中断的时候,有一些时间,和运行的时候有些静态误差,所以在初值哪儿微调。
废话少说,直接上代码。
延时函数

#ifndef __DELAY_H
#define __DELAY_H
#include "reg51.h"
#define uchar unsigned char
#define uint unsigned int 
void delay_ms(uint i);

#endif

#include "delay.h"
void delay_ms(uint i)
{
	uchar n;
 	while(i--)
	for(n=0;n<120;n++)
	;

}

下面直接主函数了

#include "sys.h"				//自己写的一个头文件
#include "delay.h"

unsigned int tim0_I; //占空时间
unsigned int tim0_T;		 //周期
uchar Temp_TH0,Temp_TL0;
uchar Temp_TH1,Temp_TL1;

sbit PWM=P1^0;	//输出引脚
sbit key0=P3^2;
sbit key1=P3^3;
sbit key2=P2^0;
sbit key3=P2^1;
void INT_Init_KEY();
void key2_Init();
void key3_Init();
void TIM0_Init_PWM();	//初始化

//sbit LED=P1^0;
void main()
{
//	uchar i;

	tim0_I=600;
	tim0_T=1000;
	PWM=0;
	TIM0_Init_PWM();
	
	INT_Init_KEY();
	while(1)
	{
		key2_Init();
		key3_Init();
		delay_ms(10);	
	}
}


void TIM0_Init_PWM()		 //定时器0初始化
{
	TMOD=0x11;				//方式1:为16位定时/计数器
	TH0=(uint)(65535-tim0_T)/256;		//取低8位	//设置初始值10us
	TL0=(uint)(65535-tim0_T)%256;		 //取低8位
	TH1=(uint)(65535-tim0_I)/256;
	TL1=(uint)(65535-tim0_I)%256;
	TR1=1;
	TR0=1;
	ET1=1;		
	TR0=1;					 //打开定时器0
	ET0=1;					 //打开外部中断
	EA=1;					 //打开总中断

}

void tim0_Int_PWM()	interrupt 1 //设定周期
{
//	TR0=0;   				 //设置定时器初值期间,关闭定时器


  	TH0=(uint)(65535-tim0_T+28)/256;		 //定时器赋值
  	TL0=(uint)(65535-tim0_T+28)%256;		//加28是为了消除静态误差,还有中断反应时间,下面加30也一样
// 	TR0=1;
	PWM=1;
	TR1=1;
}
void tim1_Int_PWM()	interrupt 3 			//占空比
{
  				 
  	TH1=(uint)(65535-tim0_I+30)/256;		 //定时器赋值
  	TL1=(uint)(65535-tim0_I+30)%256;
	PWM=0;
	TR1=0;//需要把定时器1关了,这样它就不会一直跳,让它一个周期内只跳一次
}
void key2_Init()	 //周期加1
{
	if(key2==0)
	{
	delay_ms(100);
	if(key2==0)
	{
		tim0_T+=1000;
	}
	}
}
void key3_Init()	 //周期减1
{
	if(key3==0)
	{
	delay_ms(100);
	if(key3==0)
	{
		if(tim0_T>0)
			tim0_T-=1000;
	}
	}
}
void INT_Init_KEY()	   //外部中断初始化
{
	 EA=1;
	 EX0=1;
	 EX1=1;
	 IT0=1;
	 IT1=1;
	 PX0=1;
	 PX1=1;
}

void INT0_KEY0() interrupt 0	  //外部中断0 服务程序//占空时间加1
{
	delay_ms(10);
	if(key0==0)
	{
		if(tim0_I<tim0_T)
		tim0_I+=10;		
	}
	while(!key0) ;
}
void INT1_KEY1() interrupt 2	  //外部中断1 服务程序//占空时间减1
{
	delay_ms(10);
	if(key1==0)
	{	
		if(tim0_I>0)
		tim0_I-=10;
		
			
	}
	while(!key1) ;
}

我就一小白,不足之处,还请指出。

本文地址:https://blog.csdn.net/weixin_44017446/article/details/85922851

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网