欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

51单片机PWM输出

程序员文章站 2022-06-23 20:57:58
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