十、PWM脉宽调制信号的发生与控制

调整占空比,脉宽调制作用:

①直流电机的调速

②灯光的控制:亮度

③声音大小

④舵机角度调整

利用PWM脉宽信号实现独立按键S7(J5跳帽2、3)L1指示灯亮度变化的控制。

①PWM脉宽信号的频率为100Hz

②系统上电后L1指示灯处在熄灭状态

③L1指示灯有4种亮度模式,分别是完全熄灭、10%亮度、50%亮度、90%亮度

按下S7按键,循环切换L1指示灯的4种亮度模式 

十、PWM脉宽调制信号的发生与控制

分析:

①100Hz = 0.01s = 10ms = 10000us  (周期为10ms) 

将周期分为100等份 = 100 * 100us(每100us产生一次中断 65535 - 100)

怎样产生60%占空比:60次高电平,40次低电平(设count计数)

十、PWM脉宽调制信号的发生与控制

②系统上电后L1指示灯处在熄灭状态:先产生低电平

1、自己写的代码(按键读取部分有点问题,为什么容易误判?)

#include "reg52.h"

sbit S7 = P3^0;
sbit L1 = P0^0;

sbit HC138_A = P2^5;
sbit HC138_B = P2^6;
sbit HC138_C = P2^7;

void InitHC138()//选LED
{
	HC138_C = 1;
	HC138_B = 0;
	HC138_A = 0;
}

//************定时器相关函数****************************************
unsigned char count = 0;
unsigned char PWM_duty = 0;//PWM占空比
	
void InitTimer0() //中断函数
{
	TMOD = 0x01;
	TH0 = (65535 - 100) / 256; //100Hz = 0.01s = 10ms = 100*100us
	TL0 = (65535 - 100) % 256; //将周期分为100份 = 100us产生一次中断
	
	ET0 = 1;//打开定时器中断
	EA = 1;//打开总中断
	
//TR0 = 1; (启动定时器)先不打开,等需要产生脉宽调制的时候再打开
}

void ServiceTimer0() interrupt 1 //中断服务函数
{
	TH0 = (65535 - 100) / 256; 
	TL0 = (65535 - 100) % 256;//自动重装
	
	count++;
	if (count <= PWM_duty)//计数<=PWM占空比 L1亮
	{
		L1 = 0;
	}
	else if (count < 100)//PWM占空比<计数<100(周期) L1灭
	{
		L1 = 1;
	}
	else if (count == 100)//计数达到一个周期,L1灭,count清零,继续循环
	{
		L1 = 0;
		count = 0;
	}
	
//方法二
//count++;
//if (count == PWM_duty)
//{
//	L1 = 1;
//}
//else if (count == 100)
//{
//	L1 = 0;
//	count = 0;
//}
}

//*****************************************************************


//************按键操作************************************************
void DelayKey(unsigned int t) //按键消抖函数
{
	while(t--);
}

unsigned char flat = 0;//标志位(0时灯灭)

void ScanKeys() //按下S7按键,循环切换L1指示灯的4种亮度模式
{
	if (S7 == 0)
	{
		DelayKey(100);//按键消抖
		if (S7 == 0)
		{
			if (flat == 0)//10%亮度
			{
				L1 = 0;
				TR0 = 1;//启动定时器
				PWM_duty = 10;
				flat = 1;
			}
			else if (flat == 1)//50%亮度
			{
				PWM_duty = 50;
				flat = 2;
			}
			else if (flat == 2)//90%亮度
			{
				PWM_duty = 90;
				flat = 3;
			}
			else if (flat == 3)//灭灯,进入下一次循环
			{
				L1 = 1;
				TR0 = 0;//关闭定时器
				flat = 0;//循环
			}
			while(!S7);//松开后,再进行读取(防止误判)
		}
	}
}
//*******************************************************************

void main()
{
	InitHC138();
	L1 = 1; //系统上电后L1指示灯处在熄灭状态
	InitTimer0();
	while(1)
	{
		ScanKeys();
	}
}

2、标准代码(也有相同情况)

#include "reg52.h"

sbit S7 = P3^0;
sbit L1 = P0^0;

sbit HC138_A = P2^5;
sbit HC138_B = P2^6;
sbit HC138_C = P2^7;

void InitHC138()//选LED
{
	HC138_C = 1;
	HC138_B = 0;
	HC138_A = 0;
}

//************定时器相关函数****************************************
unsigned char count = 0;
unsigned char PWM_duty = 0;//PWM占空比
	
void InitTimer0() //中断函数
{
	TMOD = 0x01;
	TH0 = (65535 - 100) / 256; //100Hz = 0.01s = 10ms = 100*100us
	TL0 = (65535 - 100) % 256; //将周期分为100份 = 100us产生一次中断
	
	ET0 = 1;//打开定时器中断
	EA = 1;//打开总中断
	
//TR0 = 1; (启动定时器)先不打开,等需要产生脉宽调制的时候再打开
}

void ServiceTimer0() interrupt 1 //中断服务函数
{
	TH0 = (65535 - 100) / 256; 
	TL0 = (65535 - 100) % 256;//自动重装
	
	count++;
	if (count <= PWM_duty)//计数<=PWM占空比 L1亮
	{
		L1 = 0;
	}
	else if (count < 100)//PWM占空比<计数<100(周期) L1灭
	{
		L1 = 1;
	}
	else if (count == 100)//计数达到一个周期,L1灭,count清零,继续循环
	{
		L1 = 0;
		count = 0;
	}
	
//方法二
//count++;
//if (count == PWM_duty)
//{
//	L1 = 1;
//}
//else if (count == 100)
//{
//	L1 = 0;
//	count = 0;
//}
}

//*****************************************************************


//************按键操作************************************************
void DelayKey(unsigned int t) //按键消抖函数
{
	while(t--);
}

unsigned char flat = 0;//标志位(0时灯灭)

void ScanKeys() //按下S7按键,循环切换L1指示灯的4种亮度模式
{
	if (S7 == 0)
	{
		DelayKey(100);//按键消抖
		if (S7 == 0)
		{
			switch(flat)
			{
				case 0:  //10%亮度
					L1 = 0;
					TR0 = 1;//启动定时器
					PWM_duty = 10;
					flat = 1;
				break;
				
				case 1:  //50%亮度
					PWM_duty = 50;
					flat = 2;
				break;
				
				case 2:  //90%亮度
					PWM_duty = 90;
					flat = 3;
				break;
				
				case 3:  //灯灭,进入下一次循环
					L1 = 1;
					TR0 = 0;//关闭定时器
					flat = 0;
				break;
			}
			while(!S7);//松开后,再进行读取(防止误判)
		}
	}
}
//*******************************************************************

void main()
{
	InitHC138();
	L1 = 1; //系统上电后L1指示灯处在熄灭状态
	InitTimer0();
	while(1)
	{
		ScanKeys();
	}
}

上一篇:16.15-S7-1200-开关量PWM的方式控制-固态继电器调节水温


下一篇:C51单片机输出pwm信号