ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-02-01 16:35:03  阅读:298  来源: 互联网

标签:count 脉宽调制 HC138 信号 sbit 65535 100 PWM 256


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

①直流电机的调速

②灯光的控制:亮度

③声音大小

④舵机角度调整

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

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

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

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

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

分析:

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

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

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

②系统上电后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();
	}
}

标签:count,脉宽调制,HC138,信号,sbit,65535,100,PWM,256
来源: https://blog.csdn.net/qq_53889131/article/details/122763911

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有